Components · Data display
Avatar
BetaA client's or coach's photo or initials.
- Source
components/ui/avatar.tsx - shadcn/ui Avatar
- Figma: not linked yet (Q13)
Sara Al-Otaibi
12-week strength · Week 3
When to use
- To help coaches recognise a client or teammate at a glance: in the client list, a check-in thread, a chat, the account menu.
- To show who is in a group: the clients in a bootcamp, the coaches on a team.
When not to use
- For the SuperCoach or Coach logo: use the logo tile from Brand. Brand avatars may use the chamfered corner; avatars of people are always round (Shape).
- For progress photos or exercise images: those are content, not identity. Show them at full size, for example in a Carousel.
- As the only way to identify someone. Put the name next to the avatar, or give the avatar a name.
Anatomy
- 1. Container: round, clips the image, rounded-full
- 2. Image, or initials while it loads or when there is none
- 3. Badge (optional): a status dot or icon on the bottom end corner
Variants
Lina Farouk
Checked in today
Morning bootcamp
| Variant | Use for |
|---|---|
| Image | The client's photo, when they uploaded one. |
Initials (AvatarFallback) | No photo, or while the photo loads. Muted fill and text, the same for everyone. |
With badge (AvatarBadge) | One status that matters in context, such as "Checked in today". Always also in text nearby. |
Group (AvatarGroup + AvatarGroupCount) | Up to 3 avatars that overlap, then "+3" for the rest. |
States
| State | What changes | Token |
|---|---|---|
| Loading | Initials show until the image has loaded; set delayMs on the fallback to avoid a flash on fast connections | bg-muted, text-muted-foreground |
| Loaded | The image fills the circle | rounded-full |
| Error or no image | Initials stay. No broken-image icon | bg-muted, text-muted-foreground |
| With badge | Dot or icon with a ring that separates it from the photo | ring-background, bg-primary (default) |
Avatars are not interactive. When an avatar opens a profile, the link around it (with the name) gets the focus ring.
Sizes
- sm · 24px
- default · 32px
- lg · 40px
sm (24px) in dense tables and comment threads. default (32px) in lists and menus. lg (40px) in headers and cards. The badge and group count scale with the avatar. There are no sizing tokens yet; these are steps of the 4px spacing unit (QUESTIONS Q5).
Usage guidelines
- Show the same person with the same avatar everywhere: the photo if there is one, otherwise the same initials.
- In a group, show at most 3 avatars and a count. More becomes noise.
- Use the badge for one status. Two badges on one avatar can't be told apart at 8px.
Sara Al-Otaibi
Checked in today
Content guidelines
- Initials: the first letter of the first name and of the family name, skipping the article "Al-" or "ال": Sara Al-Otaibi is "SO", Khalid Al-Qahtani is "KQ". Two letters at most, in capitals.
- Arabic initials: the same rule: سارة العتيبي is "س ع". Arabic letters join, so put a zero-width non-joiner (U+200C) between the two letters. Without it, "سع" reads as a word.
- Use the script the name was entered in. Don't transliterate a name to make initials.
- Alt text: when the name is next to the avatar, the image is decorative:
alt=""andaria-hiddenon the avatar. When the avatar stands alone, give it the person's name:role="img"andaria-label="Sara Al-Otaibi". Never "avatar", "profile picture" or the file name. - Group count: "+3", and the group's accessible name says "and 3 more clients".
Accessibility
Avatars are not focusable and have no keyboard interaction.
- An avatar next to a name is hidden from screen readers (
aria-hidden), so the name isn't read twice. - A standalone avatar has
role="img"and anaria-labelwith the name, so it is announced as "Sara Al-Otaibi, image", whether the photo or the initials show. - A group has one name for the whole stack: "Sara Al-Otaibi, Omar Haddad, Khalid Al-Qahtani and 3 more clients, image". The "+3" alone means nothing when read out.
- A badge's meaning is written nearby or included in the avatar's name ("Omar Haddad, checked in today"). Color alone fails WCAG 1.4.1.
- Initials use
text-muted-foregroundonbg-muted(5.28:1).
RTL
- The badge sits on the bottom end corner (
end-0), so it moves to the bottom left. - Groups overlap toward the end:
-space-x-2uses logical margins, so the first avatar is on the right and the count on the left. - Photos don't mirror. Initials follow the script of the name.
Tokens used
Read from components/ui/avatar.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.
| Token | Utilities | SuperCoach | Coach |
|---|---|---|---|
| --background | ring-background | white | white |
| --muted | bg-muted | neutral-100 | neutral-100 |
| --muted-foreground | text-muted-foreground | neutral-600 | neutral-600 |
| --primary | bg-primary | brand-600 | orange-500 |
| --primary-foreground | text-primary-foreground | white | white |
- Layer
z-(--z-raised) - Radius
rounded-full - Type
text-sm - Type
text-xs
Props
<Avatar>
Also takes every prop of Radix Avatar.Root
| Prop | Type | Default |
|---|---|---|
| size? | "default" | "sm" | "lg" | "default" |
<AvatarImage>
Also takes every prop of Radix Avatar.Image
No props of its own.
<AvatarFallback>
Also takes every prop of Radix Avatar.Fallback
No props of its own.
<AvatarBadge>
Also takes every prop of <span>
No props of its own.
<AvatarGroup>
Also takes every prop of <div>
No props of its own.
<AvatarGroupCount>
Also takes every prop of <div>
No props of its own.
Replaces in coach-admin
From the read-only audit of coach-admin: 40 style values, 40 uses.
coach-admin colors each client's initials with one of 16 muted background colors, assigned per client in src/lib/helpers/avatar.ts, with near-black text. The design system uses one muted fill for everyone, because those colors have no tokens and the text contrast was not checked. Whether to bring per-client colors back, as tokens, is an open question.
Classes and selectors
.avatar4.avatar-status4.avatar--xl3.avatar--md3.avatar--lg2.avatar, .avatar-initials1.avatar.avatar-xs1.avatar--sm1
Files
src/lib/helpers/avatar.ts17src/reusableComponents/Avatar/Avatar.scss13
The inventory lists the first 12 locations of each value, so file counts are a lower bound.
SCSS variables in these styles
$status-widthnot a color: spacing, size or layout$layout-transition-speednot a color: spacing, size or layout
Related
Data table, Badge, Shape, Content.