Velora UI
All components

Avatar Circles

Stacked initials avatars with a +N badge — zero images.

0.6 KB gzippedZero dependenciesReduced-motion safeBase UI & Radix compatible
MCTOSLDR+2k

Installation

npx shadcn@latest add https://velora.colorlib.com/r/avatar-circles.json

Source

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

interface AvatarCirclesProps extends React.HTMLAttributes<HTMLDivElement> {
  /** Names rendered as initials */
  people: string[];
  /** "+N" badge count */
  extra?: number;
}

const tones = [
  "bg-blue-600",
  "bg-slate-600",
  "bg-sky-700",
  "bg-indigo-600",
  "bg-slate-700",
  "bg-blue-800",
];

export function AvatarCircles({
  people,
  extra,
  className,
  ...props
}: AvatarCirclesProps) {
  return (
    <div
      data-slot="avatar-circles"
      className={cn("flex -space-x-3", className)}
      {...props}
    >
      {people.map((name, i) => {
        const initials = name
          .split(" ")
          .map((w) => w[0])
          .slice(0, 2)
          .join("");
        return (
          <span
            key={name}
            title={name}
            className={cn(
              "flex size-10 items-center justify-center rounded-full text-xs font-semibold text-white ring-2 ring-background",
              tones[i % tones.length]
            )}
          >
            {initials}
          </span>
        );
      })}
      {extra && (
        <span className="flex size-10 items-center justify-center rounded-full bg-muted text-xs font-semibold ring-2 ring-background">
          +{extra >= 1000 ? `${Math.floor(extra / 1000)}k` : extra}
        </span>
      )}
    </div>
  );
}