Avatar
A person's round picture, or their own colour gradient when there is no photo.
ui.avatar
components/ui/avatar.tsxUse case
Use an avatar wherever a teammate appears: the person assigned to an order in a table row, the author of a note on a client's history, the account button in the top bar. With no photo, AvatarFallback takes the person's email as seed and draws their gradient, the same one on every screen. Several people on one job overlap as a group.
Use it when
- A teammate beside their name in a row or a comment
- Who an order or a task is assigned to
- The signed-in person's account button
- Several assignees at once, overlapped
Use something else when
- Switching between teams or workspaces: Team selector
- Showing more about the person when the pointer rests on them: Preview card
- The person's row is still loading: Skeleton
- Labelling a row with a status or a category, not a person: Badge
Examples
A face, or the person's own gradient (picked from their email, no letters)
+3
Code
Import
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"Usage
export function Assignee({ name, email, photo }: { name: string; email: string; photo?: string }) {
return (
<div className="flex items-center gap-2">
<Avatar className="size-8">
{photo ? <AvatarImage src={photo} alt="" /> : null}
<AvatarFallback seed={email} />
</Avatar>
<span className="text-[13px]">{name}</span>
</div>
)
}
export function Assignees({ emails, max = 4 }: { emails: string[]; max?: number }) {
const more = emails.length - max
return (
<div className="flex -space-x-2">
{emails.slice(0, max).map((email) => (
<Avatar key={email} className="size-8 ring-2 ring-surface">
<AvatarFallback seed={email} />
</Avatar>
))}
{more > 0 && (
<span className="relative grid size-8 place-items-center rounded-full bg-surface-3 text-[11px] font-medium text-ink-3 tabular-nums ring-2 ring-surface">
+{more}
</span>
)}
</div>
)
}Rules
- A person with no photo is drawn with AvatarFallback seed= (their email, else their name): their gradient from lib/avatar-gradient.ts, never initials in a grey circle.
- Keep AvatarFallback beside AvatarImage: it shows while the photo loads and if it fails.
- Size it with a size class on Avatar: size-6, size-8 (the default) or size-10.
- In a group each avatar carries ring-2 ring-surface and the row overlaps them with -space-x-2; a +3 count is a plain round span on an opaque ground (bg-surface-3), never a translucent fill the face behind would show through.
- AvatarImage takes alt="" when the name is printed beside it, so it is not read twice.