Skip to content

fix(markdown): name the checkboxes of a task list - #230

Merged
dgesteves merged 1 commit into
dgesteves:mainfrom
kasettadoo-sys:fix/markdown-task-list-names
Oct 30, 2026
Merged

dgesteves merged 1 commit into
dgesteves:mainfrom
kasettadoo-sys:fix/markdown-task-list-names

Conversation

@kasettadoo-sys

Copy link
Copy Markdown
Contributor

What was wrong

GFM task lists render as disabled checkboxes with no name: Markdown passed remark-gfm's <input type="checkbox" disabled> through as it is. The existing streaming test renders - [x] search but runs no axe check on it.

Before:

<Markdown>{'- [x] search\n- [ ] read'}</Markdown>

axe reports a critical label violation on both checkboxes (<input disabled="" type="checkbox" checked="">), and a screen reader announces a checkbox with no name. Agents write - [x] plans and to-do lists all the time, in AgentMessage too.

After: each checkbox is named "Task", with its checked state as before. axe finds no violations.

What changed

  • src/markdown.tsx: an input component, TaskCheckbox, that names a checkbox from labels.markdown.task. Other attributes are as remark-gfm sets them: disabled, and checked or not.
  • src/lib/labels.ts: a new key, markdown.task ("Task"). The Portuguese labels (test/labels-pt.ts, examples/playground/lib/labels-pt.ts and the copy in content/docs/labels.md) add "Tarefa".
  • test/labels-locale.test.tsx: the Markdown scenario renders a task list, so the new label has a state that shows it, and no English is left in it.
  • content/components/markdown.md says how task lists read.
  • A minor changeset, since it adds a label key: a translation typed as SignoffLabels needs markdown.task to type-check, and one passed as SignoffLabelsInput keeps the English (as in fix(approval-card, diff-review): accessibility and touch: Approve all's focus, what a card runs, code left to right, 16px fields #174).

How it was tested

New tests in test/markdown.test.tsx fail on main and pass here:

  • names the checkboxes of a task list, which read with their state: two checkboxes named "Task", the first checked, both disabled, no axe violations.
  • takes the task name from the labels: labels={{ markdown: { task: 'Tarefa' } }} names it "Tarefa".

Checks, all exit 0: pnpm build:lib, pnpm format:check, pnpm lint, pnpm lint:registry, pnpm registry:check, pnpm typecheck, pnpm test (1601 passed), pnpm size (AgentMessage stays 91.7 kB; /custom-markdown unchanged), pnpm test:site, pnpm examples:check.

For the owner to decide

  • One name or two: the checkbox gets one name, with its checked state read separately. Two names ("Done", "To do") would read the state twice.
  • Name from the item: naming each box after its item's text would need aria-labelledby and ids per item, which aren't stable while the text streams.

remark-gfm renders `- [x] Read the route` as `<input type="checkbox" disabled checked>`, and
`Markdown` had no `input` component, so the checkbox reached the page with no name. axe reports
that as a critical `label` violation, and a screen reader reads an unnamed checkbox before each
item. Agents write task lists for their plans and to-dos, so an `AgentMessage` with one failed
the axe check the kit's own tests run.

`Markdown` renders the checkbox through `TaskCheckbox`, which names it from the new
`labels.markdown.task` ("Task"); it stays disabled, and its state reads as checked or not. The
Portuguese labels in the tests, the gallery and the labels guide add "Tarefa", and the labels
test renders a task list, so the new key has a state that shows it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dgesteves dgesteves closed this Oct 30, 2026
@dgesteves dgesteves reopened this Oct 30, 2026
@dgesteves
dgesteves merged commit fc4c22f into dgesteves:main Oct 30, 2026
20 of 21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants