feat(lab): InfoTip — accessible info-icon help affordance (RFC #3349)#3355
Conversation
Lab experiment accompanying RFC #3349. Composes core Tooltip + Icon (registry "info" icon) behind a pre-wired accessible button trigger: aria-label (default "More information"), Tab-reachable, tooltip on hover AND keyboard focus, Escape dismissal.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Analysis Report📚 Storybook PreviewView Storybook for this PR 🧪 Sandbox PreviewView Sandbox for this PR No new or modified components detected. Bundle Size Summary
Accessibility AuditStatus: No accessibility violations detected. Generated by PR Enrichment workflow | Storybook | Sandbox | View full report |
cixzhang
left a comment
There was a problem hiding this comment.
Internally this is the help message. I think we should use hover card if the content is more complex than a string since tooltips have an inverted palette and we should also make sure to double check that the content is accessible.
cixzhang
left a comment
There was a problem hiding this comment.
Thanks. Since this is in lab I'll stamp so we can see it.
What
Adds
InfoTipto@astryxdesign/lab: an inline info-icon help affordance — a small "i" button that reveals a tooltip on hover and keyboard focus.Tooltip+Icon(registry"info"icon viagetIcon(), no hardcoded SVG) + a real<button>trigger.content(ReactNode, mirrors Tooltip'scontent),label(accessible name, default"More information"),size('xsm' | 'sm' | 'md' | 'lg', maps 1:1 to Icon sizes; default'sm').:hovercolor change guarded behind@media (hover: hover); focus ring per system convention (2px solid --color-accenton:focus-visible, matching Button/IconButton).isOpen(dismissed until pointer/focus leaves the trigger, then triggers re-arm).InfoTip.doc.mjsfollows the lab doc convention (docs / docsZh / docsDense).Why
Gap report from an internal-tool builder (Meridian): they needed an "i" info/help affordance next to labels/values and hand-composed an info
Iconinside aTooltip. This is one of the most common internal-tools affordances (permission notes, metric definitions, field help).The a11y-wiring argument (see RFC #3349):
Tooltiprequires the consumer to supply a correct trigger, and the naiveIcon-in-Tooltipcomposition gets accessibility wrong by default —Iconrendersaria-hiddenand unfocusable, so keyboard users never see the tooltip, there is no accessible name, and no touch-sized target. Composition can do this correctly; the value of InfoTip is that the a11y wiring naive composition (and LLM codegen) gets wrong is pre-wired. No new visuals.Testing
npx vitest run packages/lab/src/InfoTip— 9/9 passed: renders with default accessible name; customlabel;aria-describedbylinks trigger to tooltip layer; trigger Tab-focusable; tooltip on hover; tooltip on keyboard focus; Escape closes; re-opens after Escape once trigger is left; ReactNode content.npx vitest run packages/lab— 116/116 passed (8 files, whole lab package).pnpm -F @astryxdesign/lab lint— clean.pnpm -F @astryxdesign/lab typecheck— clean.Open questions
InfoTipvs ahelpTipslot onFieldLabel/Field? External systems diverge (Ant/Carbon/Polaris ship a component; Radix/shadcn leave it to composition) — worth vibe-testing both shapes.contentmirrorsTooltip; is that the right family convention, or should it bechildren?Tooltipsuppresses hover on touch devices; should InfoTip add explicit tap-to-toggle before graduation?Notes
No changeset:
@astryxdesign/labisprivate: true(canary-only) andscripts/check-changesets.mjsrejects changesets referencing private packages — PR #3235's changeset targeted@astryxdesign/coreonly because it also changed core. This PR touches onlypackages/lab.