Flyout
A full-height overlay panel that slides in from the edge of the viewport. Follows the controlled component pattern — the consumer manages open state and responds to the dismiss event.
Keyboard interaction
| Key | Action |
|---|---|
| Escape | Closes the flyout by emitting the dismiss event. Focus returns to the element that triggered the flyout. |
| Tab / Shift+Tab | Navigates between focusable elements inside the panel. Note: V1 does not implement a full focus trap — Tab can move focus outside the panel. |
| Enter / Space | Activates the focused button (dismiss button, or any interactive element in body/footer slots). |
V1 limitation: A full focus trap (preventing Tab from leaving the panel while open) is not yet implemented. This will be added in V2.
Screen reader behaviour
| Attribute / Property | Value / Behaviour |
|---|---|
role="dialog" | Applied to the panel element. Announces to screen readers that this is a dialog region. |
aria-modal="true" | Signals that the dialog is modal, so screen reader virtual cursors are restricted to the dialog content. |
aria-label | Set to the heading prop value (falls back to "Flyout"). Provides an accessible name for the dialog. |
aria-hidden="true" (backdrop) | The backdrop div is hidden from assistive technologies — it exists as a click target only. |
Focus management
- Opening: When open changes to true, the panel element receives programmatic focus via requestAnimationFrame. This ensures the focus shift happens after the CSS transition begins, so screen readers announce the dialog correctly.
- Closing: When the flyout closes, focus is returned to the element that was focused immediately before the flyout opened (the trigger element). This satisfies WCAG 2.4.3 Focus Order.
- Body scroll lock: While open, document.body overflow is set to hidden so background content cannot be scrolled. This is restored on close or when the component is disconnected from the DOM.
WCAG 2.2 compliance
role="dialog" and aria-modal convey the flyout structure semantically.
Escape closes the flyout and the dismiss button is keyboard-operable.
V1 has no full focus trap, so Tab can exit the panel. This is documented and targeted for V2.
prefers-reduced-motion disables panel and backdrop transitions.
Focus moves to the panel on open and returns to the trigger on close.
aria-label provides an accessible name and role="dialog" is applied correctly.
Best practices
- Reduced motion — all CSS transitions inside the shadow DOM respond to
prefers-reduced-motion: reduceand are suppressed automatically. - Trigger context — ensure the element that opens the flyout is a button or has
role="button"so screen readers announce the open affordance correctly. - Slotted content — provide a meaningful
headingslot; it becomes the accessible name of the dialog viaaria-labelledbyand helps users understand the panel's purpose.