Skip to main content

Design system components

Avatar

Profile image, initials, link, or menu trigger.

Status: stable. Group: display. Markdown version: /design-system/components/avatar.md

When to use

Avatar renders a person or entity mark: the image when imageUrl resolves, otherwise initials derived from name. It scales through the size tokens and can act as a link (clickable + destinationUrl) or as a menu trigger (menuItems + menuLabel) with an in-place dropdown. Always pass name; it feeds both the initials fallback and the accessible naming.

When not to use

  • Do not render two interactive children inside Avatar (link plus menu); the contract is exactly one interaction mode per instance.
  • Do not nest an Avatar inside a Button. Pick one; Avatar already owns the click affordance when clickable, and Button owns it when not.
  • Do not use variant="initials" to hide a broken image pipeline; fix the source, the fallback is for genuinely imageless users.

Look-alikes

  • Button: Do not nest an Avatar inside a Button. Pick one; Avatar already owns the click affordance when clickable, and Button owns it when not.

Props

Avatar props
PropTypeDefaultDescriptionRequired
namestringnoneNo description in the contract.No
imageUrlstring | { default: string } | StaticImageDatanoneNo description in the contract.No
clickablebooleannoneNo description in the contract.No
destinationUrlstringnoneNo description in the contract.No
sizeAvatarSizemdAvatar size: token sizes sm/md/lg/xl (2/2.5/3/4rem) are canonical; any CSS length is accepted as an escape hatch. Default md.No
srcSetstringnoneNo description in the contract.No
sizesstringnoneNo description in the contract.No
loading"lazy" | "eager"lazyNo description in the contract.No
decoding"auto" | "sync" | "async"asyncNo description in the contract.No
menuItemsAvatarMenuItem[]noneWhen provided, renders an in-place dropdown menu triggered by the avatar.No
menuLabelstringnoneAccessible label announced for the avatar menu trigger.No
variant"image" | "initials"imageControls whether the avatar prefers an image or initials.No
altstringnoneOverrides the image alt text (defaults to name). Pass "" when the name is already printed beside the avatar, so it is not read twice.No

Variants

  • Available variants: image, initials (default image).
  • Available sizes: sm, md, lg, xl, 2rem, 2.5rem, 3rem, 4rem, 5rem, 6rem, 7rem, 8rem (default md).
  • Allowed loading values: lazy, eager (default lazy).
  • Allowed decoding values: auto, sync, async (default async).

Invalid combinations

The contract records no invalid combinations.

Keyboard

The contract records no keyboard interaction.

Rules

Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.

Avatar rules
LevelRuleHow it is checked
MUSTARIA: Menu trigger needs accessible name.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTARIA: Image alt from name.Not yet verified: no evidence record. WCAG 4.1.2.
MUSTRequired stories produce no axe violations at the configured severity.Automated by npm run test:stories:matrix:ci. WCAG 2.5.8.
MUSTThe accessibility tree (role, name, state) matches the committed snapshot for every required story.Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2.
MUSTThe component remains legible and operable under a real browser forced-colors: active pass.Automated by npm run test:stories:hc.
MUSTA human completed an end-to-end accessibility review of this component.Manual review, last on 2026-11-04.
SHOULDAlways provide name, even with an image; it is the initials fallback and the accessible name.Not stated in the contract.
SHOULDProvide srcSet/sizes for photographic avatars so dense grids do not ship desktop images to mobile.Not stated in the contract.
SHOULDUse menuLabel to say what the menu does ("Account menu"), not who the person is.Not stated in the contract.
SHOULDKeep loading lazy (default-friendly) in long lists; eager only above the fold.Not stated in the contract.
SHOULD NOTDo not wrap Avatar in another link/button when clickable or menuItems already make it interactive; nested controls break AT.Not stated in the contract.

Install and import

  • Install: npm install @digitaltableteur/react (version 0.9.1, restricted access on npm).
  • Import: import { Avatar } from "@digitaltableteur/react";
  • Entry point: @digitaltableteur/react/identity exports it too.
  • Styles: import @digitaltableteur/react/style.css once at the app boundary.
  • Also available as the custom element <dt-avatar>; see the custom elements manifest.