Skip to content

a11y: static-board-display.tsx — accessible name drops the board's message content #205

Description

@claude

File: src/components/board/static-board-display.tsx

Category: C (quality — unhelpful accessible name)

WCAG: 1.1.1 Non-text Content (A); related 4.1.2 Name, Role, Value.

The barrier

StaticBoardDisplay renders the split-flap grid as a single role="img" with aria-label={message ? previewLabel : emptyLabel}, and previewLabel defaults to the generic string "Board preview" (static-board-display.tsx:45, :90). The board's actual message is drawn as a wall of individual glyph tiles inside an aria-hidden="true" container, so the only thing a screen reader can announce is the label.

The result: a board rendered with real content — e.g. the Default, MediumSize, WhiteBoard, NoteDevice, and ThumbnailGrid stories all pass message but no previewLabel — is announced as just "Board preview, image." The text a sighted user reads ("HELLO WORLD / WELCOME TO / FIESTABOARD / …") is completely inaccessible to a screen-reader user.

This is inconsistent with its two sibling renderers, both of which put the message content into the accessible name by default:

  • BoardDisplay — default messageLabel = (msg) => \Board display: ${msg}`` (board-display.tsx:1237), so it announces the message.
  • BoardTeaser — derives the label from the teaser text, color markup stripped (board-teaser.tsx:53–60).

StaticBoardDisplay is the odd one out: for the thumbnail/list use case it exists for, dropping the content is exactly the wrong default.

Who is affected, and how

A blind or low-vision screen-reader user browsing a dashboard, board list, or chat card built on StaticBoardDisplay hears "Board preview" for every board and cannot tell one from another — the message that distinguishes them (weather, alerts, a quote) is never spoken. Sighted users get all of it; screen-reader users get none of it. In the ThumbnailGrid story, four distinct boards are announced identically.

Why existing tooling misses it

axe only checks that an accessible name exists"Board preview" is a non-empty label, so role="img" passes image-alt / aria-label rules cleanly. axe cannot judge whether the name is useful or whether it reflects the rendered content, so this passes CI in both themes.

Suggested fix

Make the default accessible name include the message content, matching BoardDisplay. Either:

  • Change the default so the label incorporates the parsed message text (color markup stripped, newlines collapsed) — e.g. a default previewLabel builder (msg) => \Board preview: ${msg}`, mirroring BoardDisplay's messageLabel` contract; or
  • Accept a messageLabel?: (message: string) => string prop like BoardDisplay so the three renderers share one labelling contract.

This is a behavioural/API choice (default wording, and possibly a new prop signature), not a mechanical edit, so it is filed rather than auto-fixed. Visually neutral — it changes only the accessible name, no rendered pixels, so no VRT baseline reseed is required.


Filed by the a11y-audit cron — round 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a11yAccessibility: keyboard, screen reader, motion, contrasta11y-auditFiled by the a11y-audit cronclaude-fixRun the Claude issue-triage workflow on this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions