Avatar Group
Headless avatar stack with a bounded tile count and an accessible overflow tile.
| Package | @vizejs/ui/avatar-group |
| Maturity | stable |
| Own the source | vize lib pull avatar-group |
| Requires | avatar |
| Aliases | avatar group, avatar stack, facepile, people list |
| Covers | Chakra UI AvatarGroup, MUI AvatarGroup, Mantine Avatar.Group |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/ui
Add the public import below to <script setup lang="ts">. Components provide behavior without styles; the preview uses optional Paper styles.
import { AvatarGroup, AvatarGroupOverflow } from "@vizejs/ui/avatar-group";
Or copy the source into your project with vize lib pull avatar-group (see Source Distribution).
Try it
This is the basic example maintained with the component source, using the public package imports. The preview adds the optional Paper styles.
Open the interactive example · Styling these components
Copy the example
<!-- Reviewer stack capped at four tiles, collapsing the rest into an accessible "+N more" tile. -->
<script setup lang="ts">
import { AvatarGroup } from "@vizejs/ui/avatar-group";
interface Reviewer {
readonly name: string;
readonly initials: string;
}
const reviewers: readonly Reviewer[] = [
{ name: "Ada Lovelace", initials: "AL" },
{ name: "Grace Hopper", initials: "GH" },
{ name: "Linus Torvalds", initials: "LT" },
{ name: "Barbara Liskov", initials: "BL" },
{ name: "Alan Kay", initials: "AK" },
{ name: "Margaret Hamilton", initials: "MH" },
];
</script>
<template>
<AvatarGroup :items="reviewers" :max="4" :spacing="-8" aria-label="Reviewers">
<template #item="{ item }">
<span role="img" :aria-label="item.name">{{ item.initials }}</span>
</template>
</AvatarGroup>
</template>
API
AvatarGroup<Item>
Source: src/families/layout/avatar-group/avatar-group.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items (required) |
readonly Item[] |
required |
People rendered as avatar tiles, in order. |
max |
number |
undefined |
Maximum number of tiles, including the overflow tile. undefined never collapses. |
total |
number |
undefined |
Total number of people when items is a page of a larger set; the remainder joins the overflow count. |
spacing |
number | string |
undefined |
Overlap or gap published as --vize-ui-avatar-group-spacing. Numbers are pixels. |
messages |
AvatarGroupMessageOverrides | undefined |
undefined |
Localized overflow strings. |
ariaLabel |
string |
undefined |
Accessible list name, e.g. "Project members". |
ariaLabelledby |
string |
undefined |
Space-separated ids that label the list. |
Slots
| Slot | Slot props | Description |
|---|---|---|
item |
AvatarGroupItemSlotState<Item> |
Renders one visible person, typically an Avatar. |
overflow |
AvatarGroupOverflowSlotState<Item> |
Replaces the default overflow tile. Receives the hidden items and count. |
Exposed
| Member | Type | Description |
|---|---|---|
visibleItems |
readonly Item[] |
Items rendered as tiles. |
hiddenItems |
readonly Item[] |
Items collapsed into the overflow tile. |
overflowCount |
number |
Hidden count including any total remainder. |
state |
AvatarGroupState |
Stable state token. |
element |
HTMLUListElement | null |
Rendered list element. |
AvatarGroupOverflow<Item>
Source: src/families/layout/avatar-group/avatar-group-overflow.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
count (required) |
number |
required |
Number of hidden people announced by the tile. |
items |
readonly Item[] |
undefined |
Hidden items forwarded to the slot, e.g. for a tooltip listing names. |
messages |
AvatarGroupMessageOverrides | undefined |
undefined |
Localized overflow strings. |
Slots
| Slot | Slot props | Description |
|---|---|---|
default |
AvatarGroupOverflowSlotState<Item> |
Overflow tile content. Defaults to the overflowText message, e.g. "+3". |
Exposed
| Member | Type | Description |
|---|---|---|
element |
HTMLSpanElement | null |
Rendered overflow element. |
count |
number |
Hidden count announced by the tile. |
Behavior
Normative state x input -> outcome table for avatar-group.vue and
avatar-group-overflow.vue (@vizejs/ui/avatar-group). Every row is proven by
the named test.
AvatarGroup renders a native <ul> of <li> tiles. The item slot renders each
visible person (typically an Avatar). max bounds every tile, including the
overflow tile. The overflow tile is role="img" with an accessible "N more"
name, and it wraps an aria-hidden Avatar showing "+N".
| ID | State | Input | Outcome | Evidence |
|---|---|---|---|---|
| AG1 | no max |
render | a labelled list renders every item through the item slot, data-state="expanded", and no overflow tile |
renders a labelled list of avatars without collapsing by default |
| AG2 | max exceeded |
render | max - 1 items plus one overflow tile render; the tile is role="img" named "N more" showing "+N" |
max counts the overflow tile and announces hidden people |
| AG3 | total |
render | people beyond items join the overflow count, with or without max |
total adds server-side people to the overflow count |
| AG4 | messages/spacing | render | overflow name and text come from typed messages; spacing publishes --vize-ui-avatar-group-spacing |
localized messages, spacing, and empty groups |
| AG5 | empty | render | data-state="empty" and no tiles |
localized messages, spacing, and empty groups |
| AG6 | custom overflow | overflow slot |
the slot receives typed hidden items, count, label, and text | the overflow slot receives hidden items for custom tiles |
| AG7 | reactive props | max/items change |
the split re-computes; the instance exposes state, visible/hidden items, overflow count, and element | items and max are reactive and the instance exposes the split |
| AG8 | pure helpers | splitAvatarGroup() etc. |
invalid max/total never collapse; spacing rejects declaration injection |
splits groups, resolves messages, and sanitizes spacing |
| AG9 | SSR | isolated requests | markup is byte-identical | renders byte-identical avatar group markup across isolated SSR requests |
| AG10 | SSR / hydration | hydrate | server markup hydrates without warnings or node replacement | hydrates avatar group markup without warnings or node replacement |
| AG11 | types | compile | item types flow from items into slots and exposes; states and messages are closed |
avatar-group.types.test-d.ts |