Skip to content

a11y(2.1.1): navigation primitives — replace hover-only CSS :after label tooltip with focusable Tooltip#3529

Open
rosanusi wants to merge 2 commits into
mainfrom
wcag/2.1.1-navigation-css-tooltip-disclosure
Open

a11y(2.1.1): navigation primitives — replace hover-only CSS :after label tooltip with focusable Tooltip#3529
rosanusi wants to merge 2 commits into
mainfrom
wcag/2.1.1-navigation-css-tooltip-disclosure

Conversation

@rosanusi

Copy link
Copy Markdown
Contributor

Description & motivation 💭

Three navigation primitives (navigation-item, navigation-button, navigation-badge) rendered their text label as a CSS :after pseudo-element keyed exclusively to :hover via group-data-[nav=closed]:hover:after:flex. In the collapsed rail, keyboard users tabbing through the icons received no visible label and no accessible description — pseudo-elements are not in the accessibility tree.

This PR replaces the :after/data-tooltip block in each component with the Tooltip primitive (right, hide={$navOpen}), which provides:

  • Label on focus — the tooltip appears when the trigger (<a> / <div role="button">) receives keyboard focus
  • aria-describedby linkage — screen readers announce the label as a description
  • Escape-to-dismiss — keyboard users can hide the tooltip without losing focus
  • Mouse parity — hover path unchanged; the Tooltip's mouseenter/mouseleave drives the same popover

hide={$navOpen} suppresses the tooltip when the nav is expanded, since the inline label is already visible in that state — matching the original group-data-[nav=closed] gating.

Depends on: the Tooltip primitive must support focusin/focusout + Escape-to-dismiss + role="tooltip" + aria-describedby (tracked in 1.4.13-tooltip.md). This PR is drafted to land after that work.

Files changed (3):

  • src/lib/holocene/navigation/navigation-item.svelte (finding Install testing #1)
  • src/lib/holocene/navigation/navigation-button.svelte (finding #2a)
  • src/lib/holocene/navigation/navigation-badge.svelte (finding Add navigation #3)

SC: 2.1.1 Keyboard (Level A) — current verdict: Fails → Supports (for these three primitives)

Screenshots (if applicable) 📸

No visual change on hover. New behaviour: tooltip appears on keyboard focus in collapsed rail state.

Design Considerations 🎨

None — the Tooltip primitive reuses existing visual styling. Layout classes controlling icon visibility in nav-open state are preserved on the Tooltip wrapper.

Testing 🧪

How was this tested 👻

  • Manual testing

Steps for others to test: 🚶🏽‍♂️🚶🏽‍♀️

  1. Collapse the side nav and Tab through every nav item, nav button, and nav badge in order. Confirm a tooltip appears on each focus.
  2. While a tooltip is visible, press Escape — confirm the tooltip dismisses without moving focus.
  3. Expand the nav and Tab through again. Confirm no tooltip appears (the inline label is already visible).
  4. Screen reader (VoiceOver / NVDA): on a focused collapsed nav item, confirm the announcement includes the label as a description.
  5. Hover regression: confirm the popover still appears on mouse hover for all three primitives.
  6. axe-core run on / (sidebar always present): zero new violations.

Checklists

Draft Checklist

  • Blocked on 1.4.13-tooltip.md — Tooltip primitive must have focus + Escape + aria-describedby support before merging
  • VoiceOver + NVDA smoke test on collapsed rail

Merge Checklist

  • 1.4.13-tooltip.md fix is merged and the Tooltip primitive supports keyboard focus
  • All three nav primitives tested with keyboard Tab in collapsed rail
  • Hover regression confirmed

Issue(s) closed

Closes findings #1, #2a, #3 from audit-output/issues/2.1.1-keyboard-audit.md.

Docs

Any docs updates needed?

No doc changes needed.

A11y-Audit-Ref: 2.1.1-navigation-css-tooltip-disclosure

…primitive

The CSS :after / data-tooltip pattern on the three nav primitives fired only
on :hover with no :focus companion, making labels invisible to keyboard users
in the collapsed rail. Replace all three with the Tooltip component (right,
hide={$navOpen}) so labels appear on focus, are linked via aria-describedby,
and are dismissible with Escape.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
holocene Ready Ready Preview, Comment Jun 11, 2026 3:23pm

Request Review

@github-actions github-actions Bot added a11y Accessibility audit PR a11y:bucket-3 Bucket 3: engineer required a11y:sc-2.1.1 labels Jun 10, 2026
@rosanusi rosanusi marked this pull request as ready for review June 11, 2026 15:42
@rosanusi rosanusi requested a review from a team as a code owner June 11, 2026 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a11y:bucket-3 Bucket 3: engineer required a11y:sc-2.1.1 a11y Accessibility audit PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant