Skip to content

Commit 87b7cd5

Browse files
committed
fix(accordion): work with normalize css
Fixes #1914
1 parent e908d67 commit 87b7cd5

File tree

7 files changed

+65
-46
lines changed

7 files changed

+65
-46
lines changed

.changeset/eight-spiders-brake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@patternfly/pfe-accordion": patch
3+
---
4+
5+
Fix #1914: `<pfe-accordion>` on a page with CSS normalize

.changeset/three-owls-add.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@patternfly/pfe-sass": major
3+
---
4+
5+
Removed `pfe-collapsible` mixin. See `pfe-accordion-panel.scss` for implementation.

core/pfe-sass/mixins/_containers.scss

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,6 @@
3030
}
3131
}
3232

33-
@mixin pfe-collapsible($state: closed) {
34-
@if $state != closed {
35-
display: block;
36-
position: relative;
37-
opacity: 1;
38-
} @else {
39-
display: none;
40-
overflow: hidden;
41-
will-change: height;
42-
border-color: transparent;
43-
opacity: 0;
44-
}
45-
}
46-
4733
/// Accent bar styles
4834
@mixin accent-bar(
4935
$direction: horizontal,

elements/pfe-accordion/demo/pfe-accordion.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<link href="/elements/pfe-accordion/demo/demo.css" rel="stylesheet">
1+
<link rel="stylesheet" href="/elements/pfe-accordion/demo/demo.css">
22

33
<pfe-band id="context-band" class="contextual" color="lightest" use-grid full-width aside-height="full" aside-mobile="top">
44
<pfe-jump-links-nav slot="aside" autobuild id="context" style="position: sticky; top: 0;">

elements/pfe-accordion/pfe-accordion-panel.scss

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
:host {
1818
@include pfe-box-sizing;
19-
@include pfe-collapsible($state: closed);
20-
19+
display: none;
20+
overflow: hidden;
21+
will-change: height;
22+
border-color: transparent;
23+
opacity: 0;
24+
2125
// relative prevents the left border overflow
2226
position: relative;
2327
box-sizing: border-box;
@@ -108,11 +112,17 @@
108112
opacity: 1;
109113
}
110114

115+
:host(.animating[hidden]),
111116
:host([expanded]:not(.animating)) {
112-
overflow: visible;
113117
margin-bottom: 0;
114118
border-bottom-width: pfe-local(BorderWidth);
115-
@include pfe-collapsible($state: open);
119+
display: block !important;
120+
position: relative;
121+
opacity: 1;
122+
}
123+
124+
:host([expanded]:not(.animating)) {
125+
overflow: visible;
116126
}
117127

118128
@include pfe-accordion--expanded();

elements/pfe-accordion/pfe-accordion-panel.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { LitElement, html } from 'lit';
22
import { customElement, property } from 'lit/decorators.js';
33

4-
import { observed, pfelement } from '@patternfly/pfe-core/decorators.js';
4+
import { pfelement } from '@patternfly/pfe-core/decorators.js';
55
import { getRandomId } from '@patternfly/pfe-core/functions/random.js';
66

77
import { PfeCollapsePanel } from '@patternfly/pfe-collapse/pfe-collapse-panel.js';
@@ -26,7 +26,6 @@ export class PfeAccordionPanel extends LitElement {
2626
/** Disclosure */
2727
@property({ type: String, reflect: true }) disclosure?: 'true'|'false';
2828

29-
@observed
3029
@property({ type: Boolean, reflect: true }) expanded = false;
3130

3231
@property({ attribute: 'aria-labelledby', reflect: true }) ariaLabelledby?: string;
@@ -46,10 +45,6 @@ export class PfeAccordionPanel extends LitElement {
4645
</div>
4746
`;
4847
}
49-
50-
protected _expandedChanged() {
51-
this.hidden = !this.expanded;
52-
}
5348
}
5449

5550
declare global {

elements/pfe-accordion/pfe-accordion.ts

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ export class AccordionCollapseEvent extends ComposedEvent {
4242
}
4343
}
4444

45+
const CSS_TIMING_UNITS_RE = /(?<value>[0-9.]+)(?<unit>[a-zA-Z]+)/g;
46+
4547
/**
4648
* Accordions toggle the visibility of sections of content.
4749
* They feature panels that consist of a section text label and a caret icon that collapses or expands to reveal more information.
@@ -214,6 +216,10 @@ export class PfeAccordion extends LitElement {
214216

215217
private logger = new Logger(this);
216218

219+
private styles = getComputedStyle(this);
220+
221+
private transitionDuration = this.getAnimationDuration();
222+
217223
connectedCallback() {
218224
super.connectedCallback();
219225
this.addEventListener('change', this._changeHandler as EventListener);
@@ -286,6 +292,7 @@ export class PfeAccordion extends LitElement {
286292
}
287293

288294
panel.expanded = true;
295+
panel.hidden = false;
289296

290297
await panel.updateComplete;
291298

@@ -318,29 +325,49 @@ export class PfeAccordion extends LitElement {
318325
const rect = panel.getBoundingClientRect();
319326

320327
panel.expanded = false;
328+
panel.hidden = true;
321329

322330
this._animate(panel, rect.height, 0);
323331
}
324332

333+
private getAnimationDuration() {
334+
if ('computedStyleMap' in this) {
335+
// @ts-expect-error: https://caniuse.com/?search=computedStyleMap
336+
return this.computedStyleMap().get('transition-duration')?.to('ms').value;
337+
} else {
338+
const { transitionDuration } = this.styles;
339+
const groups = CSS_TIMING_UNITS_RE.exec(transitionDuration)?.groups;
340+
if (!groups) {
341+
return null;
342+
}
343+
const factor = groups.unit === 's' ? 1000 : 1;
344+
return parseFloat(groups.value) * factor;
345+
}
346+
}
347+
325348
private async _animate(panel: PfeAccordionPanel, start: number, end: number) {
326349
if (panel) {
327350
const header = panel.previousElementSibling;
328-
if (header) {
329-
header.classList.add('animating');
351+
352+
const transitionDuration = this.getAnimationDuration();
353+
if (transitionDuration) {
354+
this.transitionDuration = transitionDuration;
330355
}
331356

357+
const duration = this.transitionDuration;
358+
359+
header?.classList.add('animating');
332360
panel.classList.add('animating');
333-
panel.style.height = `${start}px`;
334361

335-
// panel.animate({ height: [`${start}px`, `${end}px`] }).play();
362+
const animation = panel.animate({ height: [`${start}px`, `${end}px`] }, { duration });
363+
animation.play();
364+
await animation.finished;
365+
366+
header?.classList.remove('animating');
367+
panel.classList.remove('animating');
336368

337-
// TODO: use Element#animate
338-
requestAnimationFrame(() => {
339-
requestAnimationFrame(() => {
340-
panel.style.height = `${end}px`;
341-
panel.addEventListener('transitionend', this._transitionEndHandler, { once: true });
342-
});
343-
});
369+
panel.style.removeProperty('height');
370+
panel.hidden = !panel.expanded;
344371
}
345372
}
346373

@@ -380,16 +407,6 @@ export class PfeAccordion extends LitElement {
380407
newHeader?.focus?.();
381408
}
382409

383-
@bound private _transitionEndHandler(evt: TransitionEvent) {
384-
const panel = evt.target as PfeAccordionPanel;
385-
const header = panel.previousElementSibling;
386-
if (header) {
387-
header.classList.remove('animating');
388-
}
389-
panel.style.removeProperty('height');
390-
panel.classList.remove('animating');
391-
}
392-
393410
private _allHeaders(): PfeAccordionHeader[] {
394411
return Array.from(this.children).filter(PfeAccordion.isHeader);
395412
}
@@ -532,6 +549,7 @@ export class PfeAccordion extends LitElement {
532549
if (panel) {
533550
header.setAttribute('aria-controls', panel.id);
534551
panel.setAttribute('aria-labelledby', header.id);
552+
panel.hidden = !panel.expanded;
535553
}
536554
});
537555

0 commit comments

Comments
 (0)