Accessibility
Keyboard navigation, focus management, accessible labels, motion preferences, and contrast checks.
Onset provides focus indicators, keyboard handlers, and accessibility attributes for its components. Application code supplies labels, content, and focus behavior for custom compositions. Component references document individual keyboard patterns and limitations.
Keyboard & focus
Native buttons and inputs use browser keyboard behavior. Components such as
Tabs, Carousel, and SplitPane add the keyboard interactions documented on
their reference pages. TreeView and MiniCalendar use Tab navigation without
arrow-key navigation.
Focus rings
Focus styles use --m-focus-outline, --m-focus-offset, and
--m-focus-ring CSS variables.
--m-focus-outlinedraws outside the border. Ancestors withoverflow: hiddencan clip the outline.--m-focus-ringand--m-focus-ring-insetuse box shadows within the element's bounds. These styles are used in clipped or scrolling regions.
Focus trapping
Modal and Drawer use Dialog to trap focus while open.
Popover provides positioning without a focus trap.
useFocusTrap moves initial focus into a container,
wraps Tab navigation at its boundaries, and attempts to restore the previously
focused element on cleanup. initialFocusRef selects the initial target.
Set autoFocus or restoreFocus to false to disable the corresponding behavior.
Scroll locking
useScrollLock sets overflow: hidden on
document.body while enabled and restores scrolling on cleanup.
Dialog includes scroll locking.
Scrolling regions
ScrollArea adds its viewport to the tab order while content overflows.
Carousel handles arrow keys, Home, and End on its track.
Resizable panes
Each SplitPane divider has role="separator" and reports the leading panel's
share through aria-valuenow. Arrow keys resize by step percentage points.
Home and End select the size limits. Enter toggles a collapsible panel.
Dismissal
useDismiss calls onDismiss for Escape and pointer
presses outside the elements listed in ignoreRefs.
import { useRef } from "react";
import { useDismiss, useFocusTrap } from "@solarius/onset";
function CustomOverlay({
open,
onClose,
}: {
open: boolean;
onClose: () => void;
}) {
const panelRef = useRef<HTMLDivElement>(null);
useDismiss({ enabled: open, ignoreRefs: [panelRef], onDismiss: onClose });
useFocusTrap({ enabled: open, containerRef: panelRef });
return open ? (
<div ref={panelRef} role="dialog" aria-modal="true" aria-label="Details">
<button onClick={onClose}>Close</button>
</div>
) : null;
}Include a trigger ref in ignoreRefs when trigger presses should not dismiss
an open overlay.
Screen readers
VisuallyHidden
VisuallyHidden hides text visually while retaining the text in the accessibility
tree. Use the component to label controls that have no visible text.
import { VisuallyHidden } from "@solarius/onset";
<button type="button">
<VisuallyHidden>Close dialog</VisuallyHidden>
<span aria-hidden="true">×</span>
</button>;Icons
Icon forwards SVG attributes to the supplied icon component. Set
aria-hidden="true" on decorative icons. Label icon-only buttons with
aria-label or visually hidden text.
Form validation
Field passes its error state to nested controls for invalid styling.
ValidationMessage renders role="alert" for errors and role="status" for
other tones. Associate descriptions with inputs through matching id and
aria-describedby attributes in custom layouts.
Color contrast
Theme configuration changes generated foreground and background colors.
Verify the color pairs used by the application after changing baseColor,
status colors, or surface styles. WCAG AA requires a contrast ratio of 4.5:1
for normal text and 3:1 for large text.
Status colors use per-mode values unless overridden through theme configuration. Do not rely on color alone to communicate status. Include a label or another visible indicator.
Accessibility support
Custom compositions require application-level checks:
- Label controls and associate field descriptions and errors.
- Check keyboard navigation and focus restoration after closing overlays or removing content.
- Verify contrast for the actual foreground and background pairs.
- Keep required actions available without hover or pointer dragging.
Motion preferences
Skeleton disables animation under prefers-reduced-motion.
Carousel stops automatic advancement and smooth scrolling. Spinner uses
an opacity pulse instead of rotation. Use
useReducedMotion for custom animations.