Skip to content
loopkit

Docs

Accessibility

Agent apps ask people to make decisions. Everyone should be able to make them, with any input and any setting.

What every component does

  • Works with the keyboard alone, with a visible focus ring from --ring.
  • Uses native elements first (buttons, checkboxes, radios) and ARIA roles where there is no native one (radiogroup, timer, meter, log).
  • Never uses colour alone: risk, status and validity always have text or an icon too.
  • Announces changes politely (aria-live) without stealing focus.
  • Checks prefers-reduced-motion: loops stop, springs become fades, and canvases draw one still frame.
  • Meets WCAG AA contrast with the default tokens in both themes.

Keyboard shortcuts

  • Approval Card: A approve, R reject, while focus is inside the card.
  • Approval Inbox: j/k move, x select, a/r decide.
  • Mode Switch: arrow keys move and select.

Per component

Approval Card
  • Card is a group labelled by its title.
  • Countdown has role=timer and an aria-label with seconds left.
  • Stamp is announced via role=status.
Mode Switch
  • role=radiogroup with role=radio buttons and roving tabindex.
  • Arrow keys move and select.
  • Hint is aria-live=polite.
Cost Meter
  • Budget bar is role=meter with min, max and current value.
  • Sparkline is decorative (aria-hidden).
Tool Call Viewer
  • Header is a button with aria-expanded / aria-controls.
  • Payload tabs use role=tablist / tab / tabpanel.
Run Timeline
  • Ordered list; the active step has aria-current=step.
  • List is aria-live=polite so screen readers hear progress.
Agent Chat
  • Message list is role=log, aria-live=polite.
  • Input has a visually hidden label.
Audit Log
  • Status chip is role=status.
  • Each row ends with a valid/invalid label, not colour alone.
Policy Prompt
  • role=alertdialog with label and description.
  • Native checkboxes and radios, so keyboard and screen readers work as expected.
Task Board
  • Columns announce their task count.
  • Each card is a button whose label says where it will move.
Swarm Map
  • SVG has role=img with a summary label.
  • Agents are focusable buttons with name and role.
  • Packets stop under reduced motion.
Knowledge Graph
  • Nodes are focusable buttons with label and type.
  • Legend uses text, not colour only.
Voice Input
  • Mic is a toggle button with aria-pressed and a changing label.
  • Transcript is aria-live=polite.
  • Waveform is decorative.
Agent Status
  • Each avatar is a button whose label includes name, state and task.
  • Counts are aria-live=polite.
Handoff Banner
  • Region with a label; timer has role=timer.
  • Collapsible list uses aria-expanded.
  • Result line is role=status.
Diff Review
  • File list is a nav; current file has aria-current.
  • Toggles use aria-pressed.
  • Status line is role=status.
Eval Card
  • Bars are role=meter with values.
  • Pass/fail is text, not colour only.
Memory Inspector
  • Search has a label; filters use aria-pressed.
  • Confidence has a text label.
  • Undo bar is role=status.
Budget Guard
  • Bucket is role=meter.
  • State chip is role=status.
Plan Stepper
  • Progress bar has aria values.
  • Status line is aria-live.
Approval Inbox
  • List is focusable with keyboard instructions in its label.
  • Every row has labelled checkbox and buttons.
  • Toast is role=status.
Hero Mesh Gradient
  • Canvas and the dot-grid overlay are aria-hidden; only real text and links are in the accessibility tree.
  • Headline is a single <h1>; CTAs are real <a> elements with visible focus rings from the design system.
  • Contrast of headline and body text against the gradient is kept high by layering a background/background-gradient scrim under the text column.

Your part

  • Give each component a meaningful title or label in real use; the demo text is generic.
  • Don't auto-approve on a timer in production. The countdown should expire to “expired”, which is the default.
  • Test with your screen reader of choice after wiring real data.