Zetta v1.6

Components · Data display & feedback

Avatar

A fully rounded user image or initials on a muted surface. Five sizes from 16px (dense table cells) to 48px (profile headers); use 44px or larger for anything tappable.

Preview

AC AC AC AC

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Avatar" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `avatar` spec (variants: xs, sm, md, lg, xl) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `avatar` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

  ╭──────╮
  │  AB  │  ← initials fallback (sizeMd: 40px)
  ╰──────╯

Parts:

  • Container — circular, {colors.surface-muted} fill when no image
  • Imagecover fit, same circular clip as container
  • Initials — 13px / 500 Geist, {colors.muted}, centered
State Visual
Default — image User photo, cropped to circle
Default — initials {colors.primary-bg} fill, {colors.primary} initials text
Default — fallback icon {colors.surface-muted} fill, {colors.muted} person icon
Loading Skeleton shimmer (same dimensions)
Online indicator {colors.success} dot, bottom-right
Offline indicator {colors.border-strong} dot, bottom-right
Busy indicator {colors.warning} dot, bottom-right

When to use

  • Representing a person in a list, card, comment, or header.
  • Representing a project (square shape) or AI agent (hexagon shape).

When not to use

  • As decoration with no semantic meaning — use an illustration instead.
  • When the person's identity is not relevant to the context.

Do

  • Always provide name — used for initials fallback and screen reader announcements.
  • Use sizeLg (44px) or larger for any avatar the user can tap or click.
  • Use circle for people, square for projects/repos, hexagon for AI agents.

Don't

  • Don't show sizeXs or sizeSm avatars as interactive elements — their touch target is too small.
  • Don't use generic placeholder text ("User") as the name value.
  • Initials: max 2 characters. "John Doe" → "JD". Single name → first letter only.
  • Alt text for image avatars: user's full name. e.g. alt="John Doe".
  • Fallback order: photo → initials → icon. Never show broken image.
  • Status indicator label: aria-label="John Doe — Online" on the avatar container.

Keyboard

Avatar is non-interactive by default and has no keyboard behavior. When used as a trigger (e.g. inside a button or link), keyboard interaction is inherited from the parent interactive element: Tab moves focus to it; Enter/Space activates the action.

Accessibility

  • Alt text: derive from name prop — "Alice Bernstein's avatar".
  • Decorative avatars: add aria-hidden="true" when the avatar is purely decorative and the name appears as adjacent text.
  • Interactive avatars: add role="button" and aria-label describing the action ("View Alice Bernstein's profile").
  • Minimum touch target: use sizeLg (44px) for all tappable avatars.

Spec

Values and token references resolved straight from the Zetta spec.

avatar
backgroundColor
{colors.surface-muted}
textColor
{colors.muted}
borderRadius
{rounded.full}
fontFamily
Geist
fontSize
13px
fontWeight
500
sizeXs
16px
sizeSm
24px
sizeMd
40px
sizeLg
44px
sizeXl
48px
avatar-image
borderRadius
{rounded.full}
objectFit
cover
avatar-presence
size
10px
borderRadius
{rounded.full}
borderWidth
2px
borderColor
{colors.canvas}
position
absolute
bottom
0
right
0
avatar-presence-online
backgroundColor
{colors.success}
avatar-presence-away
backgroundColor
{colors.warning}
avatar-presence-offline
backgroundColor
{colors.muted}
avatar-presence-busy
backgroundColor
{colors.danger}
avatar-badge-overlay
position
absolute
top
-2px
right
-2px
borderWidth
2px
borderColor
{colors.canvas}
borderRadius
{rounded.full}
minSize
16px
display
flex
alignItems
center
justifyContent
center

Known gaps

  • Avatar Group — specified as a separate component (zetta-avatar-group-v1_6.md); not yet built.