# Avatar

An image with a fallback for representing a user.

Source: [avatar.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/avatar.tsx)

```tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { people } from "@/examples/data";

export default function AvatarWithImage() {
  const [ada, sam, priya] = people;
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Avatar size="sm">
        <AvatarImage src={ada.image} alt={ada.name} />
        <AvatarFallback>{ada.initials}</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage src={sam.image} alt={sam.name} />
        <AvatarFallback>{sam.initials}</AvatarFallback>
      </Avatar>
      <Avatar size="lg">
        <AvatarImage src={priya.image} alt={priya.name} />
        <AvatarFallback>{priya.initials}</AvatarFallback>
      </Avatar>
    </div>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/avatar
```

## Usage

```tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";

export function UserAvatar() {
  return (
    <Avatar>
      <AvatarImage src="/avatars/ada.png" alt="Ada Park" />
      <AvatarFallback>AP</AvatarFallback>
    </Avatar>
  );
}
```

The fallback shows while the image loads, and stays if it fails.

## Composition

- `Avatar`
  - `AvatarImage`
  - `AvatarFallback`
  - `AvatarBadge`
- `AvatarGroup`
  - `AvatarGroupCount`

## Examples

### Initials

`size` sets the avatar's size.

```tsx
import { Avatar, AvatarFallback } from "@/components/ui/avatar";

export default function AvatarInitials() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Avatar size="sm">
        <AvatarFallback>AP</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarFallback>AP</AvatarFallback>
      </Avatar>
      <Avatar size="lg">
        <AvatarFallback>AP</AvatarFallback>
      </Avatar>
    </div>
  );
}
```

### With a badge

`AvatarBadge` marks a corner of the avatar, such as for someone's presence. Pass a background
class to change its color. The badge is only visual, so say what it means in nearby text or the
image's `alt`.

```tsx
import { CheckIcon } from "lucide-react";

import { Avatar, AvatarBadge, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { people } from "@/examples/data";

export default function AvatarWithBadge() {
  const priya = people[2];
  return (
    <div className="flex flex-wrap items-center gap-3">
      <Avatar size="sm">
        <AvatarFallback>SR</AvatarFallback>
        <AvatarBadge />
      </Avatar>
      <Avatar>
        <AvatarFallback>SR</AvatarFallback>
        <AvatarBadge />
      </Avatar>
      <Avatar size="lg">
        <AvatarFallback>SR</AvatarFallback>
        <AvatarBadge />
      </Avatar>
      <Avatar size="lg">
        <AvatarImage src={priya.image} alt={priya.name} />
        <AvatarFallback>{priya.initials}</AvatarFallback>
        <AvatarBadge>
          <CheckIcon />
        </AvatarBadge>
      </Avatar>
      <Avatar size="lg">
        <AvatarFallback>JK</AvatarFallback>
        <AvatarBadge className="bg-warning" />
      </Avatar>
    </div>
  );
}
```

### Stack

`AvatarGroup` overlaps its avatars, and `AvatarGroupCount` shows how many more there are.

```tsx
import {
  Avatar,
  AvatarFallback,
  AvatarGroup,
  AvatarGroupCount,
  AvatarImage,
} from "@/components/ui/avatar";
import { people } from "@/examples/data";

const team = people.slice(0, 3);

export default function AvatarStack() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      {(["sm", "default", "lg"] as const).map((size) => (
        <AvatarGroup key={size}>
          {team.map((person) => (
            <Avatar key={person.value} size={size}>
              <AvatarImage src={person.image} alt={person.name} />
              <AvatarFallback>{person.initials}</AvatarFallback>
            </Avatar>
          ))}
          <AvatarGroupCount>+4</AvatarGroupCount>
        </AvatarGroup>
      ))}
    </div>
  );
}
```

### With a name

When the name is shown beside the avatar, give the image an empty `alt`.

```tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { people } from "@/examples/data";

export default function AvatarWithName() {
  const ada = people[0];
  return (
    <div className="flex items-center gap-2">
      <Avatar>
        <AvatarImage src={ada.image} alt="" />
        <AvatarFallback>{ada.initials}</AvatarFallback>
      </Avatar>
      <div className="flex flex-col">
        <span className="text-sm font-medium">{ada.name}</span>
        <span className="text-xs text-faint">{ada.email}</span>
      </div>
    </div>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `Avatar` | [`Avatar.Root`](https://base-ui.com/react/components/avatar#root) |
| `AvatarImage` | [`Avatar.Image`](https://base-ui.com/react/components/avatar#image) |
| `AvatarFallback` | [`Avatar.Fallback`](https://base-ui.com/react/components/avatar#fallback) |
| `AvatarBadge` | `<span>` |
| `AvatarGroup` | `<div>` |
| `AvatarGroupCount` | `<div>` |

The tables leave out `className`, `style` and `render`. Parts built on Base UI take them as its [styling](https://base-ui.com/react/handbook/styling) and [composition](https://base-ui.com/react/handbook/composition) guides describe.

### Avatar

| Prop    | Type                        | Description          |
| ------- | --------------------------- | -------------------- |
| `size?` | `"default" \| "lg" \| "sm"` | Default: `"default"` |

### AvatarImage

| Prop                     | Type                                     | Description                                                                                                                                                                            |
| ------------------------ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onLoadingStatusChange?` | `((status: ImageLoadingStatus) => void)` | Callback fired when the loading status changes.                                                                                                                                        |
| `keepMounted?`           | `boolean`                                | Whether the image element stays mounted and loads in place instead of being preloaded. Supports `loading="lazy"` and optimized image components such as `next/image`. Default: `false` |

### AvatarFallback

| Prop     | Type     | Description                                                                           |
| -------- | -------- | ------------------------------------------------------------------------------------- |
| `delay?` | `number` | How long to wait before showing the fallback. Specified in milliseconds. Default: `0` |
