Avatar Group
- Stable
- WCAG 2.2 evidence
- RTL
A row of overlapping avatars with a "+N" chip for the rest. The group sizes its
avatars, draws the first count of them, and counts the others in a chip made of real text: "+4" is shown, and screen
readers hear "and 4 more" (or your moreLabel), so the number is not lost and not read twice (WCAG 1.1.1, 1.3.1, 1.4.1).
It is a plain row, not a list or a control: give it aria-label to make it a named group ("Project members"). Overlap
reverses in right-to-left layouts. Presentational: renders in React Server Components, without React Aria. Consumer duties: name every avatar (or the group), and do not rely on the avatars alone to say who is in a team where that
matters (list the people elsewhere). Figma draws no ring on the overlapping avatars, so avatars of the same tint merge into
one shape: use photos or distinct initials, or give the avatars a ring with className. Make the group a link or button by
wrapping it.
import { AvatarGroup } from "@nexera-ui/react";- 6
- examples
- 5
- props
- 2
- live controls
- 1
- platform
- 4
- WCAG criteria
- 3
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { AvatarGroup } from "@nexera-ui/react";
<AvatarGroup />Examples 5
The same examples as Storybook, rendered live. Open Code to copy one.
Overflow chip
count is how many avatars are drawn and the rest are counted for you. Pass more when the group holds only some of the people (the first page of a longer list): a number becomes "+N" and is read as "and N more"; text is shown as written.
import { AvatarGroup } from "@nexera-ui/react";
const people = [
["AK", "Ayesha Khan"],
["BA", "Bilal Ahmed"],
["CL", "Chen Li"],
["DM", "Dana Mills"],
["EN", "Elif Nur"],
["FR", "Farah Rizvi"],
["GS", "Gita Sharma"],
["HT", "Hugo Tran"],
] as const;
const avatars = (total: number) => people.slice(0, total);
export function OverflowChip() {
return (
<div className="flex flex-col gap-6">
<AvatarGroup size="md" aria-label="Derived: 8 people, 3 drawn">
{avatars(8)}
</AvatarGroup>
<AvatarGroup size="md" count={5} aria-label="Derived: 8 people, 5 drawn">
{avatars(8)}
</AvatarGroup>
<AvatarGroup size="md" more={120} aria-label="Given number: 3 people and 120 more">
{avatars(3)}
</AvatarGroup>
<AvatarGroup size="md" more="99+" moreLabel="and many more" aria-label="Given text">
{avatars(3)}
</AvatarGroup>
<AvatarGroup size="md" aria-label="Everyone fits, no chip">
{avatars(2)}
</AvatarGroup>
</div>
);
}
With photos and rings
Photos separate better than same-tint initials. Figma draws no ring on the avatars (only the chip has one); add one with className on the avatars when your design wants it.
import { Avatar, AvatarGroup } from "@nexera-ui/react";
const people = [
["AK", "Ayesha Khan"],
["BA", "Bilal Ahmed"],
["CL", "Chen Li"],
["DM", "Dana Mills"],
["EN", "Elif Nur"],
["FR", "Farah Rizvi"],
["GS", "Gita Sharma"],
["HT", "Hugo Tran"],
] as const;
const photo = (colour: string) =>
`data:image/svg+xml,${encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><rect width="40" height="40" fill="${colour}"/>` +
'<circle cx="20" cy="15" r="7.6" fill="white" fill-opacity="0.92"/>' +
'<ellipse cx="20" cy="38" rx="15.6" ry="12" fill="white" fill-opacity="0.92"/></svg>',
)}`;
const colours = ["steelblue", "seagreen", "darkorange", "mediumpurple", "firebrick"] as const;
export function WithPhotosAndRings() {
return (
<div className="flex flex-col gap-6">
<AvatarGroup size="lg" aria-label="Photos">
{colours.map((colour, index) => (
<Avatar
key={colour}
type="photo"
src={photo(colour)}
initials={people[index]?.[0]}
label={people[index]?.[1] ?? "Member"}
/>
))}
</AvatarGroup>
<AvatarGroup size="lg" aria-label="Photos with a ring" count={5}>
{colours.map((colour, index) => (
<Avatar
key={colour}
type="photo"
src={photo(colour)}
initials={people[index]?.[0]}
label={people[index]?.[1] ?? "Member"}
className="ring-surface rounded-full ring-2"
/>
))}
</AvatarGroup>
</div>
);
}
Translated label
The "and N more" text is translatable. German here; the visible "+N" stays.
import { AvatarGroup } from "@nexera-ui/react";
const people = [
["AK", "Ayesha Khan"],
["BA", "Bilal Ahmed"],
["CL", "Chen Li"],
["DM", "Dana Mills"],
["EN", "Elif Nur"],
["FR", "Farah Rizvi"],
["GS", "Gita Sharma"],
["HT", "Hugo Tran"],
] as const;
const avatars = (total: number) => people.slice(0, total);
export function TranslatedLabel() {
return (
<AvatarGroup size="md" moreLabel="und {count} weitere Personen" aria-label="Projektmitglieder">
{avatars(7)}
</AvatarGroup>
);
}
Many people
Many avatars in a narrow container: count keeps the row short, so nothing scrolls at 320 px.
import { AvatarGroup } from "@nexera-ui/react";
const people = [
["AK", "Ayesha Khan"],
["BA", "Bilal Ahmed"],
["CL", "Chen Li"],
["DM", "Dana Mills"],
["EN", "Elif Nur"],
["FR", "Farah Rizvi"],
["GS", "Gita Sharma"],
["HT", "Hugo Tran"],
] as const;
const avatars = (total: number) => people.slice(0, total);
export function ManyPeople() {
return (
<div className="max-w-xs">
<AvatarGroup size="lg" count={5} aria-label="Whole company">
{avatars(8)}
</AvatarGroup>
</div>
);
}
Right to left
Right-to-left: the overlap and the chip mirror (the chip ends up on the left), and "+4" keeps its order.
import { Avatar, AvatarGroup } from "@nexera-ui/react";
const arabicPeople = [
["أخ", "أيشة خان"],
["بأ", "بلال أحمد"],
["شل", "شين لي"],
["دم", "دانا ميلز"],
["إن", "إيليف نور"],
["فر", "فرح رضوي"],
["غش", "غيتا شارما"],
] as const;
export function RightToLeft() {
return (
<div dir="rtl" lang="ar">
<AvatarGroup size="md" moreLabel="و{count} آخرين" aria-label="أعضاء المشروع">
{arabicPeople.map(([initials, name]) => (
<Avatar key={name} initials={initials} label={name} />
))}
</AvatarGroup>
</div>
);
}
Props 5
Press "Try it" on a card to load that prop into the playground.
5 props shown
children*NexeraReactNodeThe avatars, one Avatar per person. The group sets their size,
so you do not repeat it. Pass the avatars directly or from an array: a fragment counts as one item. Name each avatar
(label), because a group of people is read person by person.
sizeNexera"sm" | "md" | "lg"Size of the group and of its avatars: 24, 32 or 40 px.
countNexeranumberHow many avatars are drawn. Avatars beyond it are not rendered and are counted in the "+N" chip. It is a number, so a group can draw 4 or 7 as well.
moreNexerastring | numberThe text of the "+N" chip. When it is left out the chip shows "+N" for the
N avatars that were not drawn, and there is no chip when all avatars fit. Pass a number (shown as "+N") or a string when
the group holds only some of the people, for example the first page of a longer list ("+99"). This is Figma Show more:
the chip is shown when there is something to show.
moreLabelNexerastringText for assistive technology that replaces the visible "+N", with {count} standing for the number: "and {count} more".
Translate it for your locale. {count} is the number of avatars not drawn, or more when it is a number.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
3 direct · 1 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 4.1.2Name, Role, ValueLevel A · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
<AvatarGroup className="shadow-sm" />Used in blocks
- Invite your teamOnboarding
- Team availabilityScheduling and calendar
- Event detailsScheduling and calendar
Related components
- AccordionItemOne collapsible section of an FAQ or settings page.
- AreaChartA stacked area chart: layers piled up over time with the title, range switch, actions and legend of the card.
- AvailabilityRowOne person's availability across a window of the day: an avatar with initials and the name, and a timeline with the busy periods drawn as bars.
- AvatarA person or organisation shown as a photo, initials or an icon.
- AvatarLabelAn avatar with a name and an optional subtitle beside it, for a person in a list, a header or a mention.
- BadgeShort status or category label: `Tone` x `Variant` x `Size`, with an optional dot, leading icon and remove button.
- BadgeGroupA pill that pairs a small badge with a short message, for an announcement or a status line.
- BadgeOverflowThe "+N" pill that stands in for the badges a row has no room for.