Focus
Keyboard focus stays visible on both theme canvases and uses the shared ring tokens. Focus should not depend on hover or on a change of color alone.
Contrast
Check the real light and dark surfaces, not only isolated swatches. Status colors include text, background, and border roles so color is not the only signal.
--color-text-primary on --color-bg-surface
Use only where the surrounding context carries the hierarchy.
Do not use disabled contrast for content that a person still needs to read.
Scrollbars
The document viewport keeps the platform scrollbar. Bounded regions opt into scrollbar-hover-reveal from packages/ui/src/styles/base.css: the thumb is visually hidden until pointer hover, keyboard focus within the region, or active interaction.
- Keep a scroll region bounded and let it scroll; do not clip content just to remove the scrollbar.
- Do not communicate a state only through thumb color. The region still needs a usable size, native scrolling, and clear surrounding context.
- Check nested regions, keyboard scrolling, touch input, zoom to 200%, and forced-colors mode before shipping.
Labels and errors
- Every control has a visible label or a concise accessible name; icon-only actions use
aria-label. - Errors identify the field, explain what needs to change, and are linked with
aria-describedbywhen the component supports it. - Do not communicate status with color alone; pair it with text, an icon, or a change in structure.
Interaction checklist
Tab through the route, activate controls with Enter/Space, test Escape for overlays, zoom to 200%, and enable reduced motion.
Hidden focus, clipped scroll regions, hover-only instructions, unlabeled icon buttons, and errors announced only by color.
Use the Colors, Sizing, and Motion pages together when reviewing a component.