Skip to content

fix(PUPIL-1759): announce tooltip content only when opened#720

Open
paulsweeting wants to merge 3 commits into
mainfrom
fix/PUPIL-1759-announce-tooltip-on-open
Open

fix(PUPIL-1759): announce tooltip content only when opened#720
paulsweeting wants to merge 3 commits into
mainfrom
fix/PUPIL-1759-announce-tooltip-on-open

Conversation

@paulsweeting

@paulsweeting paulsweeting commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

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 (mirroring OakCopyLinkButton). 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-expanded toggles to true
  • conditional aria-describedby points at the off-screen description node (only when open)
  • OakInfo also updates aria-label (openclose 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 div remains as the aria-describedby target (visible tooltip is portaled separately). A follow-up could point aria-describedby at the portaled tooltip to remove duplicate DOM.

Testing instructions

Automated

  • pnpm test:ci for OakInfo, OakQuizHint, OakCodeRenderer, OakLessonBottomNav

Storybook (screen reader)

  1. Open OakInfo and OakQuizHint stories above
  2. Tab to the trigger — confirm hint text is not announced while closed
  3. Activate the button — confirm hint is announced via aria-expanded / aria-describedby (and label change on OakInfo); no live-region chime expected
  4. Tab away and back while open — confirm hint is available again via aria-describedby

OWA integration (after release / yalc)

  • Pupil listing pages using OakInfo (e.g. programme units)
  • Starter/exit quiz journeys using OakQuizHint via OakLessonBottomNav

ACs

  • Tooltip content is not exposed to assistive technologies until the user activates the trigger
  • On activation, aria-expanded="true" is set on the trigger
  • On activation, hint content is announced to screen reader users (via disclosure semantics, not aria-live)
  • While open, users can recover hint text on refocus via conditional aria-describedby
  • Dismiss by activating the trigger again (unchanged interaction)
  • OakInfo Storybook story includes required id prop

Components changed: OakInfo, OakQuizHint (oak-components only — OWA consumes via version bump after release)

Reviewer checklist notes

  • Snapshots updated for OakInfo, OakQuizHint, OakLessonBottomNav, and OakCodeRenderer (embedded OakInfo consumer) — expected collateral from markup change
  • No new exports, tokens, or internal component leaks
  • aria-live removed after manual a11y QA; Copilot duplicate-DOM feedback partially addressed (live region attrs gone; description target retained)

Made with Cursor

paulsweeting and others added 2 commits June 18, 2026 14:55
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>
@vercel

vercel Bot commented Jun 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
oak-components-storybook Ready Ready Preview, Comment Jun 18, 2026 3:22pm

Request Review

@notion-workspace

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 OakQuizHint and OakInfo to conditionally apply aria-describedby only when open and to set aria-expanded on 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 thread src/components/owa/OakInfo/OakInfo.tsx Outdated
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>
@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

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,
}}
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