feat(Avatar): add tooltip prop (string | boolean) for name-on-hover (#4164)#4219
Draft
cixzhang wants to merge 1 commit into
Draft
feat(Avatar): add tooltip prop (string | boolean) for name-on-hover (#4164)#4219cixzhang wants to merge 1 commit into
cixzhang wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
github-actions
Bot
requested review from
cvkxx,
ernestt,
kentonquatman and
rubyycheung
July 22, 2026 23:05
Contributor
Author
Self-review — Quick Self-Review checklist (Component Build Protocol)
Spec compliance / deviations:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds one prop to
Avatar:tooltip?: string | boolean(default effectivelytrue), giving every named avatar an identify-on-hover tooltip for free.true→ show the avatar'snameon hover and keyboard focus<Tooltip>)false→ no tooltipname/alt(decorative), or atrue/omitted tooltip with an empty/whitespacename→ no tooltipCloses #4164.
Why
Avataralready exposes identity to assistive tech via the rootaria-label(alt || name), but a sighted mouse/keyboard user hovering an unfamiliar face gets nothing, and every consumer that wants it has to hand-roll<Tooltip content={name}><Avatar .../></Tooltip>— boilerplate that drifts and is applied inconsistently. Making the name tooltip a built-in default matches how mature avatar UIs (facepiles, comment headers, contributor stacks) behave.API — convention reuse
tooltip?: string | booleanreuses two established system conventions rather than inventing a new one:tooltip?: stringships onButton,Link,StatusDot,ToggleButton.string | booleandual-purpose union ships onLink.download/TopNavItem.download(bool toggles, string configures).The only intentional divergence: the existing
tooltip?: stringprops default to off, whereas Avatar defaults to show the name — because Avatar uniquely already holds the name. For rich/ReactNode tooltips, wrap inTooltip/HoverCardand settooltip={false}(kept text-only on purpose; no placement/delay knobs on Avatar).Avatar owns the tooltip (no wrapper DOM)
Avatar owns its tooltip via the existing
useTooltiphook — the same patternButtonuses — attaching the hook's ref to the root and rendering the tooltip as a sibling. No extra wrapper<div>, no changes toTooltip/HoverCard/Layer.Deliberate: no auto-disable when wrapped
Per the approved spec, there is no automatic overlay detection and no shared
OverlayAncestorContext. The name tooltip is a purely visual concern; accessibility never depends on it (the rootaria-labelis always correct). If a consumer layers their ownTooltip/HoverCard, they explicitly opt out withtooltip={false}— trivial and discoverable with this same prop. Wrapping without opting out yields at most a visual double-popup, never an a11y problem. (If this proves a real foot-gun in practice, detection can be revisited later.)Accessibility
aria-labelstaysalt || nameunconditionally, independent of the tooltip. Decorative avatars stayrole="presentation"+aria-hiddenand get no tooltip.aria-describedby(its text duplicates the root's accessible name, so describing it too would double-announce the same name).aria-describedby(it adds information), composing with any consumer-suppliedaria-describedby— matchingButton.div[role="img"], not natively focusable) gainstabIndex={0}+ a focus-visible ring so keyboard users can reveal it (WCAG 1.4.13 / 2.1.1) — matchingTimestamp/Button. No tab stop when the tooltip is off.Testing
New tests (all green, plus the existing Avatar suite unchanged):
name;tooltip="…"shows the custom string (not the name);tooltip={false}renders no tooltiparia-labelunchanged across default / disabled / custom-string / alt casesaria-describedbyfor the default name tooltip; present (and pointing at the tooltip layer) for a custom string; consumeraria-describedbycomposed for custom, preserved untouched for defaultrefforwarded to the rootAlso verified
TooltipandAvatarGroupsuites stay green.Files (Avatar-only)
packages/core/src/Avatar/Avatar.tsxpackages/core/src/Avatar/Avatar.test.tsxpackages/core/src/Avatar/Avatar.doc.mjsapps/storybook/stories/Avatar.stories.tsx(default / custom / disabled stories).changeset/avatar-name-tooltip.mdNo changes to
Tooltip,HoverCard, orLayer.