P-07 · Primitives · Primitives
All elements · Transition on the Primitives page
Last checked 2026-10-22 · Awaiting approval · Accessibility tests
Approve Transition
Approving as
Enter/exit presets driven by data-state, plus keyframe classes for elements that mount
already open. Honors prefers-reduced-motion globally.
| Axis | Values |
|---|---|
data-preset |
fade · scale · slide-up · slide-down · slide-left · slide-right · collapse |
data-state · data-speed |
open · closed / fast · slow |
.qf-enter-* |
one-shot mount animations with the same names |
Guidance
When to use
-
Animate a popover, menu or dialog panel in and out with
data-presetanddata-state. - Collapse or expand a section with the
collapsepreset. -
Slide a drawer or detail pane in from an edge with
slide-leftorslide-right. -
Play a one-time entrance on an element that mounts already open with a
.qf-enter-*class.
When to consider something else
- When content expands under a header with its own button and state, use Accordion. See Accordion.
- When you need a floating panel, not just its motion, use Layer or the Overlay system and add Transition to it. See OverlaySystem.
- When you need to show ongoing work, use Progress or Skeleton rather than a looping animation. See Progress.
Usability
-
Keep motion short; use
data-speed="fast"for small menus and the default for panels. - Use motion that matches the direction of the change, such as a drawer sliding from its own edge.
-
Pair a closed panel with
hiddenorinertonce the exit finishes so it leaves the tab order. - Use
collapseonly for content with a sensible maximum height.
- Don't use motion as the only sign that something changed.
- Don't animate frequent updates such as table rows on every refresh.
- Don't chain several presets on one change.
Accessibility
Keyboard
No keyboard interaction of its own.
Roles and names
-
Transition adds no role or state. The animated element keeps its own semantics, such as
aria-expandedon the trigger of a collapsed region. -
The
closedstate only sets opacity, transform ormax-height; it does not hide content from assistive technology. The binding must addhidden,inertoraria-hiddenwhen the content is meant to be gone.
Focus
- Content that is visually closed but still in the DOM can still receive focus; remove it from the tab order when closed.
- Move focus only after an entering panel is in place, so focus is not drawn off-screen.
Other requirements
- Transition has no keyboard behavior of its own.
-
base.csshonorsprefers-reduced-motion: reduceglobally by cutting transition and animation durations to near zero (2.3.3). - No preset flashes; keep it that way (2.3.1).
-
Content revealed by
collapsemust not be clipped at 200% zoom;max-heightis100vh(1.4.4, 1.4.10).
Test your implementation too. This guidance covers the element as specified here. How a screen composes it (labels, order, announcements) still needs its own keyboard and screen reader check.
Accessibility tests
Passed the gate (run 358b316 on 2026-10-22): no finding in any theme. Awaiting a person’s approval of the checklist below.
| Area | Automated | A person checks |
|---|---|---|
| General | Passed | Color is never the only cue, text alternatives say the same thing as the graphic, and the element reads the same in the light and the dark theme. |
| Zoom | Passed | At 200% zoom, at 320 CSS pixels wide and with the WCAG text-spacing overrides, nothing is lost, clipped or overlapping. |
| Keyboard | Passed | Every row of the Keyboard table works, focus is always visible and never trapped, and the tab order follows the reading order. |
| Screen reader | Passed | With NVDA or JAWS on Windows and VoiceOver on macOS, names, roles and states are announced as Roles and names says, and changes are announced once. (2 items) |
Approving. When the checklist passes on the checked run, record it with
bun run a11y:approve -- transition --by "Your name" and commit
a11y/approvals.json with the rebuilt pages.
All test status
Package
Consumers link one stylesheet, css/classic/index.css, which includes every element. The
files below are where this element is defined.
Latest updates
No recorded changes yet.