Skip to content

[Feature]: Expose each chat message as a heading for screen reader navigation #8535

Description

@Leos-Khai

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I am describing a concrete problem or use case, not just a vague idea.

Area

apps/web

Problem or use case

As a screen reader user, moving around a conversation in T3 Code is slow. The transcript renders as a flat run of text with no semantic structure marking where one message ends and the next begins. To get back to an earlier message I have to arrow through every line of everything in between, including long code blocks. There is no way to skim, and no way to answer "where does the previous reply start?" without reading forward through the whole thing.

Proposed solution

Render the author of each message as a real heading element. For every turn in the transcript, emit a heading whose text identifies who sent it:

  • "You" for user messages
  • "T3 Code" (or the model name) for assistant messages

Use a consistent level that nests under whatever heading identifies the conversation itself — if the chat title is an h1, each message becomes an h2.

If the visual design does not want a visible heading, it can be visually hidden with an sr-only utility while staying in the accessibility tree. Where a sender label is already rendered, marking that existing element up as a heading is enough — no new visible UI required.

Why this matters

Heading navigation is the primary way screen reader users skim. NVDA and JAWS move heading to heading with H, and VoiceOver's rotor lists every heading on the page. With one heading per message, jumping to the previous message becomes a single keystroke and the whole conversation becomes listable. Without them, the transcript is an undifferentiated wall of text and the only navigation available is line-by-line arrowing.

Issue #1915 added an outline minimap that solves the same navigation problem for sighted users. This is the assistive-technology equivalent, and it is considerably cheaper to build.

Smallest useful scope

One heading per message, announcing the author, at a consistent level, in the chat transcript. Visually hidden is fine.

Alternatives considered

  • role="article" with an aria-label per message. This helps, but article navigation is supported and used far less widely than heading navigation.
  • A live region announcing new replies as they stream in. That is a real and separate need — it covers content arriving, not navigating back through content that is already there.

Risks or tradeoffs

Heading levels need to stay consistent with the rest of the page so the document outline does not skip levels.

Worth noting: assistant replies frequently contain their own markdown headings. Those need to render at a level below the per-message heading, otherwise a model reply containing an h2 will sit as a sibling of the message headings and break the outline.

Examples or references

  • WCAG 2.4.10 Section Headings
  • WCAG 1.3.1 Info and Relationships

Contribution

  • I would be open to helping implement this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions