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.

VariantLookUse it for
raisedA surface with a shadowMost avatars. This is the default
softA tinted fillAvatars in a dense list
solidA strong fillOne avatar that needs to stand out, such as the current user
surfaceA light fill and a borderAvatars on a tinted background
outlineA border onlyEmpty 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

PropTypeDefaultDescription
fallbackReactNodeRequired. Shows when there is no image or it fails to load
srcstringThe image URL
altstringThe image's text alternative
size'1' to '9', responsiveTheme sizeThe size step
variant'raised' | 'solid' | 'soft' | 'surface' | 'outline''raised'The look of the fallback
colorAccentColor'gray'The fallback colour. Gray fills with step 12
radius'none' | 'small' | 'medium' | 'large' | 'full'Theme radiusThe corner
statusAccentColorShows a dot of this colour in the corner. Not with badge
statusLabelstringThe name a screen reader reads for the status dot, such as "Online"
badgeReactNodeShows 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') => voidCalled when the image starts, finishes or fails to load
asChildbooleanfalseRenders the child element, such as a link or a button, with the avatar inside
refRef<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 alt the person's name when the avatar stands alone. Use alt="" when the name is already in text beside it.
  • Fallback: With alt set, the fallback is an image named by alt, so a screen reader says the name, not the initials. With an empty or missing alt, the fallback is hidden from screen readers.
  • Status: With statusLabel the 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.