Avatar Group

An overlapping stack of avatars with built-in overflow. Cap how many show and the rest fold into a +N chip. The group owns the overlap, the ring separation and the hover lift; the children stay plain Avatars.

JEMDLCSR+5

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add avatar-group

Usage#

Wrap your Avatar children in AvatarGroup and set max. The group owns only the layout and the overflow chip: the avatars stay plain Avatars with no per-instance ring or z-index. Match the group's size to its children.

team.tsxTSX
import { AvatarGroup } from "@/components/ui/avatar-group"import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"export function Team({ members }: { members: Member[] }) {  return (    <AvatarGroup size="md" max={4} total={members.length}>      {members.slice(0, 4).map((m) => (        <Avatar key={m.id} size="md">          <AvatarImage src={m.avatar} alt={m.name} />          <AvatarFallback>{m.initials}</AvatarFallback>        </Avatar>      ))}    </AvatarGroup>  )}

Sizes#

Set size on the group to match the avatars; it sizes the +N chip and tightens the overlap as the box grows, so the stack stays a single cluster at every size.

sm
JMLS+5
md
JEMDLCSR+5
lg
JEMDLCSR+5

Fallbacks#

With no image the avatar shows its initials. Inside a group, give each fallback a color so the stack reads as distinct people instead of a row of identical gray chips: pass one of the Avatar color hues per child and stride-mix them so no two neighbours share a tint. The neutral gray default is fine for a lone avatar, not for a cluster. The +N chip stays neutral since it's a count, not initials.

NBEMCWWEGO

Overflow#

max caps the avatars shown; everything past it collapses into a single +N chip. Pass total when more people exist than you render (e.g. a server count) so the chip reflects the real number. Omit max to show every avatar.

max 2
JEMD+7
max 3
JEMDLC+6
no max
JEMDLCSR+5

Custom overflow#

Take over the chip with renderOverflow, which receives the overflow count. Return any node: here the chip is a Tooltip that names the people the stack hides, riding the same shared bubble as the avatars.

JEMDLCSR+5

API reference#

AvatarGroup

A <div> that lays out its Avatar children as an overlapping stack and appends the overflow chip. Its children sit inside a TooltipGroup, so every Tooltip in the stack shares one gliding bubble. Forwards all native div props; className is merged last.

  • size — xs | sm | md | lg | xl (default md). Sizes the chip and the overlap; pass the same value you set on the children.
  • max — cap the visible avatars; the rest fold into the +N chip.
  • total — the real count when it exceeds the rendered avatars, so +N reflects it.
  • renderOverflow — (overflow: number) => ReactNode; replace the default chip with a custom affordance.

FAQ#

Use AvatarGroup whenever you stack collaborators: it owns the overlap, the `ring-background` separation, and the hover lift, and adds a `+N` overflow chip via `max`. Hand-rolling those classes on each Avatar drifts the moment the recipe changes, which is exactly what this component prevents.