fix(web): role=button + aria-label on source-detail chunk cards (#700)#810
Merged
fix(web): role=button + aria-label on source-detail chunk cards (#700)#810
Conversation
Source-detail .chunk-card rows had no accessible name and the collapsible ones had no keyboard activation — only mouse-click was wired. Screen readers announced cards as anonymous "group" landmarks, and keyboard users could neither focus nor expand a collapsed card. Set aria-label unconditionally on every card (chunk type + line range + heading-hierarchy trail). Cards that grow tall enough to be marked .chunk-card-collapsible additionally get role="button" + tabindex="0" and a keydown handler that mirrors the existing click toggle. Refactor the toggle into a local toggleCard() helper so click and keydown share one code path. The keydown handler skips when focus is in .chunk-card-actions (so a button's Enter doesn't also collapse the parent) or .chunk-card-edit-area (so a textarea's Enter doesn't collapse the card mid-edit). Drag detection on click is preserved. Pin the contract with TestChunkCardA11y in test_web_a11y.py — three source-scan assertions: aria-label is set on every card, role=button + tabindex live inside the .chunk-card-collapsible activation block, and the keydown handler exists with both required exclusion zones. Mutation-validated: removing role= from the activation block fails the specific test. Refs #700, umbrella #702. Co-Authored-By: Claude <[email protected]>
4f96a07 to
9fda6d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Source-detail
.chunk-cardrows had no accessible name, and the collapsible variant — added in the rAF accordion pass whencontentDiv.scrollHeight > 120— had only mouse-click wired for expand/collapse. Screen readers announced cards as anonymous "group" landmarks and keyboard users could neither tab to a card nor expand it.Third of three split PRs against #700 (
Source detail chunk cardstarget). Independent of #808 (search) and #809 (timeline).Changes (
app.js,browseSource)aria-labelon every card (chunk type + line range + heading-hierarchy trail) right aftercard.dataset.chunkId— informational cards still need an accessible name.requestAnimationFrameaccordion-activation block, when a card becomes.chunk-card-collapsible, also setrole="button"+tabindex="0"and add akeydownhandler that mirrors the existing click toggle.toggleCard()helper so click and keydown share one path.The keydown handler skips when focus is in:
.chunk-card-actions— so a Copy/Edit/Delete button's Enter doesn't also toggle the parent card..chunk-card-edit-area— so a textarea's Enter newline doesn't collapse the card mid-edit.Drag-vs-click detection on the click path is preserved unchanged.
tests/test_web_a11y.py— newTestChunkCardA11yclass, three pin assertions:aria-labelis set on every card.role="button"+tabindexlive inside the.chunk-card-collapsibleactivation block (i.e. only on toggle-able cards, matching the issue's "informational" vs "clickable" distinction).keydownhandler exists with both required exclusion zones.Mutation-validated: removing
role=from the activation block fails the relevant test.Why this scoping
role="button"to a non-toggle card would be a lie. This matches issue List-row a11y: search / sources / timeline rows lack role / aria-label #700's option-1 / option-2 distinction.aria-labeltext uses data already on the card; no new server data, no i18n keys (chunk_type / line numbers are not localized prose).Out of scope
role="list"on the chunk-list container +role="listitem"on non-collapsible cards — could be a small follow-up but isn't required to close List-row a11y: search / sources / timeline rows lack role / aria-label #700.Test plan
uv run pytest packages/memtomem/tests/test_web_a11y.py— all green (this PR + fix(web): role=button + aria-label on search result rows (#700) #808 + fix(web): role=button + aria-label on Timeline rows (#700) #809 each contribute their own class).role=from the collapsible block fails the specific test.uv run ruff check packages/memtomem/src packages/memtomem/testsclean..chunk-card-collapsiblecard, press Enter — confirm expand. Press Enter while inside the textarea after Edit — confirm the card does NOT collapse.Merge interaction with #808 and #809
All three PRs touch
tests/test_web_a11y.py: each creates the file with the same fixtures + helpers and adds its own test class. Whichever lands first leaves the others with a trivial rebase to keep all classes side-by-side.Refs #700, umbrella #702.
🤖 Generated with Claude Code