What
Overlay/animated components in @wordpress/ui currently express the same opacity fade in two different, mutually-inverse ways. We should standardise on a single canonical pattern (potentially centralised in a shared utility) so every component fades in/out identically and the intent is obvious.
This was surfaced in review on #78885 (r3387360744) and flagged again as a follow-up in r3382084439.
Why
The two patterns are functionally equivalent, but the inconsistency makes the code harder to read, harder to keep in sync, and easy to get subtly wrong (e.g. forgetting a :not([data-ending-style]) guard, which previously caused the Popover backdrop to snap in on mount). A single shared approach reduces drift and makes future overlay work copy-pasteable with confidence.
Current state
There are two opposite directions in use:
Pattern A — "hidden by default, reveal when open" (used by the dropdown motion util and Popover):
.dropdown-motion {
/* ... */
opacity: 0;
/* ... */
&[data-open]:not([data-starting-style]) {
opacity: 1;
transform: translate(0);
}
}
.backdrop {
/* ... */
opacity: 0;
&[data-open]:not([data-starting-style]):not([data-ending-style]) {
opacity: 1;
}
}
Pattern B — "visible by default, hide during transition states" (used by Dialog and Drawer):
.backdrop {
/* ... */
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
}
&[data-open] {
opacity: 1;
}
}
Note that even within Pattern A the two usages aren't identical: dropdown-motion guards only :not([data-starting-style]), while the Popover backdrop adds :not([data-ending-style]).
Inventory
| File |
Element |
Pattern |
Property |
utils/css/dropdown-motion.module.css |
.dropdown-motion |
A |
opacity + transform |
utils/css/item-popup.module.css |
.popup |
A (via composes) |
opacity + transform |
popover/style.module.css |
.popup (via composes) |
A |
opacity + transform |
popover/style.module.css |
.backdrop |
A (with extra guard) |
opacity |
dialog/style.module.css |
.popup, .backdrop |
B |
opacity + transform |
drawer/style.module.css |
.popup, .backdrop, etc. |
B |
opacity + transform |
collapsible-card/style.module.css |
.panel |
B-style |
height (not opacity) |
Proposal / desired outcome
- Pick one canonical direction for opacity fades and apply it everywhere.
- Normalise the state guards so all usages match (consistent handling of
[data-starting-style] / [data-ending-style]).
- Keep
collapsible-card in mind as part of the broader "unify transition approaches" effort, even though it animates height rather than opacity.
Open questions
- Which direction wins? Pattern A (
opacity: 0 default + reveal on open) vs. Pattern B (opacity: 1 default + hide in transition states). Worth confirming whether one interacts better with Base UI's mount/data-starting-style timing.
Scope
CSS-only consistency change across @wordpress/ui overlay components; no public component API changes expected.
What
Overlay/animated components in
@wordpress/uicurrently express the same opacity fade in two different, mutually-inverse ways. We should standardise on a single canonical pattern (potentially centralised in a shared utility) so every component fades in/out identically and the intent is obvious.This was surfaced in review on #78885 (r3387360744) and flagged again as a follow-up in r3382084439.
Why
The two patterns are functionally equivalent, but the inconsistency makes the code harder to read, harder to keep in sync, and easy to get subtly wrong (e.g. forgetting a
:not([data-ending-style])guard, which previously caused the Popover backdrop to snap in on mount). A single shared approach reduces drift and makes future overlay work copy-pasteable with confidence.Current state
There are two opposite directions in use:
Pattern A — "hidden by default, reveal when open" (used by the dropdown motion util and Popover):
Pattern B — "visible by default, hide during transition states" (used by Dialog and Drawer):
Note that even within Pattern A the two usages aren't identical:
dropdown-motionguards only:not([data-starting-style]), while the Popover backdrop adds:not([data-ending-style]).Inventory
utils/css/dropdown-motion.module.css.dropdown-motionutils/css/item-popup.module.css.popupcomposes)popover/style.module.css.popup(viacomposes)popover/style.module.css.backdropdialog/style.module.css.popup,.backdropdrawer/style.module.css.popup,.backdrop, etc.collapsible-card/style.module.css.panelProposal / desired outcome
[data-starting-style]/[data-ending-style]).collapsible-cardin mind as part of the broader "unify transition approaches" effort, even though it animatesheightrather than opacity.Open questions
opacity: 0default + reveal on open) vs. Pattern B (opacity: 1default + hide in transition states). Worth confirming whether one interacts better with Base UI's mount/data-starting-styletiming.Scope
CSS-only consistency change across
@wordpress/uioverlay components; no public component API changes expected.