Skip to content

Commit eee4557

Browse files
Merge pull request #771 from thejackshelton/popover-attributes
popover data attribute refactor
2 parents bf763a4 + 2f48ecd commit eee4557

File tree

4 files changed

+44
-47
lines changed

4 files changed

+44
-47
lines changed

apps/website/src/routes/docs/headless/popover/index.mdx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ Entry and exit animations have often been a frustrating experience in web develo
143143

144144
Until recently, discrete properties were not animatable. Luckily, there's [new properties to CSS](https://developer.chrome.com/blog/entry-exit-animations) that solve this problem.
145145

146-
The browser support for these is similar to support of the popover API. That said, the Qwik UI team has done an awesome job of managing animations on polyfill browsers for you using the `popover-showing` and `popover-closing` classes.
146+
The browser support for these is similar to support of the popover API. That said, the Qwik UI team has done an awesome job of managing animations on polyfill browsers for you using the `data-open` and `data-closing` attributes.
147147

148148
```css
149149
.my-transition {
@@ -159,11 +159,11 @@ The browser support for these is similar to support of the popover API. That sai
159159
opacity: 0;
160160
}
161161

162-
.popover-showing {
162+
.my-transition[data-open] {
163163
opacity: 1;
164164
}
165165

166-
.popover-closing {
166+
.my-transition[data-closing] {
167167
opacity: 0;
168168
}
169169
```
@@ -333,9 +333,9 @@ We put it under an `@layer` so that it can be easily overridden when adding your
333333

334334
To use an animation, add the following CSS classes to the component.
335335

336-
- The `.popover-showing` class determines the animation that happens when it is first opened.
336+
- The `data-open` attribute determines the animation that happens when it is first opened.
337337

338-
- The `.popover-closing` class determines what class is added when the listbox is **closed**.
338+
- The `data-closing` class determines what class is added when the listbox is **closed**.
339339

340340
Here's the CSS imported from the example:
341341

@@ -344,11 +344,11 @@ Here's the CSS imported from the example:
344344
transform: scale(0);
345345
}
346346

347-
.popover-animation.popover-showing {
347+
.popover-animation[data-open] {
348348
animation: popover-grow 0.5s ease-in-out forwards;
349349
}
350350

351-
.popover-animation.popover-closing {
351+
.popover-animation[data-closing] {
352352
animation: popover-shrink 0.4s ease-in-out forwards;
353353
}
354354

@@ -377,7 +377,7 @@ Here's the CSS imported from the example:
377377
378378
### Transition declarations
379379

380-
Transitions use the same classes for entry and exit animations. Those being `.popover-showing` and `.popover-closing`. They are explained more in the `Caveats` section.
380+
Transitions use the same classes for entry and exit animations. Those being `data-open` and `data-closing`. They are explained more in the `Caveats` section.
381381

382382
<Showcase name="transition" />
383383

@@ -395,11 +395,11 @@ CSS from the example:
395395
transition-behavior: allow-discrete;
396396
}
397397

398-
.popover-transition.popover-showing {
398+
.popover-transition[data-open] {
399399
opacity: 1;
400400
}
401401

402-
.popover-transition.popover-closing {
402+
.popover-transition[data-closing] {
403403
opacity: 0;
404404
}
405405
```
@@ -461,19 +461,19 @@ To read more about the popover API you can check it out on:
461461
description: 'Style the element when the popover is open.',
462462
},
463463
{
464-
name: '.popover-open',
465-
type: 'class',
466-
description: 'Polyfill class added to style unsupported browsers.',
464+
name: 'data-closing',
465+
type: 'selector',
466+
description: 'Style the element when the popover is closing.',
467467
},
468468
{
469-
name: '.popover-showing',
470-
type: 'class',
471-
description: 'Class to animate entry behavior.',
469+
name: 'data-closed',
470+
type: 'selector',
471+
description: 'Style the element when the popover is closed.',
472472
},
473473
{
474-
name: '.popover-closing',
474+
name: 'data-closing',
475475
type: 'class',
476-
description: 'Class to animate close behavior.',
476+
description: 'Class to animate exit behavior.',
477477
},
478478
]}
479479
/>

apps/website/src/routes/docs/headless/popover/snippets/popover.css

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,23 @@
3939
transition-behavior: allow-discrete;
4040
}
4141

42-
.popover-transition.popover-showing {
42+
.popover-transition[data-open] {
4343
opacity: 1;
4444
}
4545

46-
.popover-transition.popover-closing {
46+
.popover-transition[data-closing] {
4747
opacity: 0;
4848
}
4949

5050
.popover-animation {
5151
transform: scale(0);
5252
}
5353

54-
.popover-animation.popover-showing {
54+
.popover-animation[data-open] {
5555
animation: popover-grow 0.5s ease-in-out forwards;
5656
}
5757

58-
.popover-animation.popover-closing {
58+
.popover-animation[data-closing] {
5959
animation: popover-shrink 0.4s ease-in-out forwards;
6060
}
6161

packages/kit-headless/src/components/popover/popover-panel-impl.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ export const HPopoverPanelImpl = component$((props: PropsOf<'div'>) => {
105105
id={panelId}
106106
ref={props.ref}
107107
data-open={context.isOpenSig.value ? '' : undefined}
108-
data-closed={!context.isOpenSig.value ? '' : undefined}
109108
popover={
110109
(context.manual && 'manual') || props.popover === 'manual'
111110
? 'manual'
@@ -116,7 +115,7 @@ export const HPopoverPanelImpl = component$((props: PropsOf<'div'>) => {
116115
if (!context.panelRef?.value) return;
117116

118117
if (e.newState === 'open' && context.panelRef.value) {
119-
supportShowAnimation(context.panelRef.value, isPolyfillSig.value);
118+
await supportShowAnimation(context.panelRef.value, isPolyfillSig.value);
120119
}
121120
if (e.newState === 'closed') {
122121
supportClosingAnimation(context.panelRef.value);

packages/kit-headless/src/components/popover/utils.ts

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,46 @@
44
/**
55
* Adds CSS-Class to support popover-opening-animation
66
*/
7-
export function supportShowAnimation(popover: HTMLElement, isPolyfill: boolean) {
7+
export async function supportShowAnimation(popover: HTMLElement, isPolyfill: boolean) {
88
const { transitionDuration } = getComputedStyle(popover);
99

10-
if (isPolyfill) {
11-
// polyfill needs a bit of extra time to execute
12-
if (transitionDuration !== '0s') {
13-
setTimeout(() => {
14-
popover.classList.add('popover-showing');
15-
popover.classList.remove('popover-closing');
16-
}, 10);
17-
} else {
18-
popover.classList.add('popover-showing');
19-
popover.classList.remove('popover-closing');
20-
}
21-
} else {
22-
if (transitionDuration !== '0s') {
23-
setTimeout(() => {
24-
popover.classList.add('popover-showing');
25-
popover.classList.remove('popover-closing');
26-
}, 5);
27-
} else {
28-
popover.classList.add('popover-showing');
29-
popover.classList.remove('popover-closing');
30-
}
10+
async function delay(ms: number): Promise<void> {
11+
return new Promise((resolve) => setTimeout(resolve, ms));
3112
}
13+
14+
const delayTime = isPolyfill ? 10 : 5;
15+
16+
if (transitionDuration !== '0s') {
17+
await delay(delayTime);
18+
}
19+
20+
popover.classList.add('popover-showing');
21+
popover.classList.remove('popover-closing');
22+
popover.removeAttribute('data-closing');
23+
popover.removeAttribute('data-closed');
3224
}
3325

3426
/**
3527
* Listens for animation/transition events in order to
3628
* remove Animation-CSS-Classes after animation/transition ended.
37-
* export function supportClosingAnimation(popover: HTMLElement, afterAnimate: () => void) {
3829
*/
3930
export function supportClosingAnimation(popover: HTMLElement) {
4031
popover.classList.remove('popover-showing');
4132
popover.classList.add('popover-closing');
33+
popover.dataset.closing = '';
4234

4335
const { animationDuration, transitionDuration } = getComputedStyle(popover);
4436

4537
const runAnimationEnd = () => {
4638
popover.classList.remove('popover-closing');
39+
popover.removeAttribute('data-closing');
40+
popover.dataset.closed = '';
4741
};
4842

4943
const runTransitionEnd = () => {
5044
popover.classList.remove('popover-closing');
45+
popover.removeAttribute('data-closing');
46+
popover.dataset.closed = '';
5147
};
5248

5349
if (animationDuration !== '0s') {
@@ -56,5 +52,7 @@ export function supportClosingAnimation(popover: HTMLElement) {
5652
popover.addEventListener('transitionend', runTransitionEnd, { once: true });
5753
} else {
5854
popover.classList.remove('popover-closing');
55+
popover.removeAttribute('data-closing');
56+
popover.dataset.closed = '';
5957
}
6058
}

0 commit comments

Comments
 (0)