HyAvatarGroup
Usage examples on this page are written for Lit / plain HTML (
<hy-avatar-group>). The same component ships asHyAvatarGroupin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A stack of avatars — overlapping, ringed, capped at max with a "+N" indicator that opens the rest.
Key Features
- Sets
sizeandshapeonce for every childhy-avatar - Each avatar after the first moves back by a quarter of its size, first on top
- A ring in the page color around each stacked avatar, wider at larger sizes
- Above
max, showsmax - 1avatars and a "+N" button opening a list of the rest - The hidden avatars move into that list — the same elements, so everything set on them survives
- A name tooltip on each stacked avatar, on hover and on keyboard focus
- A
markedavatar's ring turns brand — the one editing, speaking or followed — with no change to the overlap; in the overflow list the mark sits just inside its edge
Accessibility: built in
role="group"named bylabel(required — a dev warning when missing)- One Tab stop for the stack: Left / Right (flipped right-to-left) and Home / End move between the names, each tooltip showing as its avatar is focused
- The "+N" indicator is a button named by
overflow-label("3 more"), with its popup - An
interactiveavatar in the stack stays its own Tab stop; the arrow keys skip it no-tooltipsremoves the tooltips and the stack's Tab stop, for a stack whose names are printed beside it
Accessibility: your part
- Name every avatar:
alton a photo,aria-labelon initials. The tooltip, the overflow list and screen readers all read that name. - Put what
markedmeans in that avatar's name ("Ada Lindqvist, editing"), since the ring is visual only. Mark one avatar per group, placed first. - Set
no-tooltipsonly when the names are printed beside the stack.
Children
Direct hy-avatar children only. The group writes three things on each: size, shape, and a slot attribute (avatar-0, avatar-1, …) placing it in the stack or in the overflow list. A wrapped avatar (hy-tooltip > hy-avatar) is not part of the group and triggers a dev warning.
When to use
- Who is in a team, a thread or a document, shown as one summary.
Do
- Set
maxto the number that fits, with the count for the rest.
When not to use
- Four people or fewer with room to spare: separate
hy-avatarelements with each name printed beside them. - People who each need an action (remove, message, reassign):
hy-listwith a row per person. - Where the exact membership matters, such as permissions or an audit trail: a full
hy-listof names. A stack is a summary. - An avatar that does something: set
interactiveon thehy-avatar. Never wrap it in a link or anhy-tooltip; a wrapped avatar is not shown.
Examples
Basic group
<hy-avatar-group label="Project members">
<hy-avatar src="/ada.jpg" alt="Ada Lindqvist"></hy-avatar>
<hy-avatar initials="BK" aria-label="Ben Kato"></hy-avatar>
<hy-avatar initials="CM" aria-label="Chloé Martin"></hy-avatar>
</hy-avatar-group>One avatar marked — the person editing, first in the stack
<hy-avatar-group label="People in this design system">
<hy-avatar initials="AL" aria-label="Ada Lindqvist — editing" marked></hy-avatar>
<hy-avatar initials="BK" aria-label="Ben Kato" presence="away"></hy-avatar>
<hy-avatar initials="CM" aria-label="Chloé Martin"></hy-avatar>
</hy-avatar-group>Over max, square, on another surface
<hy-avatar-group label="Connected apps" shape="square" max="3" size="large">
<hy-avatar initials="GH" aria-label="GitHub"></hy-avatar>
<hy-avatar initials="FI" aria-label="Figma"></hy-avatar>
<hy-avatar initials="SL" aria-label="Slack"></hy-avatar>
<hy-avatar initials="LI" aria-label="Linear"></hy-avatar>
</hy-avatar-group>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
label | label | string | '' | Accessible name of the group ("Project members"). Required. |
size | size | 'small' | 'medium' | 'large' | 'medium' | Size of every avatar and of the "+N" indicator. |
shape | shape | 'circle' | 'square' | 'circle' | Shape of every avatar — one shape per group. |
max | max | number | 5 | Most avatars shown, the "+N" indicator included: above it, max - 1 avatars and the indicator. 0 shows all; 1 is read as 2 (a dev warning). |
noTooltips | no-tooltips | boolean | false | Turns off the name tooltips and the stack's arrow-key focus. |
overflowLabel | overflow-label | string | '{count} more' | The indicator's accessible name, a template: {count} is the number of hidden avatars, formatted for the resolved locale. Use for internationalization. |
Events
| Event | Detail | Description |
|---|---|---|
show | — | The overflow list opened (does not bubble). Detail: AvatarGroupVisibilityDetail |
hide | — | The overflow list closed (does not bubble). Detail: AvatarGroupVisibilityDetail |
Slots
| Slot | Description |
|---|---|
default | The hy-avatar children |
CSS Parts
| Part | Description |
|---|---|
base | The group wrapper (role="group") |
indicator | The "+N" button |
overflow-list | The list of hidden avatars in the popover |
CSS Custom Properties
The documented hooks. Every override hook the component reads — one per token it paints — is listed in @whitespaceux/harmony/theme-api.json, and @whitespaceux/harmony/component-bindings.json (the Harmony MCP get-bindings tool) says which part and state each one paints.
| Property | Default | Description |
|---|---|---|
--hy-avatar-group-control-height-xs | var(--hy-control-height-xs) | Size of a small avatar, which the overlap is a quarter of |
--hy-avatar-group-control-height-sm | var(--hy-control-height-sm) | Size of a medium avatar, which the overlap is a quarter of |
--hy-avatar-group-control-height-md | var(--hy-control-height-md) | Size of a large avatar, which the overlap is a quarter of |
--hy-avatar-group-stroke-sm | var(--hy-stroke-sm) | Ring width at the small size |
--hy-avatar-group-stroke-md | var(--hy-stroke-md) | Ring width at the medium size |
--hy-avatar-group-stroke-lg | var(--hy-stroke-lg) | Ring width at the large size |
--hy-avatar-group-background-surface-base | var(--hy-background-surface-base) | Ring color, and the presence dot's cutout — re-point it on another surface |
--hy-avatar-group-border-brand-rest | var(--hy-border-brand-rest) | Ring color of a marked avatar (the stack's ring, recolored) |
--hy-avatar-group-background-muted-hover | var(--hy-background-muted-hover) | The "+N" indicator's fill on hover |
--hy-avatar-group-background-muted-pressed | var(--hy-background-muted-pressed) | The "+N" indicator's fill when pressed |
--hy-avatar-group-background-surface-elevation-4 | var(--hy-background-surface-elevation-4) | The presence dot's cutout in the overflow list (the popover's surface) |
--hy-avatar-group-radius-pill-circle | var(--hy-radius-pill-circle) | Focus ring corner around a circle avatar |
--hy-avatar-group-radius-container-sm | var(--hy-radius-container-sm) | Focus ring corner around a square avatar |
--hy-avatar-group-gap-row-list-xs-block | var(--hy-gap-row-list-xs-block) | Gap between the rows of the overflow list |
--hy-avatar-group-gap-row-list-sm-inline | var(--hy-gap-row-list-sm-inline) | Gap between an avatar and its name in the overflow list |
--hy-avatar-group-foreground-default-rest | var(--hy-foreground-default-rest) | Color of the names in the overflow list |
Methods
focus()
Focuses the stack's Tab stop, else the first interactive avatar, else the indicator.
show()
Opens the overflow list, when there is one.
hide()
Closes the overflow list.