Gallery
Live demos
Working examples, built as real DOM. Tab through them, run a screen reader over them, zoom in, or switch on reduced motion and see what changes.
The agents here are canned. Nothing calls a model, and the same request always gets the same answer.
A minimal accessible chat
Demonstrates Announced State Changes, Stall Signal, Stop Control, Scroll Stays Put, Durable Errors, Speaker Labels, Semantic Rendering, Reflowable Output, Focus Stays Put, Actions on Focus and Forgiving Composer.
Conversation
Try this with a screen reader on: press Send and keep your focus in the message box. You'll hear "Assistant is responding", the steps, and then "Response complete" once. The streaming text is not a live region, so it isn't read chunk by chunk. When you want the answer, use "Go to latest response" or jump by heading.
Then try breaking it: scroll up mid-response (the view stays where you put it), press Escape to stop (the partial answer stays), turn on "The next send fails" (the error stays on the page and your text stays in the box), or zoom to 400% (the table scrolls inside its own box, not the page).
An approval that waits for you
Demonstrates Reachable Approval, Untimed Approval and Reversible by Default.
Approve this transfer?
- From
- Brokerage account ending 4471
- To
- Roth IRA ending 9920
- Amount
- $3,400.00
Try this: run the agent and keep your focus on the Run button. When the agent pauses, the status line announces what it's waiting for and a "Go to approval" button appears. Focus doesn't jump on its own. The approval has no countdown, the buttons say what they do, and a completed transfer can be undone.
What most products ship instead: a card titled "Confirm action", buttons labeled "Confirm" and "Cancel", and "Proceeding in 10 seconds" underneath.
Announced progress, readable result
Demonstrates Announced State Changes, Post-Stream Readability and Reduced-Motion Streaming.
Try this: start the run, then look away. The status line is a live region, so a screen reader announces "Working", then "Done", without you watching. When the run finishes, the full response stays on the page, readable from the top, because nothing here depends on having seen it arrive. If your system is set to reduced motion, the response renders in one pass instead of typing itself out.
A trail you can operate
Demonstrates Keyboard-Reachable Steps, Semantic Activity Trail and Status Beyond Color.
Activity trail
-
ReadRetrieved account balances
accounts.list(owner: current_user) → 3 accounts as of 4:02pm
-
ReadChecked 2026 contribution limit
policy.lookup("ira_limit", year: 2026) → $7,500 source: plan document, rev. Jan 2026
-
ReadCalculated remaining room
7500 − 4100 = 3400
-
WriteDrafted a contribution of $3,400
draft.create(amount: 3400, status: "pending_approval"). Nothing moves until you approve.
Try this: tab into the trail and press Enter or Space on a step. Each one is a real
<details> element inside an ordered list, so it works from the keyboard,
announces its expanded state, and can be skipped with list navigation. The one step that
changes something is marked as a write in its text label as well as its border, so it doesn't
read as a fourth identical lookup.
Status that survives without color
Demonstrates Status Beyond Color and Spoken Uncertainty.
-
ReadLocated the joint brokerage account
accounts.get(id: "…4471") → found
-
BlockedStopped before placing the trade
guardrail: trading_permissions. This session is read-only for joint accounts.
- Located the joint brokerage account
- Placing the trade
Try this: switch between the two, ideally with a screen reader or a Windows contrast theme on. In the second version the only sign that a step was blocked is a red border, which isn't there for a screen reader, is hard to see with some color vision deficiencies, and disappears in forced-colors mode. The result gives the user nothing to do next. In the first, "Blocked" is text and the result names the boundary and two ways forward.