Fluxio
← Back to the blog

Accessible Token Streams: A Real-Time Chat Walkthrough

SSE & APIsEN

Token-by-token replies make AI interfaces feel responsive, but they can also overwhelm screen readers, disrupt reading position, and hide important controls. Accessible streaming text requires separating what appears visually from what gets announced. Follow this walkthrough to build live replies that remain usable with assistive technology, a keyboard, and reduced-motion preferences.

§1 Step 1: Define Accessible States for Each Live Reply

Start with a response lifecycle: waiting, streaming, completed, stopped, and failed. Each state needs visible text and an appropriate announcement. A spinner alone does not communicate whether the request is working, and a silent interruption can make a partial answer look complete.

  • – Show a waiting message while the request is being established.
  • – Identify the answer as generating while new text arrives.
  • – Distinguish a completed reply from one the user stopped.
  • – Explain failures without deleting text that already arrived.

Keep these state labels concise. Announce transitions rather than repeatedly announcing that generation is still happening.

§2 Step 2: Separate Token Rendering from Screen Reader Announcements

Do not make every incoming token a live announcement. Speech can become fragmented or queued far behind the visible answer. Instead, keep the readable response in a stable container and use a separate, initially empty status region for announcements. Create that region before streaming begins so assistive technology can detect later changes.

For a quiet default, announce that generation has started, then announce when the response is ready. Use a polite live region for routine status changes. Avoid putting the entire changing transcript inside an assertive live region, which can interrupt the user's current task.

If live listening is important, offer an optional mode that announces completed sentences or short paragraphs. Buffer incomplete text, batch updates, and test for duplicate or dropped announcements. Provide a way to disable live reading without stopping the underlying response.

§3 Step 3: Keep Streaming Content Structurally Stable

Append text to the current response rather than rebuilding the whole conversation on every chunk. Replacing large sections of the interface can disrupt selection and a screen reader's reading position. Give each message a persistent identity and preserve existing controls.

Partial Markdown needs special care. An unfinished heading, list, or code block can repeatedly change the accessibility structure as tokens arrive. Consider displaying unfinished blocks as plain text and applying semantic formatting when a block becomes complete. After generation, ensure headings, lists, and code remain understandable in reading order.

§4 Step 4: Preserve Keyboard Focus and Offer Stop Controls

Sending a message should not move keyboard focus into the growing answer. Keep focus predictable, usually in the composer, and make the response reachable through normal navigation. Provide a clearly named native button to stop generation, with a visible focus indicator and an adequate target size.

When generation ends, do not remove a focused stop button without a focus plan. Keep the control stable or deliberately restore focus to a sensible location. Stopping should cancel the client request and signal cancellation upstream where supported; confirm separately whether the provider stops generation and billing.

§5 Step 5: Make Auto-Scroll and Motion Optional

Follow new text only while the user is already near the conversation's bottom. If they scroll upward, stop following immediately. Show a keyboard-accessible control labeled with a clear action such as “Jump to latest reply” instead of dragging them away from earlier content.

Respect reduced-motion preferences by avoiding animated scrolling and decorative typing effects. Never communicate streaming status through animation or color alone. Check that long replies remain readable at high zoom and narrow viewport widths.

§6 Step 6: Connect the Stream Without Exposing Credentials

Fluxio fits applications that need a streaming-first, pay-per-token AI API relay through an OpenAI-style client. Route requests through your server to keep API credentials out of the browser. Configure the API base as https://api.fluxioapi.com/v1 for OpenAI-style clients, then forward response text and lifecycle events to your interface.

Keep the accessibility layer independent of the selected model. Whether using Claude Haiku 4.5 or Gemini 2.5 Flash, buffer network chunks before deciding what to announce. A transport chunk is not necessarily a complete word or sentence.

§7 Step 7: Test Interrupted and Completed Token Streams

Test with keyboard-only navigation and screen readers across your supported browsers. Include slow connections, immediate completion, long answers, cancellation, and network failure. Verify that users can read earlier content without losing position, hear completion once, and recover without losing their draft.

Sign up for Fluxio to build accessible live replies.

Create a Fluxio account →

More from the current