SvAvatarGroup

Overlapping, stacked avatars with a "+N" overflow pill - the "assigned to" and "members" row for cards, tables, and detail panels.

SvAvatarGroup takes an array of avatar descriptors and renders them as a neat overlapping stack, capping the count with max and rolling the rest into a "+N" pill. Each entry is a subset of SvAvatar props, so the same initials-and-color fallback applies to every face.

Basic usage

<script lang="ts">
  import { SvAvatarGroup } from '@svgrid/grid'
</script>

<SvAvatarGroup max={3} avatars={[
  { name: 'Ada Lovelace' },
  { name: 'Alan Turing' },
  { name: 'Grace Hopper' },
  { name: 'Ken Thompson' },
]} />

Props

Prop Type Default Description
avatars ReadonlyArray<AvatarProps> - The people/entities to stack (see the entry shape below).
max number 4 How many avatars to show before collapsing to "+N".
size sm | md | lg | number md Size preset or explicit pixel size, applied to every avatar.

The avatar entry shape

Each item is a compact subset of the SvAvatar props:

type AvatarProps = {
  name?: string   // initials + deterministic fallback color
  src?: string    // image URL
  alt?: string    // accessible name
  color?: string  // override the fallback color
}

The overlap and the "+N" pill size scale automatically with size.

Patterns

Assignees on a card

Drop a group into a card footer to show who is on a task:

<SvAvatarGroup size="sm" max={4} avatars={task.assignees} />

Overflow tuning

Lower max in tight rows so more faces roll into the "+N" pill:

<SvAvatarGroup max={2} avatars={team} />
<!-- shows 2 faces then +N for the rest -->

Mixing images and initials

Entries with a src render the photo; entries without fall back to initials - in the same stack:

<SvAvatarGroup avatars={[
  { name: 'Ada Lovelace', src: '/ada.jpg' },
  { name: 'Grace Hopper' },
]} />

Reviewers from records

Map your own member objects to the compact entry shape, then let max collapse the tail into "+N" - ideal for an "assigned to" cell or a card footer:

<script lang="ts">
  import { SvAvatarGroup } from '@svgrid/grid'

  type Member = { id: string; fullName: string; photoUrl?: string }
  let reviewers = $state<Member[]>([])

  const faces = $derived(
    reviewers.map((m) => ({ name: m.fullName, src: m.photoUrl }))
  )
</script>

<div style="display:flex; align-items:center; gap:8px;">
  <SvAvatarGroup size="sm" max={4} avatars={faces} />
  <span style="color:var(--sg-muted); font-size:12px;">{reviewers.length} reviewers</span>
</div>

Tip: the overlap and the "+N" pill scale from size, so switching to size="sm" in a dense grid row keeps the stack tight without any manual spacing.

Accessibility

See also