How to build an accessible AiStatus in React

The label lives in a role="status" node holding one stable string per phase, so each phase change is announced once and token-level streaming never is. The glyph is aria-hidden and only it pulses (under prefers-reduced-motion: no-preference), so the label never drops below contrast. Stop is a real button outside the status node, so pressing it does not re-announce; forced colours render everything CanvasText

When to use a AiStatus

When not to use it

Keyboard interactions

Role status, verified at WCAG 2.2-AA.

Common mistakes

Avoid: aria-live on the streaming response text

Prefer: <AiStatus status={phase} /> beside the response, which renders silently

A live region on streaming text re-announces on every token; AiStatus announces each phase change once

Avoid: Showing AiStatus for a response that arrives in under a second

Prefer: Delay mounting it ~1s so fast responses never flash a loader

A loader that blinks on and off reads as a glitch and makes a screen reader announce noise

Example

<AiStatus status="thinking" />

See the full AiStatus reference →