Skip to content
ShineUI
Install

AvatarGroup

The team, stacked.

<sui-avatar-group>MiscStable

About

Overlapped avatars with a +N chip: who can see this record, who is on the engagement. Pass the people as the users property and keep max small so the row stays scannable. The chip is plain text, so put a visible count beside the stack when the exact number matters.

Usage

<sui-avatar-group max="4"></sui-avatar-group> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); const el = document.querySelector("sui-avatar-group"); el.users = [ { name: "Dana Whitfield", accent: true }, { name: "Marcus Lee" }, { name: "Priya Raman" }, { name: "Tom Gordon" }, { name: "Riley Hobbs" }, { name: "Greg Cockerel" }, ]; /* SuiAvatarGroupUser[] */ </script>
import { SuiAvatarGroup } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { const users = [ { name: "Dana Whitfield", accent: true }, { name: "Marcus Lee" }, { name: "Priya Raman" }, { name: "Tom Gordon" }, { name: "Riley Hobbs" }, { name: "Greg Cockerel" }, ]; /* SuiAvatarGroupUser[] */ return <SuiAvatarGroup max="4" users={users} />; }
<script setup> import { SuiAvatarGroup } from "@shineui/vue"; import "@shineui/core/shineui.css"; const users = [ { name: "Dana Whitfield", accent: true }, { name: "Marcus Lee" }, { name: "Priya Raman" }, { name: "Tom Gordon" }, { name: "Riley Hobbs" }, { name: "Greg Cockerel" }, ]; // SuiAvatarGroupUser[] </script> <template> <SuiAvatarGroup max="4" :users="users" /> </template>
import { Component } from "@angular/core"; import { SuiAvatarGroup } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiAvatarGroup], template: `<sui-avatar-group max="4" [users]="users"></sui-avatar-group>`, }) export class Example { users = [ { name: "Dana Whitfield", accent: true }, { name: "Marcus Lee" }, { name: "Priya Raman" }, { name: "Tom Gordon" }, { name: "Riley Hobbs" }, { name: "Greg Cockerel" }, ]; // SuiAvatarGroupUser[] }

Basic

Six people share the record and max is four, so the last two collapse into a +2 chip. Each avatar keeps its own name for assistive tech; the chip is plain text, so pair the stack with a visible count when the exact number matters.

<sui-avatar-group max="4"></sui-avatar-group>
// setup(root): properties and events setup(root) { root.querySelector('sui-avatar-group').users = roster(); }

Sizes

xs 22, sm 26, md 32 and lg 40 px. The overlap is always 20% of the size behind a 2px ring, so the stack keeps its rhythm and two initials stay whole. The ring paints the surface; on another ground, set --sui-avatar-group-ring to that ground.

<div style="display:flex;flex-direction:column;gap:14px;align-items:flex-start"> <sui-avatar-group id="ag-xs" size="xs" max="4"></sui-avatar-group> <sui-avatar-group id="ag-sm" size="sm" max="4"></sui-avatar-group> <sui-avatar-group id="ag-md" max="4"></sui-avatar-group> <sui-avatar-group id="ag-lg" size="lg" max="4"></sui-avatar-group> </div>
// setup(root): properties and events setup(root) { ['#ag-xs', '#ag-sm', '#ag-md', '#ag-lg'].forEach((sel) => { root.querySelector(sel).users = roster(); }); }

How much overflow

No chip appears while max covers everyone. Keep max small so the row stays scannable; four is the default.

max 6, nothing hidden
max 2, four collapse
max 1, the shared-with-many case
<div style="display:grid;gap:14px;justify-items:start"> <div style="display:flex;gap:12px;align-items:center"><sui-avatar-group id="ag-all" max="6"></sui-avatar-group><span style="font:460 12px/1.6 var(--font-sans);color:var(--ink-faint)">max 6, nothing hidden</span></div> <div style="display:flex;gap:12px;align-items:center"><sui-avatar-group id="ag-two" max="2"></sui-avatar-group><span style="font:460 12px/1.6 var(--font-sans);color:var(--ink-faint)">max 2, four collapse</span></div> <div style="display:flex;gap:12px;align-items:center"><sui-avatar-group id="ag-one" max="1"></sui-avatar-group><span style="font:460 12px/1.6 var(--font-sans);color:var(--ink-faint)">max 1, the shared-with-many case</span></div> </div>
// setup(root): properties and events setup(root) { ['#ag-all', '#ag-two', '#ag-one'].forEach((sel) => { root.querySelector(sel).users = roster(); }); }

On a record header

The shared-record indicator in place: who can see invoice 1043. The visible count carries the number for assistive tech.

Invoice 1043 Shared with 6 people
<div style="display:flex;gap:12px;align-items:center;max-width:420px;padding:12px 14px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--canvas)"> <span style="font:600 13px/1.4 var(--font-sans);color:var(--ink)">Invoice 1043</span> <span style="margin-left:auto;font:460 12px/1.6 var(--font-sans);color:var(--ink-faint)">Shared with 6 people</span> <sui-avatar-group id="ag-header" size="sm" max="3"></sui-avatar-group> </div>
// setup(root): properties and events setup(root) { root.querySelector('#ag-header').users = roster(); }

API

<sui-avatar-group>

Properties

PropertyAttributeTypeDefaultDescription
maxmaxnumber4How many avatars render before the +N chip, which takes the calm brand-on-soft tone.
sizesizeSuiAvatarGroupSize"lg" | "md" | "sm" | "xl" | "xs"'md'Avatar size: xs 22px, sm 26px, md 32px, lg 40px, xl 56px, the same ladder sui-avatar takes. Each avatar overlaps the previous by 20% of its size, ring included, so two initials clear the disc in front. The 2px ring paints --sui-avatar-group-ring (the surface by default): set it to the ground the stack sits on, var(--canvas) in a page header. Reflected.
usersproperty onlySuiAvatarGroupUser[][]People to show: { name, initials?, src?, accent? }[]. Property, not attribute.

Types

SuiAvatarGroupSize type
No members.
SuiAvatarGroupUser interface
name?string
initials?string
src?string
accent?boolean

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also