AI assistant — accessibility
Keyboard
- Every control is a real
<button>: the four head actions, the trace toggle, the four answer actions, the slash button and send. Tab reaches them in reading order. - The composer is a multiline input: <kbd>Enter</kbd> sends, <kbd>Shift</kbd>+<kbd>Enter</kbd> makes a new line. Typing <kbd>/</kbd> at the start opens the prompt menu; the slash button does the same for the mouse. These are the only two shortcuts the panel owns.
- The trace toggle is operable from the keyboard and carries
aria-expanded, so the collapsed state is both announced and controllable. - The panel does not trap focus — it is a column of the page, not a modal — and it does not move focus when it opens.
ARIA
section.aichat-panelis labelledAI asistent, so the panel is findable as a region.- The thread body is
role="log"witharia-live="off". That is deliberate: an answer streams token by token, and a live log would read every fragment. The cost is that a completed answer is not announced at all —AssistantChatmounts a separateRunAnnouncerfor that, and it is the only thing that speaks. - The feedback buttons carry
aria-labelandaria-pressed, so the active thumb is announced as pressed and re-pressing it clears the vote. - The head buttons are named by
titleonly; the kebab additionally carriesaria-haspopup="menu"andaria-expanded. The Anonymous mode row is amenuitemcheckboxand keeps the menu open; the model choices aremenuitemradio; Thread history and Model open a drill-in level headed by a back row. - The tool trace is a list of spans with no roles — it is a summary of what happened, not a structure to navigate.
- The sparkle mark is decorative.
Focus
- All controls take the foundation ring from
ds.css(outline: 2px solid var(--accent); outline-offset: 1px); neitherassistant.cssnorai-chat.cssswitches it off. - Focus ring
--accent: 4.44:1 light, 3.83:1 dark. - The scroll-to-bottom button appears and disappears with scroll position, so a tab stop comes and goes while the user reads.
Contrast
Computed from packages/ui/src/tokens/tokens.css:
- The answer text is ink on the canvas — 17.59:1 light, 14.53:1 dark.
- The question block is ink on
--surface-75, which is a 1.03:1 ground against the canvas: the block is distinguished by its shape and alignment far more than by its colour. That is intentional (it is meant to be quiet), but it means the boundary between question and answer is carried almost entirely by position. - Tool labels and the typing line use the muted tone — 2.85:1 light, 3.63:1 dark, below AA.
Known limits
thumb-up,thumb-downandplayer-stopare missing from the icon set and fall back toinfo-circle. The two feedback buttons therefore draw the same glyph. Theiraria-labels still differ, so a screen-reader user can tell them apart — but a sighted user cannot, which inverts the usual failure. Verified in the browser.aria-live="off"means the thread itself never announces; everything depends onRunAnnouncer.- The question/answer boundary is positional and low-contrast.
- Tool labels sit below AA.
- No shortcut focuses the panel or the composer from the page.
Source: docs/ai-assistant/ai-assistant.a11y.md · GitLab