codefast/ui

Command Palette

Search for a command to run...

Source
Display

Avatar

User icon with image support and initials fallback. Compose with AvatarGroup for stacks.

Examples

Stacked group

Overlap avatars with AvatarGroup and cap the overflow with a count.

CNLRER
26 lines
import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from "@codefast/ui/avatar";

export function AvatarGroupExample() {
  return (
    <AvatarGroup className="grayscale">
      <Avatar>
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=128&h=128&fit=crop&q=80"
          alt="@leo"
        />
        <AvatarFallback>LR</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&q=80"
          alt="@ava"
        />
        <AvatarFallback>ER</AvatarFallback>
      </Avatar>
    </AvatarGroup>
  );
}

Badge

Use the AvatarBadge component to add a badge to the avatar. The badge is positioned at the bottom right of the avatar.

CN
11 lines
import { Avatar, AvatarBadge, AvatarFallback, AvatarImage } from "@codefast/ui/avatar";

export function AvatarWithBadge() {
  return (
    <Avatar>
      <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
      <AvatarFallback>CN</AvatarFallback>
      <AvatarBadge className="bg-green-600 dark:bg-green-800" />
    </Avatar>
  );
}

Badge with Icon

You can also use an icon inside <AvatarBadge>.

PP
14 lines
import { Avatar, AvatarBadge, AvatarFallback, AvatarImage } from "@codefast/ui/avatar";
import { PlusIcon } from "lucide-react";

export function AvatarBadgeIconExample() {
  return (
    <Avatar className="grayscale">
      <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
      <AvatarFallback>PP</AvatarFallback>
      <AvatarBadge>
        <PlusIcon />
      </AvatarBadge>
    </Avatar>
  );
}

Basic

A basic avatar component with an image and a fallback.

CN
10 lines
import { Avatar, AvatarFallback, AvatarImage } from "@codefast/ui/avatar";

export function AvatarBasic() {
  return (
    <Avatar>
      <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" className="grayscale" />
      <AvatarFallback>CN</AvatarFallback>
    </Avatar>
  );
}

Dropdown

You can use the Avatar component as a trigger for a dropdown menu.

36 lines
import { Avatar, AvatarFallback, AvatarImage } from "@codefast/ui/avatar";
import { Button } from "@codefast/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@codefast/ui/dropdown-menu";

export function AvatarDropdown() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="ghost" size="icon" className="rounded-full">
          <Avatar>
            <AvatarImage src="https://github.com/codefastlabs.png" alt="codefast" />
            <AvatarFallback>CN</AvatarFallback>
          </Avatar>
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-32">
        <DropdownMenuGroup>
          <DropdownMenuItem>Profile</DropdownMenuItem>
          <DropdownMenuItem>Billing</DropdownMenuItem>
          <DropdownMenuItem>Settings</DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

Avatar Group Count

Use <AvatarGroupCount> to add a count to the group.

CNLRER
+3
27 lines
import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from "@codefast/ui/avatar";

export function AvatarGroupCountExample() {
  return (
    <AvatarGroup className="grayscale">
      <Avatar>
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=128&h=128&fit=crop&q=80"
          alt="@leo"
        />
        <AvatarFallback>LR</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&q=80"
          alt="@ava"
        />
        <AvatarFallback>ER</AvatarFallback>
      </Avatar>
      <AvatarGroupCount>+3</AvatarGroupCount>
    </AvatarGroup>
  );
}

Avatar Group with Icon

You can also use an icon inside <AvatarGroupCount>.

CNLRER
30 lines
import { Avatar, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from "@codefast/ui/avatar";
import { PlusIcon } from "lucide-react";

export function AvatarGroupCountIconExample() {
  return (
    <AvatarGroup className="grayscale">
      <Avatar>
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=128&h=128&fit=crop&q=80"
          alt="@leo"
        />
        <AvatarFallback>LR</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&q=80"
          alt="@ava"
        />
        <AvatarFallback>ER</AvatarFallback>
      </Avatar>
      <AvatarGroupCount>
        <PlusIcon />
      </AvatarGroupCount>
    </AvatarGroup>
  );
}

RTL

Right-to-left layout support for languages such as Arabic and Hebrew.

Translations are AI-generated for demonstration and may be imperfect.

CNER
CNLRER
67 lines
import { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage } from "@codefast/ui/avatar";

import type { Translations } from "#/features/components-catalog/components/detail/language";
import { useTranslation } from "#/features/components-catalog/components/detail/language-context";

const translations: Translations = {
  en: {
    dir: "ltr",
    values: {
      moreUsers: "+3",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      moreUsers: "+٣",
    },
  },
  he: {
    dir: "rtl",
    values: {
      moreUsers: "+3",
    },
  },
};

export function AvatarRtl() {
  const { dir, t } = useTranslation(translations, "ar");

  return (
    <div className="flex flex-row flex-wrap items-center gap-6 md:gap-12" dir={dir}>
      <Avatar>
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" className="grayscale" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage
          src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&q=80"
          alt="@ava"
        />
        <AvatarFallback>ER</AvatarFallback>
        <AvatarBadge className="bg-green-600 dark:bg-green-800" />
      </Avatar>
      <AvatarGroup className="grayscale">
        <Avatar>
          <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
          <AvatarFallback>CN</AvatarFallback>
        </Avatar>
        <Avatar>
          <AvatarImage
            src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=128&h=128&fit=crop&q=80"
            alt="@leo"
          />
          <AvatarFallback>LR</AvatarFallback>
        </Avatar>
        <Avatar>
          <AvatarImage
            src="https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=128&h=128&fit=crop&q=80"
            alt="@ava"
          />
          <AvatarFallback>ER</AvatarFallback>
        </Avatar>
        <AvatarGroupCount>{t.moreUsers}</AvatarGroupCount>
      </AvatarGroup>
    </div>
  );
}

Sizes

Use the size prop to change the size of the avatar.

CNCNCN
20 lines
import { Avatar, AvatarFallback, AvatarImage } from "@codefast/ui/avatar";

export function AvatarSizeExample() {
  return (
    <div className="flex flex-wrap items-center gap-2 grayscale">
      <Avatar size="sm">
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar>
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      <Avatar size="lg">
        <AvatarImage src="https://github.com/codefastlabs.png" alt="@codefast" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
    </div>
  );
}

Anatomy

How the parts nest — every slot the component exposes, in composition order.

Avatar
├── AvatarImage
└── AvatarFallback

Features

  • Three sizes (sm, default, lg); AvatarFallback and AvatarBadge scale to match automatically.
  • AvatarBadge overlays a status dot or icon at the bottom corner, sized to the avatar via the group data attribute.
  • AvatarGroup overlaps avatars with a negative margin; AvatarGroupCount caps the overflow with a +N indicator, both RTL-aware.

API reference

Props for each part of the component. All native element props are also forwarded.

Avatar

size"sm" | "default" | "lg"

Diameter of the avatar.

Default"default"

AvatarImage

AvatarFallback renders in its place when the image is missing or fails to load.

srcstring

The image URL.

altstring

Alternative text for the image.

AvatarGroup

childrenReactNode

Wrap Avatar elements to overlap them with a negative margin.

AvatarGroupCount

childrenReactNode

The +N indicator showing how many avatars are hidden from the group.

Accessibility

Built to be keyboard-navigable and screen-reader friendly out of the box.

  • Always set a meaningful alt on AvatarImage; use the person’s name.
  • AvatarFallback initials are decorative — the name should still exist in alt or nearby text.
  • The status badge is decorative; convey the same status in text where it matters.

Guidelines

Conventions that keep usage consistent across an app.

Do

  • Provide initials as a fallback for every avatar.
  • Cap stacked groups with a +N count rather than showing dozens.

Don’t

  • Don’t rely on the avatar image alone to identify a user.
  • Don’t use colour-only badges to convey critical status.

Explore further

Ready to integrate?

Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.