Skip to content

Avatar

A picture of a person or a thing, at a known size. It draws the picture when there is one and stands in for it with initials, a glyph or a silhouette when there is not, so it is never an empty box.

tsx
import { Avatar } from 'neba';

<Avatar src="/people/jane.jpg" name="Jane Doe" />
<Avatar name="Jane Doe" />
<Avatar shape="square" variant="solid" color="info">N</Avatar>;

Props

PropTypeDefaultDescription
srcstringThe picture. Until it loads(and forever, if it fails) the fallback is what is drawn
srcSetstringCandidate images at other resolutions, as on any img
altstringnameThe picture's alt text. Falls back to name, and to an empty string when there is neither
namestringWho or what this is. It names the picture, the initials are derived from it, and a screen reader hears it instead of them
initialsstringThe initials, written out, for when the first-and-last-word rule derives the wrong ones
shape'circle' | 'square''circle'The crop. square cuts the corners off instead, at roughly 28% of the box
variantshared'solid' | 'outline' | 'text''text'Weight of the surface behind the fallback. Invisible once a picture has loaded, apart from the edge it keeps
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'The box the picture is drawn in: the control heights, so an avatar and the button beside it are the same height
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
elevationshared0 | 1 | 2 | 30Drop shadow depth. 0 means no shadow at all
delaynumberHow long to wait before drawing the fallback, in milliseconds. Stops the initials flashing up in front of a cached picture
imagePropsOmit<ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt'>Anything else the img needs: loading, crossOrigin, referrerPolicy
onLoadingStatusChange(status: 'idle' | 'loading' | 'loaded' | 'error') => voidCalled as the picture moves between its four loading states
childrenReactNodeThe fallback, drawn instead of the initials. An icon, a logo, a single emoji
transitionsharedNebaTransitionAn entrance animation, run once on mount (transition="fade"). Wrap it in an Animate* component for a trigger or a replay

Every other <span> attribute passes through to the root. The <img> takes src, srcSet and alt directly; anything else it needs goes in imageProps.

The shared axes (variant size color elevation) are defined in prop conventions. density is not offered: an avatar has no padding to change.

Examples

variant and color

solid is a filled circle, outline a hairline over a faint panel, text (the default) a tinted plate with no edge. color picks one of the six role colours. All three are invisible behind a loaded picture, apart from the edge they keep.

size

The control height ladder, so an avatar and the Button beside it in a row are the same height: 22, 26, 32, 40 and 48px. The initials are sized off the box rather than off the row, at roughly 40% of the diameter.

shape

circle is the default crop. square cuts the corners off instead, at roughly 28% of the box: use it for a logo or a repository icon, which are drawn to the edges of a rectangle and lose those edges to a round crop.

name and initials

name does three things: it becomes the picture's alt, the initials are derived from it, and a screen reader hears it instead of them.

The rule is the first character of the first word plus the first character of the last: Jane Doe is JD, jane miriam van doe is JD, 홍길동 is . Decomposed accents are recomposed first, so Ängela is Ä and not A. When the rule picks the wrong letters, write them out in initials.

children

children is the fallback, drawn instead of the initials: an icon, a logo, a single emoji. An <svg> inside it is sized to 55% of the box. With no children, no initials and no name, the avatar draws a silhouette.

Which of the three is showing is decided by the picture's loading state. Set delay to hold the fallback back for a moment so the initials do not flash up in front of a cached image, and read the state itself with onLoadingStatusChange.

Status marks

An avatar carries no status dot of its own. Wrap it in a Badge with overlap="circle", which tucks the marker in by the amount a circle's corner sits inside its bounding box.

Accessibility

  • JD read out loud is two letters, not a person. Given a name, the initials are hidden from the accessibility tree and the name becomes the fallback's accessible name instead.
  • With neither name nor alt the <img> gets an empty alt, so it is skipped rather than read out as a file name. That is the right default for an avatar sitting next to the person's own name; pass alt when the picture is the only thing identifying them.
  • A children glyph with no name says nothing. Give the avatar a name (or an aria-label on whatever wraps it) when the glyph is carrying the meaning on its own.

Released under the MIT License