Avatar
An avatar shows a person, team or organisation as a picture, with initials when there is no picture.An avatar shows who someone is: a profile picture, a team logo or a pair of initials. When the image is missing or fails to load, it shows the fallback instead. A picture that is content, such as a photo in a post, is an Image.
Playground
Usage
import { Avatar, Flex, Text } from '@kushagradhawan/kookie-ui';
export function Author({ name, email, photo }: { name: string; email: string; photo?: string }) {
const initials = name.split(' ').map((part) => part[0]).join('').slice(0, 2);
return (
<Flex gap="3" align="center">
<Avatar src={photo} alt="" fallback={initials} />
<Flex direction="column">
<Text size="2" weight="medium">{name}</Text>
<Text size="2" emphasis="medium">{email}</Text>
</Flex>
</Flex>
);
}Best practices
Always give a fallback. fallback is required because an image can fail at any time. Use one or two initials for a person and an icon for a team or an empty slot.
Put the name next to the avatar. A face or two letters is hard to tell apart in a list. Show the name in text beside it, and give the image an empty alt so a screen reader doesn't read the name twice.
Don't rely on colour alone for status. The status dot is a coloured circle. Give it a statusLabel, such as "Online", and say the state in words nearby or in a Tooltip for people who can't tell the colours apart.
Keep one size in a list. Avatars in a row or a column share a size, so names line up. Change the size between contexts, such as a comment list and a profile header, not within one.
Use colour for a category, not for decoration. An avatar rests gray. Set color when it means something, such as a colour per workspace, and keep that mapping the same everywhere.
Size
size picks one of nine square sizes. Sizes 1 to 4 are 28, 32, 40 and 48 pixels, the same heights as a Button of that size, so an avatar lines up with the controls beside it. Sizes 5 to 9 are 56, 64, 80, 96 and 128 pixels, for profile headers and cards. When you leave it unset, the avatar follows the nearest Theme size, from 1 to 4. size accepts a responsive object.
Variant
variant sets the look of the fallback. An image covers it.
| Variant | Look | Use it for |
|---|---|---|
raised | A surface with a shadow | Most avatars. This is the default |
soft | A tinted fill | Avatars in a dense list |
solid | A strong fill | One avatar that needs to stand out, such as the current user |
surface | A light fill and a border | Avatars on a tinted background |
outline | A border only | Empty slots, such as an unassigned task |
Examples
Presence
status adds a dot in the colour you pass, in the bottom corner on the end side: bottom-right in left-to-right text, bottom-left in right-to-left. It grows with the avatar. statusLabel names the dot for screen readers.
<Avatar fallback="MK" status="green" statusLabel="Online" />Count or badge
badge puts any content in the same corner, such as a Chip with a count. badge and status share the corner, so pass only one. If you pass both, badge wins.
<Avatar fallback="MK" badge={<Chip size="1" variant="solid" color="red">3</Chip>} />Logo that must not be cropped
fit sets how the image fills the square. The default cover crops to fill. Use contain for a logo that must show in full.
<Avatar src="/logos/acme.png" alt="Acme" fallback="AC" fit="contain" radius="medium" />Avatar that opens a profile
Render a link or a button with asChild. The avatar adds a hover filter to the image and a focus ring for the keyboard. Give the element a name, because initials alone don't say where it goes.
<Avatar asChild fallback="MK">
<a href="/people/mira" aria-label="Mira Kapoor's profile" />
</Avatar>Props
| Prop | Type | Default | Description |
|---|---|---|---|
fallback | ReactNode | Required. Shows when there is no image or it fails to load | |
src | string | The image URL | |
alt | string | The image's text alternative | |
size | '1' to '9', responsive | Theme size | The size step |
variant | 'raised' | 'solid' | 'soft' | 'surface' | 'outline' | 'raised' | The look of the fallback |
color | AccentColor | 'gray' | The fallback colour. Gray fills with step 12 |
radius | 'none' | 'small' | 'medium' | 'large' | 'full' | Theme radius | The corner |
status | AccentColor | Shows a dot of this colour in the corner. Not with badge | |
statusLabel | string | The name a screen reader reads for the status dot, such as "Online" | |
badge | ReactNode | Shows content in the corner. Wins over status | |
fit | 'cover' | 'contain' | 'fill' | 'scale-down' | 'none', responsive | 'cover' | How the image fills the square |
onLoadingStatusChange | (status: 'idle' | 'loading' | 'loaded' | 'error') => void | Called when the image starts, finishes or fails to load | |
asChild | boolean | false | Renders the child element, such as a link or a button, with the avatar inside |
ref | Ref<HTMLSpanElement> | The outer span |
The image attributes src, alt, srcSet, sizes, crossOrigin, referrerPolicy, loading, decoding, onLoad and onError go on the img. Everything else, such as id, aria-*, data-*, title and event handlers, goes on the outer span, with ref, className and style.
Accessibility
- Image: Give
altthe person's name when the avatar stands alone. Usealt=""when the name is already in text beside it. - Fallback: With
altset, the fallback is an image named byalt, so a screen reader says the name, not the initials. With an empty or missingalt, the fallback is hidden from screen readers. - Status: With
statusLabelthe dot is an image with that name. Without it the dot is hidden from screen readers. - Focus: A plain avatar is not focusable. An avatar rendered as a link or a button shows the focus ring for the keyboard only. A disabled child sets the avatar's disabled look.