Skip to content

Avatar Group

DisplayWeb + NativeMIT
View in Storybook

Stacked overlapping avatars with overflow count for team and member lists.

bun add @otfdashkit/ui

Preview

Avatar Group
Loading Storybook preview…

Code

import { Avatar, AvatarFallback, AvatarImage, AvatarGroup } from '@otfdashkit/ui'

const TEAM = [
  { initials: 'SC', src: 'https://i.pravatar.cc/64?img=47' },
  { initials: 'AR', src: 'https://i.pravatar.cc/64?img=12' },
  { initials: 'KL', src: 'https://i.pravatar.cc/64?img=22' },
  { initials: 'JD', src: 'https://i.pravatar.cc/64?img=33' },
  { initials: 'MP', src: 'https://i.pravatar.cc/64?img=51' },
  { initials: 'TS', src: 'https://i.pravatar.cc/64?img=58' },
  { initials: 'VR', src: 'https://i.pravatar.cc/64?img=64' },
] as const

export function Example() {
  return (
    <div className="flex flex-col gap-8">
      <div className="space-y-2">
        <p className="text-xs font-mono uppercase tracking-widest text-[hsl(var(--muted-foreground))]">Default · max 4</p>
        <AvatarGroup max={4}>
          {TEAM.map((m) => (
            <Avatar key={m.initials}>
              <AvatarImage src={m.src} alt={m.initials} />
              <AvatarFallback>{m.initials}</AvatarFallback>
            </Avatar>
          ))}
        </AvatarGroup>
      </div>

      <div className="space-y-2">
        <p className="text-xs font-mono uppercase tracking-widest text-[hsl(var(--muted-foreground))]">Compact · 24px / -10px overlap</p>
        <AvatarGroup max={5} size={24} spacing={10}>
          {TEAM.slice(0, 7).map((m) => (
            <Avatar key={m.initials}>
              <AvatarImage src={m.src} alt={m.initials} />
              <AvatarFallback className="text-[8px]">{m.initials}</AvatarFallback>
            </Avatar>
          ))}
        </AvatarGroup>
      </div>

      <div className="space-y-2">
        <p className="text-xs font-mono uppercase tracking-widest text-[hsl(var(--muted-foreground))]">Large · custom overflow</p>
        <AvatarGroup
          max={3}
          size={48}
          renderOverflow={(n) => `+${n}`}
        >
          {TEAM.map((m) => (
            <Avatar key={m.initials}>
              <AvatarImage src={m.src} alt={m.initials} />
              <AvatarFallback>{m.initials}</AvatarFallback>
            </Avatar>
          ))}
        </AvatarGroup>
      </div>

      <div className="space-y-2">
        <p className="text-xs font-mono uppercase tracking-widest text-[hsl(var(--muted-foreground))]">Fallback only · no images</p>
        <AvatarGroup max={5}>
          {TEAM.map((m) => (
            <Avatar key={m.initials}>
              <AvatarFallback>{m.initials}</AvatarFallback>
            </Avatar>
          ))}
        </AvatarGroup>
      </div>
    </div>
  )
}

Free with the SDK. This component ships in @otfdashkit/ui under the MIT license.

Kit for this component

Everything Bundle$149 · 6 kits + 20 templates

Show a stack of user avatars for a team or member list.

See the kit

Props

Props declared in the AvatarGroup source. Inherited HTML attributes are not listed.

PropTypeDefaultDescription
maxnumber4Maximum avatars rendered before collapsing into a "+N" tile. Default 4.
renderOverflow(remaining: number) => ReactNodeCustom node for the overflow tile. Falls back to "+{remaining}".
sizenumber32Pixel size of each avatar tile. Default 32.
spacingnumberPixel overlap between adjacent avatars. Default size / 3.