Data display
Avatar
Avatars put a face or a mark on people, teams and workspaces. They show a picture when there is one and fall back to tinted initials when there isn't (or when the image fails to load), carry an optional presence dot, and stack into groups with a count for everyone who doesn't fit.
On this page
<div className="flex items-end gap-4"> <Avatar name="Ada Moreno" src={ADA_PHOTO} size="xl" status="online" /> <Avatar name="Theo Lindqvist" src={THEO_PHOTO} size="lg" status="away" /> <Avatar name="Priya Raman" size="lg" status="busy" /> <Avatar name="Jonah Okafor" size="md" status="offline" /> <Avatar name="Fernhill Studio" shape="square" size="lg" /></div><AvatarGroup people={[ { name: "Ada Moreno", src: ADA_PHOTO }, { name: "Theo Lindqvist", src: THEO_PHOTO }, { name: "Priya Raman", src: PRIYA_PHOTO }, { name: "Jonah Okafor" }, { name: "Mira Castell" }, { name: "Felix Brandt" }, { name: "Sana Ibrahim" }, ]} max={4} size="lg"/>Usage
import { Avatar, AvatarGroup } from "@/components/ui/avatar"; <Avatar name="Ada Moreno" src={user.avatarUrl} status="online" /><AvatarGroup people={members} max={4} />Examples
Overview
<div className="flex items-end gap-4"> <Avatar name="Ada Moreno" src={ADA_PHOTO} size="xl" status="online" /> <Avatar name="Theo Lindqvist" src={THEO_PHOTO} size="lg" status="away" /> <Avatar name="Priya Raman" size="lg" status="busy" /> <Avatar name="Jonah Okafor" size="md" status="offline" /> <Avatar name="Fernhill Studio" shape="square" size="lg" /></div><AvatarGroup people={[ { name: "Ada Moreno", src: ADA_PHOTO }, { name: "Theo Lindqvist", src: THEO_PHOTO }, { name: "Priya Raman", src: PRIYA_PHOTO }, { name: "Jonah Okafor" }, { name: "Mira Castell" }, { name: "Felix Brandt" }, { name: "Sana Ibrahim" }, ]} max={4} size="lg"/>Sizes
Five sizes from 20 to 56 px. Use sm in dense tables, md in lists and lg or xl on profile headers.
<Avatar name="Mira Castell" size="xs" /><Avatar name="Mira Castell" size="sm" /><Avatar name="Mira Castell" size="md" /><Avatar name="Mira Castell" size="lg" /><Avatar name="Mira Castell" size="xl" />Image and fallback
Pass src for a picture. Without one, or if the image fails to load, the avatar shows initials on a tint picked from the chart palette by name, so the same person always gets the same color.
<Avatar name="Ada Moreno" src={ADA_PHOTO} size="lg" /><Avatar name="Theo Lindqvist" src={THEO_PHOTO} size="lg" /><Avatar name="Priya Raman" src={PRIYA_PHOTO} size="lg" /><Avatar name="Lucas Ferreira" size="lg" />Status
A presence dot in the corner. The status is part of the accessible name ("Ada Moreno (Online)"), so it is never conveyed by color alone.
<Avatar name="Ada Moreno" status="online" size="lg" /><Avatar name="Theo Lindqvist" status="away" size="lg" /><Avatar name="Priya Raman" status="busy" size="lg" /><Avatar name="Jonah Okafor" status="offline" size="lg" />Square
Use the square shape for workspaces, teams and apps. Its corners follow the theme radius.
<Avatar name="Ledgerly" shape="square" size="xl" /><Avatar name="Fernhill Studio" shape="square" size="lg" /><Avatar name="Quillmark" shape="square" size="md" status="online" /><Avatar name="Tidewell" shape="square" size="sm" />Group
AvatarGroup overlaps avatars with a ring in the surface color and shows +N for the rest. Hover the group to see every name.
const team = [ { name: "Ada Moreno", src: ADA_PHOTO }, { name: "Theo Lindqvist", src: THEO_PHOTO }, { name: "Priya Raman" }, { name: "Jonah Okafor" }, { name: "Mira Castell" }, { name: "Felix Brandt" }, { name: "Sana Ibrahim" }, { name: "Hana Sato" },]; <AvatarGroup people={team} max={3} size="sm" /><AvatarGroup people={team} max={5} size="md" /><AvatarGroup people={team} max={4} size="lg" />Member list
When the name is printed next to the avatar, mark it decorative so screen readers don't hear the name twice. The status is still announced.
- OnlineAda Morenoada@fernhill.exampleOwner
- AwayTheo Lindqvisttheo@fernhill.exampleAdmin
- OfflinePriya Ramanpriya@fernhill.exampleMember
<ul className="mx-auto flex w-full max-w-md flex-col divide-y divide-line rounded-ui-lg border border-line bg-surface"> {members.map((m) => ( <li key={m.email} className="flex items-center gap-3 px-4 py-3"> <Avatar name={m.name} src={m.src} status={m.status} decorative /> <div className="flex min-w-0 flex-1 flex-col"> <span className="truncate text-[14px] font-medium">{m.name}</span> <span className="truncate text-[13px] text-muted">{m.email}</span> </div> <Badge tone={m.role === "Owner" ? "accent" : "neutral"}>{m.role}</Badge> </li> ))}</ul>Props
Avatar
namerequiredstringdefault: —Person or workspace name. Used for initials, the fallback tint and the accessible name.srcstringdefault: —Image URL. Falls back to initials if missing or if it fails to load.size"xs" | "sm" | "md" | "lg" | "xl"default: "md"20, 24, 32, 40 or 56 px.shape"circle" | "square"default: "circle"Square follows the theme radius; use it for workspaces and apps.status"online" | "away" | "busy" | "offline"default: —Presence dot, also added to the accessible name.decorativebooleandefault: falseHide the name from assistive tech when it is printed next to the avatar.classNamestringdefault: —Extra classes for the outer element (margins, rings).
AvatarGroup
peoplerequired{ name: string; src?: string }[]default: —Everyone in the group, in display order.maxnumberdefault: 4Avatars shown before the +N chip.sizeAvatarSizedefault: "md"Size of every avatar in the stack.labelstringdefault: —Accessible label. Defaults to "Ada, Theo, Priya and 4 more".
Accessibility
- Avatar renders role="img" with the name (and status) as its label; images inside use an empty alt so the name is not read twice.
- Pass decorative when a visible name sits next to the avatar. The picture is hidden, but a status such as "Away" is still announced.
- Presence is never color alone: each status has a word in the accessible name.
- AvatarGroup is one image labelled with the first names and a count of the rest, and its title lists everyone on hover.
- Initials sit on an opaque tint of the chart palette mixed into the surface, keeping text readable in light and dark themes and with every accent.