lit / lit/lit

Animation in module is not defined

Open
#4,072 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

More Info Needed
Dominant language
TypeScript
Stars
21.8k
Forks
1.1k
Avg merge
18h 25m
Merged PRs (30d)
2

Description

### Which package(s) are affected?

Lit Core (lit / lit-html / lit-element / reactive-element)

### Description

In some instances, animation will be undefined when used in a css module. I say some instances, because it is not 100% consistent and only happens on some of my custom elements and the logic is the same as the custom elements it does work in.(meaning there is nothing specific to do to reproduce it)

Note: in this instance, the `fadeoutother` animation is the one not defined

**Here it is working successfully when animation is not in css module**

```js
% cat elements/sort-dialog.js
import {
LitElement,
html,
css,
} from 'lit';
import '@material/mwc-tab-bar';
import '@material/mwc-tab';
import {
hideHostFade,
fadeinother,
} from '../common-styles.js';
import '@material/mwc-radio';
import { AnimationMixin } from '../mixins/animations-mixin.js';

export class SortDialog extends AnimationMixin(LitElement) {
static styles = [
hideHostFade,
fadeinother,
css`
:host([active]) {
display: flex;
}

:host([fadeoutother]) {
animation: fadeoutother 150ms ease-in-out forwards;
}

@keyframes fadeoutother {
0% {
visibility: visible;
opacity: 1;
}

100% {
visibility: hidden;
opacity: 0;
}
}

.body {
background-color: white;
width: 50%;
height: 50%;
margin: auto;
padding: 24px;
}
`,
];

static properties = {
};

constructor() {
super();
this.addEventListener('click', (e) => {
const { localName } = e.composedPath()[0];

if (localName === 'sort-dialog') {
this.setAttribute('fadeoutother', "");
}
});
}

render() {
return html`


Sorty by















`
}

_dispatchEvent() {
const opts = { bubbles: true };
this.dispatchEvent(new CustomEvent('sort-by-changed'));
}

changeRadio(e) {
const { value } = e.target.dataset;
localStorage.setItem("sortBy", value);
this.setAttribute('fadeoutother', "");
this._dispatchEvent();
}

getRadioValue(type) {
const storeValue = localStorage.getItem('sortBy') || 'date';
if (storeValue === type) {
return true;
}
return false;
}

connectedCallback() {
super.connectedCallback();
this._setEventToLeave('fadeoutother');
}

}

window.customElements.define('sort-dialog', SortDialog);
```
![image](https://github.com/lit/lit/assets/887815/4b4d4e29-2116-43ec-9b7e-06abfd012009)

--------------------------------------------------------------------------------

**Here it is not working:**

```js
% cat elements/sort-dialog.js
import {
LitElement,
html,
css,
} from 'lit';
import '@material/mwc-tab-bar';
import '@material/mwc-tab';
import {
hideHostFade,
fadeoutother,
fadeinother,
} from '../common-styles.js';
import '@material/mwc-radio';
import { AnimationMixin } from '../mixins/animations-mixin.js';

export class SortDialog extends AnimationMixin(LitElement) {
static styles = [
hideHostFade,
fadeoutother,
fadeinother,
css`
:host([active]) {
display: flex;
}

.body {
background-color: white;
width: 50%;
height: 50%;
margin: auto;
padding: 24px;
}
`,
];

static properties = {
};

constructor() {
super();
this.addEventListener('click', (e) => {
const { localName } = e.composedPath()[0];

if (localName === 'sort-dialog') {
this.setAttribute('fadeoutother', "");
}
});
}

render() {
return html`


Sorty by















`
}

_dispatchEvent() {
const opts = { bubbles: true };
this.dispatchEvent(new CustomEvent('sort-by-changed'));
}

changeRadio(e) {
const { value } = e.target.dataset;
localStorage.setItem("sortBy", value);
this.setAttribute('fadeoutother', "");
this._dispatchEvent();
}

getRadioValue(type) {
const storeValue = localStorage.getItem('sortBy') || 'date';
if (storeValue === type) {
return true;
}
return false;
}

connectedCallback() {
super.connectedCallback();
this._setEventToLeave('fadeoutother');
}

}

window.customElements.define('sort-dialog', SortDialog);
```

```css
% cat common-styles.js
import { css } from 'lit';

const misc = css`
.blue-button {
color: white;
background-color: blue;
}

.blue-button:disabled {
background-color: grey;
}

ul {
list-style-type: none;
padding: 0;
}

svg {
fill: #686869;
}

.star-filled-icon {
fill: #00668c;
}

.btn-1 {
border-radius: 28px;
height: 40px;
border: none;
font-family: 'Roboto';
padding: 0 24px 0;
}
`;

const overlay = css`
.overlay {
position: relative;
height: 100vh;
width: 100%;
top: 0;
bottom: 0;
}
`;

const hideHostFade = css`
:host {
background: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
visibility: hidden;
opactiy: 0;
}
`;

const hideHost = css`
:host {
background: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
margin-top: 100vh;
}
`;

const fadeout = css`
:host([fadeout]) {
animation: fadeout 150ms ease-in-out forwards;
}

@keyframes fadeout {
0% {
visibility: visible;
opacity: 1;
}

100% {
visibility: hidden;
opacity: 0;
}
}
`;

const fadeoutother = css`
:host([fadeoutother]) {
animation: fadeoutother 150ms ease-in-out forwards;
}

@keyframes fadeoutother {
0% {
visibility: visible;
opacity: 1;
}

100% {
visibility: hidden;
opacity: 0;
}
}
`;

const fadeinother = css`
:host([fadeinother]) {
animation: fadeinother 150ms ease-in-out forwards 50ms;
}

@keyframes fadeinother {
0% {
visibility: visible;
opacity: 0;
}

100% {
visibility: visible;
opacity: 1;
}
}
`;

const pageTransitionStyles = css`
:host([active]) {
display: block;
}

:host([riseup]) {
display: block;
animation: riseup 125ms ease-in-out forwards 50ms;
}

:host([fadein]) {
animation: fadein 150ms ease-in-out forwards 50ms;
}

:host([slidedown]) {
margin-top: 0;
animation: slidedown 150ms ease-in-out forwards 50ms;
}

@keyframes riseup {
0% {
margin-top: 100vh;
}

100% {
margin-top: 0;
}
}

@keyframes slidedown {
0% {
margin-top: 0;
}

100% {
margin-top: 100vh;
}
}
`;

export {
pageTransitionStyles,
misc,
overlay,
hideHost,
hideHostFade,
fadeout,
fadeoutother,
fadeinother,
};
```

![image](https://github.com/lit/lit/assets/887815/413d1d58-fa7a-4904-9fb2-401619a0f5bd)

### Reproduction

na

### Workaround

do not use animation in module, use it in component instead

### Is this a regression?

No or unsure. This never worked, or I haven't tried before.

### Affected versions

2.7.4

### Browser/OS/Node environment

```
% node --version
v18.10.0

% npm list | grep -i lit
├── lit-analyzer@1.2.1
├── lit@2.7.4

% google-chrome-stable --version
Google Chrome 115.0.5790.110

% uname -a
Linux localhost 5.4.0-153-generic #170-Ubuntu SMP Fri Jun 16 13:43:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by comparing the two examples in elements/sort-dialog.js and common-styles.js, then inspect the relevant CSS module handling for keyframes. Reproduce the difference between inline and imported fadeoutother styles, and add a regression test that captures the failing case. Done means the imported animation is defined and the test passes.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, javascript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.