Skip to content

fix(core): give the toggle button an accessible name and state - #3133

Draft
adarshsm wants to merge 1 commit into
TypeCellOS:mainfrom
adarshsm:fix/2811-toggle-button-accessible-name
Draft

adarshsm wants to merge 1 commit into
TypeCellOS:mainfrom
adarshsm:fix/2811-toggle-button-accessible-name

Conversation

@adarshsm

Copy link
Copy Markdown
Contributor

Summary

Fixes #2811. Screen readers can't identify the collapse/expand button on toggle list items and toggle headings. It has no accessible name, its chevron SVG isn't hidden from assistive technology, and nothing tells the user whether the nested blocks are shown.

Rationale

createToggleWrapper (vanilla) and ToggleWrapper (React) both render .bn-toggle-button as a plain <button type="button"> containing only an SVG. The issue asks for an accessible name and a hidden decorative image. I used the standard disclosure pattern: one constant label, plus aria-expanded for the state. With that, a screen reader announces "Expand or collapse, collapsed, button" and the name stays the same when the state changes.

Changes

  • New dictionary key toggle_blocks.toggle_button_label ("Expand or collapse"), added to all 23 core locales next to the existing toggle_blocks.add_block_button.
  • Vanilla wrapper (createToggleWrapper.ts):
    • The button gets aria-label and the SVG gets aria-hidden="true".
    • The six places that set data-show-children now go through a small setShowChildren() that also sets aria-expanded on the button, so the two attributes can't get out of sync.
    • ignoreMutation now also ignores the aria-expanded attribute change on the button, the same way it already ignores data-show-children. Without this, every toggle click re-rendered the node view (see Testing).
  • React wrapper (ToggleWrapper.tsx): aria-label, aria-expanded={showChildren}, and aria-hidden on the SVG.
  • HTML exporter (internalHTMLSerializer.ts): forceToggleBlocksShow already forces exported toggles to data-show-children="true". It now also sets the button's aria-expanded="true", so exported HTML doesn't announce an open toggle as collapsed.

Impact

  • The only visible change to output is three new attributes on the toggle button and its SVG, which appear in the blocknoteHTML export snapshots. Behaviour and styling are unchanged.
  • Translation check: I wrote the 22 non-English strings myself and they haven't been checked by native speakers, so corrections from anyone who knows these languages are welcome.

Testing

  • New packages/core/src/blocks/ToggleWrapper/createToggleWrapper.test.ts (jsdom). It mounts an editor with a toggle list item and checks the label, the hidden SVG, and that aria-expanded goes false → true → false across two clicks. It also checks that the button element is still the same one after a click, i.e. the block was not re-rendered.
    • With the source change reverted, it fails: expected null to be 'Expand or collapse'.
    • With only the new ignoreMutation clause removed, the same-element check fails, which shows the clause is needed.
  • The four toggle blocknoteHTML export snapshots were updated. Before I added the exporter change, they showed a real inconsistency: data-show-children="true" next to aria-expanded="false".
  • vp test --run in packages/core, packages/react, and tests/src/unit: everything passes. vp lint --type-aware and vp fmt --check are clean on the changed files.
  • Environment note: under Node 26, jsdom's localStorage is shadowed by Node's built-in Web Storage, so the toggle-related tests need NODE_OPTIONS=--no-experimental-webstorage locally. This affects the existing export tests too and doesn't come from this change.
  • I haven't tested this with a real screen reader.

Checklist

  • Code follows the project's coding standards.
  • Unit tests covering the new feature have been added.
  • All existing tests pass.
  • The documentation has been updated to reflect the new feature (not applicable)

🤖 Generated with Claude Code

Screen readers announced the toggle list / toggle heading button as a bare
"button": it had no accessible name, its chevron SVG was not hidden, and
nothing exposed whether the nested blocks were shown.

The button now gets a localized aria-label, the SVG is aria-hidden, and
aria-expanded follows data-show-children in both the vanilla and React
toggle wrappers. The vanilla node view ignores the aria-expanded mutation
the same way it already ignores data-show-children, so toggling does not
re-render the block. The HTML exporter, which forces toggles open, sets
aria-expanded="true" to match.

Fixes TypeCellOS#2811
@vercel

vercel Bot commented Sep 28, 2026

Copy link
Copy Markdown

@adarshsm is attempting to deploy a commit to the TypeCell Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Sep 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

@blocknote/ariakit

npm i https://pkg.pr.new/@blocknote/ariakit@3133

@blocknote/code-block

npm i https://pkg.pr.new/@blocknote/code-block@3133

@blocknote/core

npm i https://pkg.pr.new/@blocknote/core@3133

@blocknote/diagram-block

npm i https://pkg.pr.new/@blocknote/diagram-block@3133

@blocknote/mantine

npm i https://pkg.pr.new/@blocknote/mantine@3133

@blocknote/math-block

npm i https://pkg.pr.new/@blocknote/math-block@3133

@blocknote/react

npm i https://pkg.pr.new/@blocknote/react@3133

@blocknote/server-util

npm i https://pkg.pr.new/@blocknote/server-util@3133

@blocknote/shadcn

npm i https://pkg.pr.new/@blocknote/shadcn@3133

@blocknote/xl-ai

npm i https://pkg.pr.new/@blocknote/xl-ai@3133

@blocknote/xl-docx-exporter

npm i https://pkg.pr.new/@blocknote/xl-docx-exporter@3133

@blocknote/xl-email-exporter

npm i https://pkg.pr.new/@blocknote/xl-email-exporter@3133

@blocknote/xl-multi-column

npm i https://pkg.pr.new/@blocknote/xl-multi-column@3133

@blocknote/xl-odt-exporter

npm i https://pkg.pr.new/@blocknote/xl-odt-exporter@3133

@blocknote/xl-pdf-exporter

npm i https://pkg.pr.new/@blocknote/xl-pdf-exporter@3133

@blocknote/xl-typst-exporter

npm i https://pkg.pr.new/@blocknote/xl-typst-exporter@3133

commit: f7c29b7

This branch has not been deployed

No deployments
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.

Collapsible list: unlabeled accessible button, decorative image

1 participant