Accessibility
Accessibility is a default, not a feature. Every Justin component ships with it.
Contrast
- All text passes WCAG AA at default sizes in both light and dark themes.
- Token pairs are designed as background/foreground pairs (
Primary/OnPrimary). Swap them both when theming — never mix across pairs.
Keyboard
- Every interactive component is reachable by keyboard.
- Focus order follows DOM order on web, declaration order on Compose.
- Focus indicators are visible (no
outline: nonewithout an equivalent). - Escape dismisses overlays (dialog, bottom sheet).
Semantics
- Use the correct role: buttons are buttons, links are links, headings build the document outline.
- Provide
contentDescriptionfor every interactive icon-only control in KMP. - Use
semantics { }blocks when aggregating custom UI into a single accessible unit.
Motion
- Animations respect
prefers-reduced-motion. When reduced, transitions are disabled or made instant. - No parallax, no auto-playing motion.
Screen readers
- Components expose role, state, and value correctly.
- Live regions (snackbar, toast, alert) announce politely unless the content is critical.
Touch targets
- Minimum target size 48×48 dp on mobile (M3 guidance).
- Hit targets can exceed visual size via padding — visual size may be smaller.
Color alone
- Never use color as the sole carrier of meaning (e.g. error state uses icon + text, not just red).
Testing checklist
- Navigate the screen using only Tab/Shift+Tab.
- Turn on TalkBack / VoiceOver and confirm every label is meaningful.
- Toggle
prefers-reduced-motionand verify no motion plays. - Verify both light and dark themes (drawer toggle in the top bar).