# Tooltip / aria-label spec: which panel controls need which Status: implemented (§1a–§1c complete, test coverage added) Owner: ux-dev-1 Implementation status: All icon-only controls listed in §1a have been retrofitted with aria-label + title + matching Radix Tooltip (via PR #476). Test coverage is provided by per-control regression test files in `panel/src/components/**/\__tests__/`. Last updated: 2026-07-11 Surface: every icon-bearing interactive control in `panel/src/components` — surveyed against the sidebar (`layout/sidebar.tsx`), header (`layout/header.tsx`), task detail (`tasks/task-detail/`, `tasks/task-actions.tsx`), kanban (`kanban/core/`, `kanban/shared/`), the dashboard queues (`dashboard/*-queue.tsx`, `dashboard/command-center.tsx`), and metrics (`metrics/*.tsx`). ## Dial read Per the team design bar, the panel is dense product UI, not a marketing surface: - **DESIGN_VARIANCE:** 1 — this spec changes no layout or grid; it is a copy/markup rule for existing controls. - **MOTION_INTENSITY:** 2 — tooltips use the existing Radix primitive (`ui/tooltip.tsx`), whose default fade/zoom-on-open is the motion budget; nothing in this spec adds a new transition. - **VISUAL_DENSITY:** 8 — the panel packs many small icon-only affordances per row (kanban cards, table action cells, queue rows); the density rule most relevant here is the "noisy vs. informative" line in §3 — every tooltip added to a dense row is one more thing competing for attention, so it must earn its place. ## Problem (Resolved) This spec resolved the panel's mixed accessible-naming strategies for icon-only controls by establishing a single rule: all icon-only controls must carry a mandatory `aria-label` (§1a), optionally with a matching visible Tooltip (§1b). All controls listed below have been retrofitted to the correct pattern (verified 2026-07-11): | Component | Pattern | Test Coverage | |---|---|---| | `layout/header.tsx:59-68` (refresh button) | ✅ `aria-label` + `title` + Tooltip | ✅ `header.test.tsx` | | `ui/copy-button.tsx:64-74` | ✅ `aria-label` + `title` + Tooltip | ✅ Implicit (component pattern) | | `kanban/core/kanban-card.tsx:237-253` (move-forward button) | ✅ `aria-label` + `title` + Tooltip | ✅ `kanban-card-aria.test.tsx` | | `notifications/notification-bell.tsx:24-31` (bell button) | ✅ `aria-label` + `title` + Tooltip | ✅ `notification-bell.test.tsx` (NEW) | | `tasks/task-detail/task-header.tsx:476-478` (back-arrow button) | ✅ `aria-label` + `title` + Tooltip | ❌ Not covered — `header.test.tsx` only renders `layout/header.tsx`, not this component | | `tasks/task-actions.tsx:145-147` (overflow-menu trigger) | ✅ `aria-label` + `title` + Tooltip | ❌ Not covered — `header.test.tsx` only renders `layout/header.tsx`, not this component | | `layout/sidebar.tsx:170-182` (collapse-rail toggle) | ✅ `aria-label` + `title` + Tooltip | ✅ `sidebar.test.tsx` | | `kanban/core/kanban-card.tsx:122-128` (drag handle) | ✅ `aria-label` + `title` + Tooltip | ✅ `kanban-card-aria.test.tsx` | | `kanban/shared/assignee-avatar.tsx` (initials badge) | ✅ `aria-label` + Tooltip with full name | ✅ `assignee-avatar.test.tsx` | Separately, some controls that DO have a visible label still lack a tooltip where one would help (`kanban/shared/assignee-avatar.tsx` shows only two-letter initials, with nothing disambiguating which agent that is), while others already use tooltips correctly for genuinely supplementary info (`kanban-card.tsx:137-151`'s sequence-number badge, `header.tsx:35-50`'s "Coming Soon" search tooltip). This spec gives every future control a three-way answer — mandatory aria-label, recommended tooltip, or neither — plus the copy rule for whichever applies. ## 1. Classification ### 1a. `aria-label` is mandatory **Any interactive control (`button`, a `Link`/`` wrapping a `Button`, a dropdown/popover trigger) whose only visible content is an icon.** No exceptions — this is a WCAG requirement, not a style preference (see §4). Examples already in the codebase that need this fixed: - `notifications/notification-bell.tsx:24` — `