Skip to main content

Required States per Component

Every interactive component must implement the full set of states listed below. Missing states are a blocking issue in design review.

Buttons (Primary, Secondary, Ghost)

Text Inputs

Toggle

TabNav (Sub-Navigation)

<TabNav> (apps/web/src/components/ui/TabNav.tsx) implements two distinct ARIA patterns depending on mode: Keyboard: state mode supports arrow-key roving focus (ArrowLeft / ArrowRight move and select the previous/next enabled tab, Home / End jump to the first/last enabled tab); disabled items are skipped. Route mode relies on standard link/tab-order navigation since items are <Link>s, not tabs. Touch target: items are 44px tall below the md breakpoint (h-11), meeting the minimum touch-target size on mobile. Focus ring: 3px solid rgba(107, 94, 248, 0.25) on every focusable item, in both modes.

Heading hierarchy

Exactly one <h1> per rendered route, supplied by <PageHeader> (apps/web/src/components/ui/PageHeader.tsx). Section layouts that own a PageHeader (admin, operator, settings, knowledge graph) mean their child pages must use <h2> for section headings rather than rendering a second PageHeader. <Breadcrumbs> (apps/web/src/components/layout/Breadcrumbs.tsx) renders a <nav> landmark above the page title, giving assistive tech a distinct region for hierarchical location separate from the <h1>.

Upload Cards (Document, Instagram)

Usage Credit Card


Contrast Ratios

All text and interactive elements must meet these minimum contrast ratios against their backgrounds.

Token Contrast Verification

--color-purple on white is borderline at 4.1:1. Use it only for focus rings (3:1 minimum for UI components) and large text. Never use it as small body text on white.
--color-disabled fails contrast on white. This is acceptable because disabled elements are not interactive, but always pair disabled visuals with aria-disabled so assistive technology communicates the state.

Focus Ring Specifications

Buttons (Primary, Secondary, Disconnect)

Toggle

Use :focus-visible (not :focus) for buttons and toggles so that mouse clicks do not show the focus ring. Inputs use :focus because the ring doubles as a “currently editing” indicator.

WCAG 2.1 AA Compliance Checklist

Use this checklist when reviewing any new page or component.
  • All images have meaningful alt text or aria-hidden="true" for decorative images
  • Color is never the sole indicator of state (always paired with icon, text, or pattern)
  • Text can be resized to 200% without loss of content or functionality
  • Contrast ratios meet minimums listed above
  • Media content has captions or transcripts where applicable
  • All interactive elements are reachable via keyboard tab
  • Focus order follows a logical reading sequence (left-to-right, top-to-bottom)
  • Focus is visible on every interactive element (see focus ring specs above)
  • No keyboard traps — user can always tab out of any component
  • Modals trap focus within themselves until dismissed, then restore focus to trigger
  • No content flashes more than 3 times per second
  • Form inputs have associated <label> elements or aria-label
  • Error messages identify the field and describe how to fix the error
  • Page language is set via lang attribute on <html>
  • Navigation is consistent across pages
  • Input purpose is identifiable via autocomplete attributes where applicable
  • HTML is valid and well-structured
  • ARIA roles, states, and properties are used correctly
  • Custom components expose correct roles (role="button", role="dialog", etc.)
  • Status messages use role="status" or role="alert" for live regions
  • Component state changes are announced to screen readers

Quick Reference

All Color Tokens

Key Sizes

5 Key Rules

1

One Primary Button per view

Never place two navy 48px buttons on the same screen. Demote the less important action.
2

Red means destructive, always

--color-destructive is never decorative. Every red element signals danger or error.
3

Focus rings on everything interactive

Every button, input, toggle, link, and card that accepts interaction must show a visible focus indicator on keyboard navigation.
4

Never rely on color alone

Pair color with icons, text labels, or patterns. A colorblind user must be able to distinguish all states.
5

Confirm before destroying

Deletions, disconnections, and irreversible actions always require an explicit confirmation step.