ui/CollapsibleCard: include card title in trigger's accessible label#76329
ui/CollapsibleCard: include card title in trigger's accessible label#76329ciampo wants to merge 5 commits into
Conversation
The toggle button in CollapsibleCard.Header used a hardcoded "Expand or collapse card" label, making multiple cards on the same page indistinguishable for screen reader users. Introduce a React Context (TitleTextContext) so Card.Title can register its rendered text content with a parent CollapsibleCard.Header. The header composes a descriptive label — e.g. "Expand or collapse Settings" — and passes it to the IconButton as both aria-label and tooltip. When no Card.Title is present, the header falls back to reading the text content of its content wrapper. Made-with: Cursor
Made-with: Cursor
…ve fallback - Split Card.Title's useLayoutEffect into two: a per-render sync (no cleanup) and a separate unmount-only cleanup, avoiding a transient clear of the title text between effect runs. - Remove TitleTextContext from the card barrel export to keep it private; import directly from card/context in collapsible-card. - Add children to the fallback effect's dependency array so the header content label re-syncs when children change. Made-with: Cursor
|
Size Change: -2 B (0%) Total Size: 6.89 MB
ℹ️ View Unchanged
|
…bsent Made-with: Cursor
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Flaky tests detected in 0628aef. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/22865379788
|
| <IconButton | ||
| { ...props } | ||
| label={ __( 'Expand or collapse card' ) } | ||
| label={ triggerLabel } |
There was a problem hiding this comment.
Why not create a stable id here and pass that in the context? Additionally set the aria-labelledby to IconButton. Current approach feels a bit over-engineered but I might be missing something..
In general if aria-labelledby is set it takes precedence over aria-label. Also I'm not sure expand/collapse text as tooltip provide much value visually and for screen readers the aria-expanded is enough.
There was a problem hiding this comment.
I definitely agree that the current approach feels more complex than you'd expect.
I initially experimented with aria-labelledby but I realized that the accessible label would go out-of-sync with the tooltip's visible text, which is something we should avoid when possible (https://www.w3.org/WAI/WCAG22/Understanding/label-in-name.html)
There was a problem hiding this comment.
Also I'm not sure expand/collapse text as tooltip provide much value visually and for screen readers the aria-expanded is enough.
I thought it would be better to explicitly announce the action associated with the button. Without it, screen readers announce something like "[Card title], button, collapsed", and tooltip would just show the "[Card title]" text.
Maybe "Toggle" instead of "Expand or collapse" is a shorter, better alternative ?
There was a problem hiding this comment.
I thought it would be better to explicitly announce the action associated with the button. Without it, screen readers announce something like "[Card title], button, collapsed"
For screen readers "[Card title], button, collapsed" is good and we should avoid extra announced things if they are not needed.
I initially experimented with aria-labelledby but I realized that the accessible label would go out-of-sync with the tooltip's visible text,
Personally I think that since for visual users we have the title next to a chevron icon is enough to communicate the togglable behavior. I also don't think we have any other similar UI where we have added the expand/collapse action verb in such a tooltip and furthermore I don't think we have cases that we use any tooltip at all.
Do you think it's necessary to have the tooltip at all?
and tooltip would just show the "[Card title]" text.
Assuming we want the tooltip, I think that's fine.
There was a problem hiding this comment.
Sure, I'll drop "Expand/collapse" (or any other string in front of the card title).
I'll do a bit more research into seeing if we can drop the tooltip, especially in the context of a separate Card exploration where dropping the tooltip is also being discused.
The two PRs may affect each other and end up "merging" into one PR.
|
Closing as superseded by #76265 |
Related to #73638
Summary
The toggle button in
CollapsibleCard.Headerused a generic "Expand or collapse" label, making multiple collapsible cards on the same page indistinguishable for screen reader users.This PR uses a React Context so that
Card.Titlecan register its rendered text with a parentCollapsibleCard.Header. The header composes a descriptive trigger label — e.g. "Expand or collapse Settings" — used as botharia-labeland tooltip. When noCard.Titleis present, the header falls back to its own text content.Outside a
CollapsibleCard,Card.Titlebehaves identically to before (the context is a no-op).Test plan
npm run test:unit -- packages/ui/src/card packages/ui/src/collapsible-card)CollapsibleCard > MultipleCardsstory shows three cards with distinct toggle button labelsVisual preview
Kapture.2026-03-09.at.17.37.24.mp4