Skip to content
turn

guides

Accessibility

Keyboard shortcuts, screen-reader behavior and how the components are tested.

how it is tested

  • Every component runs through axe in the automated test suite, along with tests for keyboard behavior, ARIA state and focus.
  • The docs pages are checked with axe in a real browser, including color contrast, at desktop and phone widths.
  • A test fails the build if any animation lacks a prefers-reduced-motion opt-out.
  • Automated checks do not replace listening to the interface. We have not yet done full manual sessions with VoiceOver, NVDA and JAWS. If something sounds wrong, please open an issue.

patterns used everywhere

  • Conversation as a log. Put messages in a container with role="log" and aria-live="polite". Set aria-busy while a reply streams so assistive technology waits for the finished message. Give the container tabIndex={0} too: a log made only of text has no focusable content, so without it keyboard users cannot scroll it.
  • Speaker labels. Each message is prefixed with a screen-reader-only "You said:" or "Assistant said:".
  • State is spoken, not only colored. Status, risk, errors and plan steps all have text. Color only reinforces it.
  • Focus is never dropped. When the focused control disappears (a removed attachment, a decided approval, a closed follow-up), focus moves to a sensible neighbor.
  • Reduced motion. Movement, scaling and looping animations stop. Color and opacity fades remain.

keyboard

componentkeyswhat they do
Prompt ComposerEnterSend. Shift+Enter adds a line. Escape stops a running reply.
Slash Commands↑ ↓ Enter Tab EscMove through the list, choose a command, close the menu.
Model Pickertype ↑ ↓ Enter EscSearch, move, choose, close. Focus returns to the trigger.
Reasoning, Tool CallEnter SpaceExpand or collapse.
FeedbackEnter Space Esc Ctrl/Cmd+EnterRate, close the follow-up, submit the comment.
AttachmentTab Enter SpaceReach a remove button and activate it. Focus moves to the next file.
Approval PromptTab Enter SpaceReach Approve or Deny and activate.
Artifact← → EnterMove between Preview and Code.
Scroll to Bottom, Suggestions, Copy ButtonTab Enter SpaceNative buttons.

notes by component

foundation

Button
  • Native button semantics with a visible focus ring.
  • Disabled buttons are removed from the tab order.

conversation

Message
  • Each message is prefixed with a screen-reader-only speaker ("You said:" / "Assistant said:"). Put the list in a container with role="log" and aria-live="polite", and give it tabIndex={0} so keyboard users can scroll a log made only of text.
  • Set aria-busy on that container while a reply streams so screen readers announce it once, not per token.
  • Actions are revealed on hover and on keyboard focus.
Streaming Markdown
  • Output is semantic HTML: headings, lists, tables and links.
  • Links open in a new tab with rel="noreferrer".
  • Citation markers are links named "Source n: title".
  • Set aria-busy on the surrounding log while streaming so updates are announced when complete.
Code Block
  • The code area is keyboard focusable so long lines can be scrolled without a mouse.
  • The Copy button confirms through a separate role="status" region ("Copied to clipboard"), which screen readers announce reliably.
  • Light mode uses a high-contrast Shiki theme (github-light-high-contrast); all token colors pass 4.5:1.
Citations
  • Markers are links named "Source n: title".
  • The hover preview also opens on keyboard focus.
  • Sources is a list labelled "Sources".
Feedback
  • Rating buttons are toggles (aria-pressed) in a group named "Rate this response".
  • Opening the follow-up moves focus to its first reason; Escape, Skip and Submit return focus to the rating button.
  • The confirmation is a role="status" region. Ctrl/Cmd+Enter submits from the comment box.
Scroll to Bottom
  • The button is only in the DOM while the container is away from the bottom, so it is never an unreachable tab stop.
  • It has an accessible name that contains its visible text ("latest").
  • After jumping, focus moves to the scroll container so it is not dropped on the page. The container gets tabindex=-1 if it has none.
  • Scrolling is instant when the user prefers reduced motion.
Thinking
  • A role="status" region with a visible text label, so the wait is announced politely.
  • The pulsing squares are decorative (aria-hidden) and stop under reduced motion.
Error Notice
  • Announced immediately as role="alert".
  • The error is stated in text; the red edge is only decoration.
  • While retrying, the button stays focusable but inert, so keyboard focus is not lost. Keep the notice mounted until the retry produces output.
Copy Button
  • An icon button with an accessible name ("Copy" by default).
  • Success is confirmed through a separate role="status" region, which screen readers announce reliably.
  • If the clipboard is blocked the button stays quiet instead of claiming success.

input

Prompt Composer
  • Enter sends, Shift+Enter inserts a newline, Escape stops a running response, and IME composition is respected.
  • Send is disabled when there is nothing to send; while streaming the same button becomes "Stop generating".
  • The attach button is labelled, and drop or paste of files is also supported.
Slash Commands
  • Focus stays in the textarea. Up/Down move through the list (wrapping), Enter or Tab selects, Escape dismisses.
  • The input points at the active option with aria-activedescendant and at the list with aria-controls.
  • The textarea does not use role="combobox" because that role is not allowed on a textarea.
Model Picker
  • Built on Base UI Combobox: the trigger is a combobox with aria-expanded and the popup is a dialog with a listbox.
  • Opening moves focus to the search field; Arrow keys and Enter select, Escape closes and returns focus to the trigger.
  • Disabled pickers cannot be opened.
  • Respects prefers-reduced-motion: the popup opens and closes without the scale/fade animation.
Attachment
  • Remove buttons are named "Remove <file>" and are visible on hover, on focus, and always on touch devices.
  • Upload progress is a progressbar named "Uploading <file>"; errors are shown as text, not color alone.
  • After removing an item, focus moves to the next one (or the message input when the list is empty).
  • Respects prefers-reduced-motion: the progress bar fill updates without animating.
Suggestions
  • A group with an accessible name; each suggestion is a native button.
  • Use disabled while a reply streams instead of removing the row, so keyboard focus is not lost.
  • On narrow screens the row scrolls sideways; its buttons make it keyboard reachable.

agent

Reasoning
  • The header is a button with aria-expanded; its label reflects state ("Thinking…", "Thought for 3s").
  • It opens while streaming and collapses afterwards.
  • Respects prefers-reduced-motion: the thinking pulse, chevron rotation and expand/collapse animation are turned off.
Tool Call
  • The header is a button with aria-expanded; its accessible name includes the tool name and status.
  • Status changes are in a polite live region.
  • Respects prefers-reduced-motion: the running pulse and chevron rotation are turned off; the status is still shown by color and text.
Plan
  • An ordered list named "Plan"; the active step has aria-current="step".
  • Each step's state is read out ("Completed:", "In progress:", "Not started:", "Failed:"), not just shown as an icon.
  • Respects prefers-reduced-motion: the active-step pulse is turned off; the active step is still marked by its ring and aria-current.
Trace
  • A table with a header row. Every span has its duration as text, so the bars are a visual extra.
  • Failed spans are labelled "failed" in text as well as shown in red.
Approval Prompt
  • An alertdialog named by its title. It does not trap focus; set autoFocus when it appears mid-conversation.
  • After a decision the buttons are removed and focus stays in the prompt, with the result in a polite live region.
Artifact
  • Tabs follow the WAI-ARIA pattern: Arrow keys move focus between tabs, Enter or Space activates, and the panel is focusable.
  • The close button is labelled "Close artifact".