# 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](/docs/image).


## Usage

```tsx
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](/docs/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](/docs/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.

```tsx
<Avatar fallback="MK" status="green" statusLabel="Online" />
```

### Count or badge

`badge` puts any content in the same corner, such as a [Chip](/docs/chip) with a count. `badge` and `status` share the corner, so pass only one. If you pass both, `badge` wins.

```tsx
<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.

```tsx
<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.

```tsx
<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 `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.
