Skip to content

fix(site/src): make tooltips with links keyboard and screen reader accessible - #30424

Open
chrifro wants to merge 2 commits into
mainfrom
a11y-interactive-hover-popovers
Open

chrifro wants to merge 2 commits into
mainfrom
a11y-interactive-hover-popovers

Conversation

@chrifro

@chrifro chrifro commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

🤖 This PR was created by Coder Agents on behalf of @chrifro.

Tooltips with links in them couldn't be reached by keyboard or screen readers, because the ARIA tooltip pattern doesn't allow interactive content. This adds an opt-in <Tooltip interactive>. It still opens on hover and looks the same, but it also opens on focus, lets Tab move into the content, stays open after a click or Enter, and closes on Escape. Plain tooltips are unchanged.

Fixes DEQ-473 (workspace permissions), DEQ-378 (audit log details) and the rest of DEQ-287 (AI Gateway). It also converts every InfoTooltip help icon, the connection log details and the agent "Troubleshoot" link. Follow-up to #30403.

housekeeping edit by @aqandrew: also fixes DEQ-568, fixes DEQ-522, fixes DEQ-223

Before After
Hover
Tab from ⓘ skips the link focuses the link

Review notes

Why opt-in instead of changing every tooltip: at least 50 of the 152 tooltip triggers are buttons or links with their own action, such as refresh or copy. Interactive mode takes over the trigger's click, uses dialog semantics instead of a description, and changes the Tab order, so applying it to every tooltip would break those triggers. It also can't be chosen automatically, because the content isn't rendered until the tooltip opens. That means a new tooltip with links needs interactive added by hand. A lint rule could enforce that later.

Worth a close look:

  • Focus management: the content is portaled, so the Tab handoff is written by hand: Tab on the trigger moves to the first focusable element in the content, and leaving the content (Tab past the end, Shift+Tab before the start, Esc) returns focus to the trigger so tab order stays intact.
  • Event isolation: the trigger and content stop click and keydown from propagating so clickable table rows don't fire. Ancestors no longer see those events.
  • Wrappers: Tooltip, TooltipTrigger and TooltipContent are now thin wrappers instead of Radix re-exports, so every tooltip goes through them.
  • Not converted: ResourcesChart bars, whose link has to="" and goes nowhere.
Verification
  • New tests in Tooltip.test.tsx cover keyboard order, Escape, hover not stealing focus, and click pinning.
  • pnpm lint is clean, and all 283 unit test files and all 464 Storybook files pass.
  • In a real browser, the Templates help icon behaves as described, and a plain tooltip (footer refresh button) is unchanged.
  • The audit, connection log, sharing and AI Gateway call sites are covered by stories only: the dev deployment has no data for them, and AI Gateway is paywalled.

…cessible

Tooltips whose content contains links or buttons used the ARIA tooltip
pattern, which cannot hold interactive content: keyboard users could not
reach the links and screen readers did not expose them.

Add an interactive mode to Tooltip. <Tooltip interactive> renders a
non-modal popover that still opens on hover and looks the same, but also
opens on keyboard focus, lets Tab move into the content, pins open on
click or Enter, and closes on Escape. Plain tooltips are unchanged.

Use it for InfoTooltip and for the workspace sharing indicator, audit and
connection log details, agent warning, and AI Gateway prompt attribution
and AI Governance tooltips.
@linear-code

linear-code Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Keep call-site edits minimal by moving the trigger button reset and focus
ring into the interactive trigger, and leaving TooltipProvider wrappers in
place. Leave the content through the trigger on Tab so the browser
continues the sequence, which removes the custom next-element lookup.
@chrifro
chrifro marked this pull request as ready for review October 7, 2026 08:07
@chrifro
chrifro requested a review from aqandrew October 7, 2026 08:07

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.

1 participant