AvatarStack
Overlapping cluster of group members.
The gap is shaped, not circular
Each disc punches a hole in the one behind it using the neighbour's own silhouette as a mask, not a circle.
A circular cut-out looks correct only when the shape in front is round. Against a hexagon it bites into one side and leaves a wedge on the other, and the gap appears to vary in width as you look around the edge. Using the real outline keeps the separation even for every shape.
Overflow
Members past maxVisible collapse into a +N chip.
The arithmetic, without the component
Three helpers carry the cluster's numbers to places that are not rendering it: a popover that has to line up with the third face, a row that needs the width before it lays out, a test that checks the maths without a DOM.
layoutAvatarStack(count, sizePx, { overlap, withOverflow })returns the leftoffsetsof each disc in draw order, theoverlapactually used and the totalwidth, including the overflow slot when reserved. The last disc contributes its whole width; every earlier one only the part its neighbour does not hide.stackMetrics(size)gives sensible proportions for each avatar size —sizePx,overlapandmaxVisible. Small clusters overlap harder and show fewer faces: atxs, three discs at the usual overlap are a smear, and two at a tighter one still read as "a group", which is all the size can carry.participantsFromMembers(members, max)splits a membership list into thevisiblefaces and ahiddencount for the chip.maxdefaults toSTACK_MAX_VISIBLE(3);STACK_OVERLAP(0.36) is the default overlap.
API
| Prop | Type | Default | Description |
|---|---|---|---|
members* | AgentLike[] | — | — |
className | string | — | — |
face | "cute" | "eyes" | "line" | — | Face style for every member, overriding their identities. |
lineWeight | number | — | Stroke width multiplier for every member. |
maxVisible | number | — | Faces to draw before the "+N" chip. Defaults to the size band's count. |
nose | "slant" | "angular" | "hook" | "long" | "curve" | "bow" | null | — | Nose for every member, overriding their identities. `null` draws none. |
overlap | number | — | How far each disc overlaps the previous one, as a fraction of its size. Defaults to the proportions for the nearest avatar size band. |
showOverflow | boolean | true | Show a "+N" chip when there are more members than fit. |
sizePx | number | 28 | — |
style | CSSProperties | — | — |
GroupAvatar
Convenience wrapper that reads members off a group record.
| Prop | Type | Default | Description |
|---|---|---|---|
group* | AgentLike | — | — |
className | string | — | — |
face | "cute" | "eyes" | "line" | — | Face style for every member, overriding their identities. |
lineWeight | number | — | Stroke width multiplier for every member. |
nose | "slant" | "angular" | "hook" | "long" | "curve" | "bow" | null | — | Nose for every member, overriding their identities. `null` draws none. |
sizePx | number | 28 | — |
style | CSSProperties | — | — |
Next
- Badges and status — unread counts and status dots
- Agent roster — twenty faces down the side