Avatar
A hand-drawn circular avatar with an image, initials, or empty fallback.
Overview
An Avatar represents a person or entity as a small circular image. When no image is available it
falls back to the initials derived from a name, and when there is neither it renders an empty
sketched circle.
Anatomy
A sketchy ellipse outline (@ghds/sketch-core) around a circular, clipped content area. The content
is an image (src), the uppercased initials of the first and last words of name, or nothing. Three
sizes — sm, md (default), lg — map to comp.avatar.size.*.
Variants & States
Avatar is presentational and non-interactive. Its only variation is size, plus which fallback
tier renders.
| State | Status | Notes |
|---|---|---|
| Image | Implemented | Rendered when `src` loads successfully. |
| Initials | Implemented | Fallback derived from `name` when there is no image (or it fails to load). |
| Empty | Implemented | Sketched circle when neither `src` nor `name` is provided. |
| Hover / Focus / Disabled | Not implemented | Avatar is not interactive. |
Usage
Do
- Always pass a `name` (or `alt`) so the avatar has an accessible label.
- Provide a `name` even when you pass a `src`, so the initials fallback works if the image fails.
- Use size to fit context — `sm` in dense lists, `lg` for profile headers.
Don't
- Don't use Avatar as a button; wrap it in a real interactive element if it must be clickable.
- Don't pass long text as a name expecting it to fit — only the first and last initials are shown.
Accessibility
- React: a named avatar is exposed as
role="img"with anaria-label; an anonymous one isaria-hidden(decorative). The inner<img>uses emptyaltso the label is not announced twice. - Web Components:
gh-avatarsetsinternals.role = 'img'andinternals.ariaLabelwhen aname/altis present, otherwise stays decorative. - React Native: sets
accessibilityRole="image"andaccessibilityLabelwhen a name/alt is given. - See the Accessibility Guide.
Content
A single image or a short name. Initials are computed as the first letter of the first and last whitespace-separated words, uppercased (e.g. “Ada Lovelace” → “AL”).
Props API
React@ghds/react
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image URL. Falls back to initials, then an empty circle, on error. |
name | string | — | Accessible label and initials source. |
alt | string | — | Overrides the accessible label (defaults to name). |
size | 'sm' | 'md' | 'lg' | 'md' | Rendered diameter. |
...rest | HTMLAttributes<HTMLSpanElement> | — | Native <span> attributes pass through. |
Web Components@ghds/web-components
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image URL. Falls back to initials on error. |
name | string | — | Accessible label and initials source. |
alt | string | — | Overrides the accessible label. |
size | 'sm' | 'md' | 'lg' | 'md' | Rendered diameter (reflected attribute). |
React Native@ghds/react-native
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | Image URI. Falls back to initials on error. |
name | string | — | Accessible label and initials source. |
alt | string | — | Overrides the accessible label. |
size | 'sm' | 'md' | 'lg' | 'md' | Rendered diameter. |
testID | string | — | Test handle for queries. |
Code examples
// React — @ghds/react
import { Avatar } from '@ghds/react/avatar';
<Avatar src="https://example.com/ada.png" name="Ada Lovelace" size="lg" />
<Avatar name="Ada Lovelace" size="md" />;
<!-- Web Components — @ghds/web-components -->
<script type="module">
import '@ghds/web-components/avatar';
</script>
<gh-avatar src="https://example.com/ada.png" name="Ada Lovelace" size="lg"></gh-avatar>
<gh-avatar name="Ada Lovelace" size="md"></gh-avatar>
// React Native — @ghds/react-native
import { Avatar } from '@ghds/react-native/avatar';
<Avatar src="https://example.com/ada.png" name="Ada Lovelace" size="lg" />;