How to build an accessible ChainOfThought in React
An ordered list whose active step carries aria-current="step" and whose list is aria-busy while any step is active. Each step speaks its state as visually hidden text after the title, because the marker glyph is decorative. Steps with detail are native <details>/<summary> disclosures (Enter/Space), so they work before hydration. Only the active marker pulses, under prefers-reduced-motion: no-preference; the chain is never a live region — pair it with AiStatus to announce progress
When to use a ChainOfThought
- Showing the discrete steps an AI agent is taking or took — searches, file reads, tool calls
- Letting a reader expand a step to see what it found, without cluttering the answer
When not to use it
- A free-form reasoning trace — use Reasoning
- A user-facing multi-step form or checkout — use Steps
- A dated activity feed — use Timeline
- One tool invocation with its input and output — use ToolCall
Keyboard interactions
Role list, verified at WCAG 2.2-AA.
TabEnterSpace
Common mistakes
Avoid: Marking several steps active at once to look busy
Prefer: One active step at a time; finished steps become complete or error
The active step is announced as the current step (aria-current="step"); more than one makes the position meaningless
Example
<ChainOfThought
items={[
{ id: 'search', title: 'Searched the docs for "refund policy"', status: 'complete' },
{ id: 'read', title: 'Reading 3 pages', status: 'active' },
{ id: 'answer', title: 'Write the answer', status: 'pending' },
]}
/>