# Avatar

> Represent a person, team, account, or organization with an image and fallback.

Source: https://www.honestui.com/docs/components/avatar

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

export function AvatarDemo() {
  return (
    <Avatar>
      <AvatarImage
        src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
        alt="Luke Tracy"
      />
      <AvatarFallback>LT</AvatarFallback>
    </Avatar>
  )
}

```

## Overview [#overview]

Use an avatar to represent a person, team, account, or organization wherever recognition helps someone parse the page: comment authors, assignees, collaborators, members. An avatar supports identity; it should not carry information that appears nowhere else. Where identity must be unambiguous — approvals, permissions, audit logs — pair the avatar with a visible name. See [Don't do this](#dont-do-this) for the alt-text mistakes that most often break this rule.

## Anatomy [#anatomy]

An avatar has an image, a fallback, and an optional status badge. The image renders when it loads successfully; the fallback renders when there is no image, the URL is broken, or loading is still in progress after the fallback's delay. The fallback takes over the full surface, so the avatar keeps its exact footprint either way and nothing around it shifts.

## Fallbacks [#fallbacks]

Always render `AvatarFallback`, even when every current user has a photo. Networks fail, images get deleted, and new records have no picture yet. Initials work well because they stay legible at every size; the component scales their font size and letter spacing to match the avatar automatically. Use a single initial or an icon when the name has no obvious initials, such as some non-Latin names. `AvatarFallback` accepts Base UI's `delay` prop if you want to wait briefly before showing the fallback while a slow image loads.

## Sizes, shapes, and color [#sizes-shapes-and-color]

Sizes run from `1` (16 px, inline with text) to `13` (120 px, profile pages). Pick one or two sizes per surface and keep them consistent; avatars compete for attention when every row uses a different size. The default shape is `full` (a circle); `rounded` gives a squircle for teams and organizations. The `color` prop tints the fallback background and pairs with `variant`: `soft` (the default) for a muted tint, `solid` for emphasis. Color is decoration here — never use it as the only signal about a person.

## Groups and status badges [#groups-and-status-badges]

`AvatarGroup` overlaps members with a shared border ring and works with `AvatarGroupCount` (`+5`) when the list is longer than you show. Keep the visible count truthful: it must equal the number of hidden members, not a rough total.

`AvatarBadge` renders a small dot pinned to the bottom-right corner. It is purely visual — a colored dot says nothing to anyone who cannot perceive that color, including screen readers. Pair it with a visible text label for the state it represents, as the [status example](#status-badge-with-a-text-equivalent) shows.

## Accessibility [#accessibility]

Give `AvatarImage` alt text that matches its job. When the person's name is visible right next to the avatar, pass `alt=""` so assistive technology skips the redundant image and reads just the name once. When the avatar stands alone, give it real alt text — the person's name, not `"Avatar"` and not `"Avatar of Sarah Chen"`. If neither a name nor useful alt text exists, reconsider whether the avatar belongs there at all.

The fallback initials are real text content. Screen readers read them letter by letter ("C", "L") when no image loads, which is acceptable noise beside a visible name but another reason the name should be present.

A loaded image fades in with a short animation that is skipped entirely under reduced-motion preferences. The `disabled` prop dims the avatar and sets `aria-disabled`, but does not block pointer events — apply any interaction rules yourself.

Single avatars mirror correctly in right-to-left layouts. `AvatarGroup`'s overlap currently uses a physical left margin rather than a logical one, so stacked groups do not fully mirror; verify groups in RTL before shipping them.

## Installation [#installation]


  

  
    <CliBlock commands="[&#x22;avatar&#x22;]" />
  

  
    
      
        Install the following dependencies:
      

      ```bash
      npm install @base-ui-components/react
      ```

      
        Copy and paste the following code into your project.
      

      ### components/ui/avatar.tsx

```tsx
"use client"

import * as React from "react"
import { Avatar as AvatarPrimitive } from "@base-ui-components/react/avatar"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const avatarVariants = cva(
  "relative flex shrink-0 items-center justify-center overflow-hidden bg-[var(--hui-color-background-neutral-secondary)] text-[var(--hui-color-foreground-base-primary)] [--fallback-font-size:calc(var(--hui-space-9,32px)*0.4)] [--fallback-letter-spacing:0.03em] outline-[0.5px] outline-[var(--hui-color-overlay-base-a2)] outline-offset-[-0.5px] select-none",
  {
    variants: {
      variant: {
        solid: "[--avatar-opacity:1]",
        soft: "text-[var(--hui-color-foreground-base-primary)] [--avatar-opacity:0.2]",
      },
      color: {
        indigo:
          "[--avatar-hue:var(--hui-color-background-accent-emphasis)] [--avatar-color:var(--hui-color-foreground-accent-emphasis)]",
        orange:
          "[--avatar-hue:var(--hui-color-background-attention-emphasis)] [--avatar-color:var(--hui-color-foreground-attention-emphasis)]",
        mint: "[--avatar-hue:var(--hui-color-background-success-emphasis)] [--avatar-color:var(--hui-color-foreground-success-emphasis)]",
        neutral:
          "[--avatar-hue:var(--hui-color-background-neutral-emphasis)] [--avatar-color:var(--hui-color-foreground-base-emphasis)]",
        sky: "[--avatar-hue:var(--hui-color-viz-sky-9)] [--avatar-color:var(--hui-color-viz-sky-11)]",
        lime: "[--avatar-hue:var(--hui-color-viz-lime-9)] [--avatar-color:var(--hui-color-viz-lime-11)]",
        grass:
          "[--avatar-hue:var(--hui-color-viz-grass-9)] [--avatar-color:var(--hui-color-viz-grass-11)]",
        cyan: "[--avatar-hue:var(--hui-color-viz-cyan-9)] [--avatar-color:var(--hui-color-viz-cyan-11)]",
        iris: "[--avatar-hue:var(--hui-color-viz-iris-9)] [--avatar-color:var(--hui-color-viz-iris-11)]",
        purple:
          "[--avatar-hue:var(--hui-color-viz-purple-9)] [--avatar-color:var(--hui-color-viz-purple-11)]",
        pink: "[--avatar-hue:var(--hui-color-viz-pink-9)] [--avatar-color:var(--hui-color-viz-pink-11)]",
        crimson:
          "[--avatar-hue:var(--hui-color-viz-crimson-9)] [--avatar-color:var(--hui-color-viz-crimson-11)]",
        gold: "[--avatar-hue:var(--hui-color-viz-gold-9)] [--avatar-color:var(--hui-color-viz-gold-11)]",
      },
      size: {
        "1": "size-[var(--hui-space-5,16px)] rounded-[var(--hui-radius-2)] [--fallback-font-size:calc(var(--hui-space-5,16px)*0.4)] [--fallback-letter-spacing:0.05em]",
        "2": "size-[var(--hui-space-6,20px)] rounded-[var(--hui-radius-2)] [--fallback-font-size:calc(var(--hui-space-6,20px)*0.4)] [--fallback-letter-spacing:0.05em]",
        "3": "size-[var(--hui-space-7,24px)] rounded-[var(--hui-radius-2)] [--fallback-font-size:calc(var(--hui-space-7,24px)*0.4)] [--fallback-letter-spacing:0.04em]",
        "4": "size-[var(--hui-space-8,28px)] rounded-[var(--hui-radius-2)] [--fallback-font-size:calc(var(--hui-space-8,28px)*0.35)] [--fallback-letter-spacing:0.04em]",
        "5": "size-[var(--hui-space-9,32px)] rounded-[var(--hui-radius-2)] [--fallback-font-size:calc(var(--hui-space-9,32px)*0.4)] [--fallback-letter-spacing:0.03em]",
        "6": "size-[var(--hui-space-10,40px)] rounded-[var(--hui-radius-4)] [--fallback-font-size:calc(var(--hui-space-10,40px)*0.35)] [--fallback-letter-spacing:0.02em]",
        "7": "size-[var(--hui-space-11,48px)] rounded-[var(--hui-radius-4)] [--fallback-font-size:calc(var(--hui-space-11,48px)*0.35)] [--fallback-letter-spacing:0.01em]",
        "8": "size-[var(--hui-space-12,56px)] rounded-[var(--hui-radius-4)] [--fallback-font-size:calc(var(--hui-space-12,56px)*0.3)] [--fallback-letter-spacing:0.01em]",
        "9": "size-[var(--hui-space-13,64px)] rounded-[var(--hui-radius-4)] [--fallback-font-size:calc(var(--hui-space-13,64px)*0.3)] [--fallback-letter-spacing:0em]",
        "10": "size-[var(--hui-space-14,72px)] rounded-[var(--hui-radius-5)] [--fallback-font-size:calc(var(--hui-space-14,72px)*0.3)] [--fallback-letter-spacing:0em]",
        "11": "size-[var(--hui-space-15,80px)] rounded-[var(--hui-radius-5)] [--fallback-font-size:calc(var(--hui-space-15,80px)*0.3)] [--fallback-letter-spacing:0em]",
        "12": "size-[var(--hui-space-16,96px)] rounded-[var(--hui-radius-5)] [--fallback-font-size:calc(var(--hui-space-16,96px)*0.3)] [--fallback-letter-spacing:-0.005em]",
        "13": "size-[var(--hui-space-17,120px)] rounded-[var(--hui-radius-5)] [--fallback-font-size:calc(var(--hui-space-17,120px)*0.3)] [--fallback-letter-spacing:-0.01em]",
      },
      shape: {
        rounded: null,
        full: "rounded-[var(--hui-radius-full)]",
      },
      disabled: {
        true: "opacity-50",
        false: null,
      },
    },
    compoundVariants: [
      {
        variant: "solid",
        color: "indigo",
        className:
          "bg-[var(--hui-color-background-accent-emphasis)] text-[var(--hui-color-foreground-accent-emphasis)]",
      },
      {
        variant: "solid",
        color: "orange",
        className:
          "bg-[var(--hui-color-background-attention-emphasis)] text-[var(--hui-color-foreground-attention-primary-hover)]",
      },
      {
        variant: "solid",
        color: "mint",
        className:
          "bg-[var(--hui-color-background-success-emphasis)] text-[var(--hui-color-foreground-success-primary-hover)]",
      },
      {
        variant: "solid",
        color: "neutral",
        className:
          "bg-[var(--hui-color-background-neutral-emphasis)] text-[var(--hui-color-foreground-base-primary)]",
      },
      {
        variant: "solid",
        color: "sky",
        className:
          "bg-[var(--hui-color-viz-sky-9)] text-[var(--hui-color-viz-sky-11)]",
      },
      {
        variant: "solid",
        color: "lime",
        className:
          "bg-[var(--hui-color-viz-lime-9)] text-[var(--hui-color-viz-lime-11)]",
      },
      {
        variant: "solid",
        color: "grass",
        className:
          "bg-[var(--hui-color-viz-grass-8)] text-[var(--hui-color-viz-grass-11)]",
      },
      {
        variant: "solid",
        color: "cyan",
        className:
          "bg-[var(--hui-color-viz-cyan-8)] text-[var(--hui-color-viz-cyan-11)]",
      },
      {
        variant: "solid",
        color: "iris",
        className:
          "bg-[var(--hui-color-viz-iris-8)] text-[var(--hui-color-viz-iris-11)]",
      },
      {
        variant: "solid",
        color: "purple",
        className:
          "bg-[var(--hui-color-viz-purple-8)] text-[var(--hui-color-viz-purple-11)]",
      },
      {
        variant: "solid",
        color: "pink",
        className:
          "bg-[var(--hui-color-viz-pink-8)] text-[var(--hui-color-viz-pink-11)]",
      },
      {
        variant: "solid",
        color: "crimson",
        className:
          "bg-[var(--hui-color-viz-crimson-8)] text-[var(--hui-color-viz-crimson-11)]",
      },
      {
        variant: "solid",
        color: "gold",
        className:
          "bg-[var(--hui-color-viz-gold-8)] text-[var(--hui-color-viz-gold-11)]",
      },
      {
        variant: "soft",
        color: "indigo",
        className: "bg-[var(--hui-color-background-accent-primary)]",
      },
      {
        variant: "soft",
        color: "orange",
        className: "bg-[var(--hui-color-background-attention-primary)]",
      },
      {
        variant: "soft",
        color: "mint",
        className: "bg-[var(--hui-color-background-success-primary)]",
      },
      {
        variant: "soft",
        color: "neutral",
        className: "bg-[var(--hui-color-background-neutral-secondary)]",
      },
      {
        variant: "soft",
        color: "sky",
        className: "bg-[var(--hui-color-viz-sky-6)]",
      },
      {
        variant: "soft",
        color: "lime",
        className: "bg-[var(--hui-color-viz-lime-6)]",
      },
      {
        variant: "soft",
        color: "grass",
        className: "bg-[var(--hui-color-viz-grass-6)]",
      },
      {
        variant: "soft",
        color: "cyan",
        className: "bg-[var(--hui-color-viz-cyan-6)]",
      },
      {
        variant: "soft",
        color: "iris",
        className: "bg-[var(--hui-color-viz-iris-6)]",
      },
      {
        variant: "soft",
        color: "purple",
        className: "bg-[var(--hui-color-viz-purple-6)]",
      },
      {
        variant: "soft",
        color: "pink",
        className: "bg-[var(--hui-color-viz-pink-6)]",
      },
      {
        variant: "soft",
        color: "crimson",
        className: "bg-[var(--hui-color-viz-crimson-6)]",
      },
      {
        variant: "soft",
        color: "gold",
        className: "bg-[var(--hui-color-viz-gold-6)]",
      },
    ],
    defaultVariants: {
      variant: "soft",
      color: "neutral",
      size: "5",
      shape: "full",
      disabled: false,
    },
  }
)

type AvatarProps = Omit<AvatarPrimitive.Root.Props, "color" | "size"> &
  VariantProps<typeof avatarVariants>

function Avatar({
  className,
  variant,
  color,
  size,
  shape,
  disabled,
  ...props
}: AvatarProps) {
  return (
    <AvatarPrimitive.Root
      data-slot="avatar"
      aria-disabled={disabled || undefined}
      className={cn(
        avatarVariants({ variant, color, size, shape, disabled }),
        className
      )}
      {...props}
    />
  )
}

function AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {
  return (
    <AvatarPrimitive.Image
      data-slot="avatar-image"
      className={cn(
        "flex size-full box-border object-cover align-middle motion-safe:animate-in motion-safe:fade-in-0 motion-safe:[animation-duration:var(--hui-duration-fast)] motion-safe:[animation-timing-function:var(--hui-ease-out)]",
        className
      )}
      {...props}
    />
  )
}

function AvatarFallback({
  className,
  ...props
}: AvatarPrimitive.Fallback.Props) {
  return (
    <AvatarPrimitive.Fallback
      data-slot="avatar-fallback"
      className={cn(
        "flex size-full items-center justify-center [font-size:var(--fallback-font-size)] [font-weight:var(--hui-font-weight-medium)] [letter-spacing:var(--fallback-letter-spacing,0.03em)] leading-none",
        className
      )}
      {...props}
    />
  )
}

function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="avatar-badge"
      className={cn(
        "absolute right-0 bottom-0 flex size-3.5 items-center justify-center rounded-full border-2 border-[var(--hui-color-background-base-primary)] bg-[var(--hui-color-background-accent-emphasis)] text-[0.5rem] text-[var(--hui-color-foreground-accent-emphasis)] [&_svg]:size-2.5",
        className
      )}
      {...props}
    />
  )
}

function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="avatar-group"
      className={cn(
        "flex flex-row items-center [--avatar-overlap:1.2em] [&>*:not(:first-child)]:ml-[calc(-0.5*var(--avatar-overlap))] [&>[data-slot=avatar]]:box-content [&>[data-slot=avatar]]:border [&>[data-slot=avatar]]:border-[var(--hui-color-background-base-primary)] [&>[data-slot=avatar]]:![outline:none]",
        className
      )}
      {...props}
    />
  )
}

function AvatarGroupCount({ className, ...props }: React.ComponentProps<"span">) {
  return (
    <span
      data-slot="avatar-group-count"
      className={cn(
        "relative inline-flex size-[var(--hui-space-9,32px)] shrink-0 items-center justify-center rounded-[var(--hui-radius-full)] border border-[var(--hui-color-background-base-primary)] bg-[var(--hui-color-background-neutral-secondary)] [font-size:calc(var(--hui-space-9,32px)*0.4)] [font-weight:var(--hui-font-weight-medium)] [letter-spacing:0.03em] leading-none text-[var(--hui-color-foreground-base-primary)] [&_svg]:size-4",
        className
      )}
      {...props}
    />
  )
}

export {
  Avatar,
  AvatarImage,
  AvatarFallback,
  AvatarBadge,
  AvatarGroup,
  AvatarGroupCount,
  avatarVariants,
}

```

      
        Update the import paths to match your project setup.
      
    
  


## Usage [#usage]

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

```tsx
<Avatar>
  <AvatarImage src="/avatars/01.png" alt="User avatar" />
  <AvatarFallback>CL</AvatarFallback>
</Avatar>
```

When the name appears beside the avatar, change `alt` to `""` so the image is treated as decorative. Keep the fallback even then — it preserves the layout while the image loads and whenever it fails.

## Don't do this [#dont-do-this]

### Redundant or missing alt text [#redundant-or-missing-alt-text]

```tsx
// Bad — name is already visible beside the avatar
<li>
  <Avatar>
    <AvatarImage src="/avatars/sarah.png" alt="Avatar of Sarah Chen" />
    <AvatarFallback>SC</AvatarFallback>
  </Avatar>
  Sarah Chen
</li>
```

```tsx
// Good
<li>
  <Avatar>
    <AvatarImage src="/avatars/sarah.png" alt="" />
    <AvatarFallback>SC</AvatarFallback>
  </Avatar>
  Sarah Chen
</li>
```

With the redundant version, a screen reader announces "Sarah Chen graphic, Avatar of Sarah Chen, Sarah Chen" — the same fact three times for every row in the list. When the name is adjacent, `alt=""` makes the image decorative. When the avatar stands alone, drop the `"Avatar of"` prefix and use plain alt text like `"Sarah Chen"`.

### Status conveyed by a colored dot alone [#status-conveyed-by-a-colored-dot-alone]

```tsx
// Bad
<Avatar>
  <AvatarImage src={src} alt="" />
  <AvatarFallback>NJ</AvatarFallback>
  <AvatarBadge className="bg-green-500" />
</Avatar>
```

```tsx
// Good
<div className="flex items-center gap-3">
  <Avatar>
    <AvatarImage src={src} alt="" />
    <AvatarFallback>NJ</AvatarFallback>
    <AvatarBadge className="bg-primary" aria-hidden="true" />
  </Avatar>
  <div>
    <p>Nick Johnson</p>
    <p className="text-muted-foreground">Available</p>
  </div>
</div>
```

The dot alone fails people who cannot distinguish green from gray, people using forced-colors themes, and screen reader users, who hear nothing at all. Mark the dot `aria-hidden` and put the state in visible text where everyone gets it.

### No fallback behind the image [#no-fallback-behind-the-image]

```tsx
// Bad
<Avatar>
  <AvatarImage src="https://cdn.example.com/u/42.png" alt="Ana Ruiz" />
</Avatar>
```

```tsx
// Good
<Avatar>
  <AvatarImage src="https://cdn.example.com/u/42.png" alt="Ana Ruiz" />
  <AvatarFallback>AR</AvatarFallback>
</Avatar>
```

Without a fallback, a deleted file, offline session, or broken CDN link leaves an anonymous empty circle. The fallback costs one line and guarantees the avatar always represents something.

## Examples [#examples]

### Fallback Only [#fallback-only]

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

export function AvatarFallbackDemo() {
  return (
    <Avatar>
      <AvatarFallback>LT</AvatarFallback>
    </Avatar>
  )
}

```

### Different Sizes [#different-sizes]

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

export function AvatarSizeDemo() {
  return (
    <div className="flex items-center gap-4">
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=96&h=96&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
      <Avatar className="size-12">
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=144&h=144&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
      <Avatar className="size-16">
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=192&h=192&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
    </div>
  )
}

```

### Different Radius [#different-radius]

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

export function AvatarRadiusDemo() {
  return (
    <div className="flex items-center gap-4">
      <Avatar className="rounded-md">
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
      <Avatar className="rounded-xl">
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
      <Avatar className="rounded-full">
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
          alt="User"
        />
        <AvatarFallback>AV</AvatarFallback>
      </Avatar>
    </div>
  )
}

```

### Group Avatars [#group-avatars]

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

export function AvatarGroupDemo() {
  return (
    <AvatarGroup aria-label="Project collaborators">
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=96&h=96&dpr=2&q=80"
          alt="Morgan Lee"
        />
        <AvatarFallback>U1</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1628157588553-5eeea00af15c?w=96&h=96&dpr=2&q=80"
          alt="Avery Patel"
        />
        <AvatarFallback>U2</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1655874819398-c6dfbec68ac7?w=96&h=96&dpr=2&q=80"
          alt="Jordan Kim"
        />
        <AvatarFallback>U3</AvatarFallback>
      </Avatar>
      <AvatarGroupCount aria-label="3 more collaborators">+3</AvatarGroupCount>
    </AvatarGroup>
  );
}

```

### Group with supporting copy [#group-with-supporting-copy]

The stack plus a short claim reads as social proof without pretending each member approved anything.

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

const people = [
  {
    src: "https://images.unsplash.com/photo-1542595913-85d69b0edbaf?w=96&h=96&dpr=2&q=80",
    alt: "Liam Thompson",
    fallback: "LT",
  },
  {
    src: "https://images.unsplash.com/photo-1485206412256-701ccc5b93ca?w=96&h=96&dpr=2&q=80",
    alt: "Nick Johnson",
    fallback: "NJ",
  },
  {
    src: "https://images.unsplash.com/photo-1620075225255-8c2051b6c015?w=96&h=96&dpr=2&q=80",
    alt: "Maria Garcia",
    fallback: "MG",
  },
  {
    src: "https://github.com/leerob.png",
    alt: "@leerob",
    fallback: "CH",
  },
]

export function AvatarGroupTrust() {
  return (
    <div className="flex items-center gap-1.5 rounded-full border border-border p-1 shadow-sm shadow-black/5">
      <AvatarGroup>
        {people.map((person) => (
          <Avatar key={person.alt} className="size-7">
            <AvatarImage src={person.src} alt={person.alt} />
            <AvatarFallback>{person.fallback}</AvatarFallback>
          </Avatar>
        ))}
      </AvatarGroup>

      <p className="me-1.5 text-xs text-muted-foreground">
        Trusted by <span className="font-semibold text-foreground">100K+</span>{" "}
        users.
      </p>
    </div>
  )
}

```

### Status badge with a text equivalent [#status-badge-with-a-text-equivalent]

Every dot is paired with a visible state label; the dots themselves are hidden from assistive technology.

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

const people = [
  {
    src: "https://images.unsplash.com/photo-1485206412256-701ccc5b93ca?w=96&h=96&dpr=2&q=80",
    alt: "Nick Johnson",
    fallback: "NJ",
    badgeClassName: "bg-primary",
    status: "Available",
  },
  {
    src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=96&h=96&dpr=2&q=80",
    alt: "Alex Johnson",
    fallback: "AJ",
    badgeClassName: "bg-green-500",
    status: "Available",
  },
  {
    src: "https://images.unsplash.com/photo-1519699047748-de8e457a634e?w=96&h=96&dpr=2&q=80",
    alt: "Sarah Chen",
    fallback: "SC",
    badgeClassName: "bg-yellow-500",
    status: "Away",
  },
  {
    src: "https://images.unsplash.com/photo-1584308972272-9e4e7685e80f?w=96&h=96&dpr=2&q=80",
    alt: "Michael Rodriguez",
    fallback: "MR",
    badgeClassName: "bg-destructive",
    status: "Do not disturb",
  },
];

export function AvatarStatus() {
  return (
    <ul className="grid gap-3">
      {people.map((person) => (
        <li key={person.alt} className="flex items-center gap-3">
          <Avatar className="relative">
            <AvatarImage src={person.src} alt="" />
            <AvatarFallback>{person.fallback}</AvatarFallback>
            <AvatarBadge className={person.badgeClassName} aria-hidden="true" />
          </Avatar>
          <span className="text-sm">
            <span className="block font-medium">{person.alt}</span>
            <span className="text-muted-foreground">{person.status}</span>
          </span>
        </li>
      ))}
    </ul>
  );
}

```

## API reference [#api-reference]

`Avatar` wraps the Base UI avatar root and adds these props:

| Prop       | Values                                                                                                             | Default   |
| ---------- | ------------------------------------------------------------------------------------------------------------------ | --------- |
| `variant`  | `soft`, `solid`                                                                                                    | `soft`    |
| `color`    | `indigo`, `orange`, `mint`, `neutral`, `sky`, `lime`, `grass`, `cyan`, `iris`, `purple`, `pink`, `crimson`, `gold` | `neutral` |
| `size`     | `1`–`13` (16 px to 120 px)                                                                                         | `5`       |
| `shape`    | `rounded`, `full`                                                                                                  | `full`    |
| `disabled` | boolean                                                                                                            | `false`   |

`color` and `size` replace the Base UI root props of the same names. All other Base UI root props, including `render` composition, pass through.

Parts: `AvatarImage` forwards native `<img>` props plus Base UI's `onLoadingStatusChange`; `AvatarFallback` accepts Base UI's `delay` (milliseconds); `AvatarBadge`, `AvatarGroup`, and `AvatarGroupCount` accept native element props and provide layout only.

See the [Base UI Avatar API](https://base-ui.com/react/components/avatar#api-reference).
