Avatar
An identity mark with an image → initials → icon fallback chain.
Usage
import { Avatar } from '@epilot/spark-ui/avatar'<Avatar name="Anna Schmidt" src={photoUrl} />Use Avatar for a person, organisation, or asset that needs a fixed-size identity
mark: a photo when there is one, otherwise the name's initials, otherwise an
icon. name is required — it drives both the accessible label and the
derived initials. For a photo or user-generated image that needs a fixed
frame instead of an identity label, use
Thumbnail.
Examples
Sizes
size sets the frame from sm to xl; both the frame and the text scale
with the density/scaling knobs.
Shapes
shape="circle" (default) is fully round. shape="square" rounds the
corners per size, following the theme's radius knob.
Colors
Set the color prop to accent, neutral, success, warning, or danger
to recolour the fallback fill and initials. The default styleVariant="soft"
owns the foreground colour; <Theme accentColor> still works for arbitrary
accent colours outside this fixed set.
Fallback chain
A loading src shows the image. No src, or a failed load, falls back to
the initials derived from name (or the initials override). Empty
initials — a blank/whitespace name, or initials="" — fall back to the
icon node, and with no icon the fallback is a bare fill.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | required | Drives the root's aria-label and, unless initials is set, the derived initials. |
src | string | — | Image URL. Absent, empty, or a failed load falls through to the initials/icon chain. |
initials | string | derived | Overrides avatarInitials(name). Pass "" to skip straight to the icon fallback. |
icon | React.ReactNode | — | Last-resort fallback when the initials are empty. A rendered node, never an icon-name string. |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Frame size. |
shape | 'circle' | 'square' | 'circle' | Corner treatment. |
styleVariant | 'solid' | 'soft' | 'surface' | 'ghost' | 'outline' | 'soft' | Fallback fill treatment; always emitted as data-style. |
color | 'accent' | 'neutral' | 'success' | 'warning' | 'danger' | 'accent' | accent omits data-accent-color; neutral→gray, success→green, warning→orange, danger→red |
imgProps | Base UI Avatar.Image props (minus src) | — | Escape hatch, e.g. onLoadingStatusChange, srcSet, crossOrigin. |
The component also forwards all other span HTML attributes (including
className, which merges with the base styling) and a ref to the root
<span>.
avatarInitials(name) is also exported: it splits name on spaces, takes
the first character of each word (surrogate-pair safe), drops empty parts,
keeps the first two, and uppercases the result.
Accessibility
- The root carries
role="img"andaria-label={name}, so there is exactly one accessible name whether the image, initials, or icon is showing. Pass your ownaria-label/aria-hiddento override it — it wins over the default. - The image renders with
alt=""and the fallback witharia-hidden, so the root label stays the single source of truth. - When the name is already visible as text right beside the avatar (e.g. an
entity header), pass
aria-hiddento the avatar to avoid a double announcement. - Avatar is non-interactive: it has no hover, focus, or keyboard handling.
Wrap it in a
Button(styleVariant="ghost") or a link to make it clickable.