fix(PUPIL-1759): announce tooltip content only when opened#720
Open
paulsweeting wants to merge 3 commits into
Open
fix(PUPIL-1759): announce tooltip content only when opened#720paulsweeting wants to merge 3 commits into
paulsweeting wants to merge 3 commits into
Conversation
Stop exposing hint text to assistive tech on focus by removing the always-hidden describedby target, and announce on open via a live region with conditional aria-describedby for refocus recovery. Co-authored-by: Cursor <cursoragent@cursor.com>
Reflect OakInfo closed-state markup used by the embedded Code colour tooltip. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR adjusts the accessibility behavior of tooltip-based hint/info components so tooltip content is not exposed to assistive technologies while closed, and is announced when opened.
Changes:
- Updates
OakQuizHintandOakInfoto conditionally applyaria-describedbyonly when open and to setaria-expandedon the trigger. - Adds tests asserting the trigger is not associated with tooltip content while closed and that content is announced on open.
- Updates Storybook args and snapshots impacted by the markup/ARIA changes.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/components/owa/pupil/quiz/OakQuizHint/OakQuizHint.tsx | Updates ARIA wiring and adds an announcement mechanism when opening the hint tooltip. |
| src/components/owa/pupil/quiz/OakQuizHint/OakQuizHint.test.tsx | Adds coverage for “not described while closed” and “announced when opened”. |
| src/components/owa/pupil/quiz/OakQuizHint/snapshots/OakQuizHint.test.tsx.snap | Snapshot update due to markup/ARIA changes. |
| src/components/owa/pupil/lesson/OakLessonBottomNav/snapshots/OakLessonBottomNav.test.tsx.snap | Snapshot update due to embedded OakQuizHint markup changes. |
| src/components/owa/OakInfo/OakInfo.tsx | Updates ARIA wiring and adds an announcement mechanism when opening the info tooltip. |
| src/components/owa/OakInfo/OakInfo.test.tsx | Adds coverage for “not described while closed” and “announced when opened”. |
| src/components/owa/OakInfo/OakInfo.stories.tsx | Ensures the story provides the required id prop. |
| src/components/owa/OakInfo/snapshots/OakInfo.test.tsx.snap | Snapshot update due to markup/ARIA changes. |
| src/components/owa/OakCodeRenderer/snapshots/OakCodeRenderer.test.tsx.snap | Snapshot update due to embedded OakInfo markup changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+72
to
+76
| const announcement = getByTestId("quiz-hint-announcement"); | ||
| expect(announcement).toHaveAttribute("aria-live", "polite"); | ||
| expect(announcement).toHaveTextContent( | ||
| "The answer is right in front of your eyes", | ||
| ); |
Comment on lines
+56
to
+60
| const announcement = getByTestId("info-tooltip-announcement"); | ||
| expect(announcement).toHaveAttribute("aria-live", "polite"); | ||
| expect(announcement).toHaveTextContent( | ||
| "The answer is right in front of your eyes", | ||
| ); |
Comment on lines
+39
to
+43
| {isOpen && ( | ||
| <div | ||
| id={id} | ||
| aria-live="polite" | ||
| aria-relevant="all" |
Comment on lines
+54
to
+60
| {isOpen && ( | ||
| <div | ||
| id={id} | ||
| aria-live="polite" | ||
| aria-relevant="all" | ||
| style={{ position: "absolute", left: "-9999px" }} | ||
| data-testid={`${id}-announcement`} |
Live regions must exist before content changes to fire announcements; our conditional mount never triggered the chime. Disclosure semantics (aria-expanded, conditional aria-describedby) are sufficient per a11y QA. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Comment on lines
46
to
51
| buttonProps={{ | ||
| "aria-describedby": id, | ||
| "aria-expanded": isOpen, | ||
| "aria-describedby": isOpen ? id : undefined, | ||
| "aria-label": isOpen ? "close info tooltip" : "open info tooltip", | ||
| ...buttonProps, | ||
| }} |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.



Link to the design doc
N/A — accessibility behaviour fix (no visual design change).
Notion: PUPIL-1759 — Announce tooltip information once tooltip is open
Audit finding: Tooltip information is announced before opening
A link to the component in the deployment preview
Storybook (Preview Env):
Why no
aria-live?Initial implementation included an off-screen
aria-live="polite"region (mirroringOakCopyLinkButton). Internal a11y QA testing showed the live-region announcement chime never fired — consistent with known behaviour when a live region is mounted already populated rather than existing empty and then updating (Sara Soueidan, TetraLogical).VoiceOver does announce hint content on open via disclosure semantics on the focused trigger:
aria-expandedtoggles totruearia-describedbypoints at the off-screen description node (only when open)OakInfoalso updatesaria-label(open→close info tooltip)That matches the interaction model: focus stays on the button, so a live region is unnecessary. The fix for the audit finding is not exposing description until open — not a background status update.
The off-screen description
divremains as thearia-describedbytarget (visible tooltip is portaled separately). A follow-up could pointaria-describedbyat the portaled tooltip to remove duplicate DOM.Testing instructions
Automated
pnpm test:ciforOakInfo,OakQuizHint,OakCodeRenderer,OakLessonBottomNavStorybook (screen reader)
OakInfoandOakQuizHintstories abovearia-expanded/aria-describedby(and label change onOakInfo); no live-region chime expectedaria-describedbyOWA integration (after release / yalc)
OakInfo(e.g. programme units)OakQuizHintviaOakLessonBottomNavACs
aria-expanded="true"is set on the triggeraria-live)aria-describedbyOakInfoStorybook story includes requiredidpropComponents changed:
OakInfo,OakQuizHint(oak-componentsonly — OWA consumes via version bump after release)Reviewer checklist notes
OakInfo,OakQuizHint,OakLessonBottomNav, andOakCodeRenderer(embeddedOakInfoconsumer) — expected collateral from markup changearia-liveremoved after manual a11y QA; Copilot duplicate-DOM feedback partially addressed (live region attrs gone; description target retained)Made with Cursor