Avatar Group
Preview: Group
Image with initials fallback (Base UI Avatar handles loading/error states).
Import
import { Avatar, AvatarGroup } from '@marbleui/ui'This is a style of avatar; see its examples for all variants.
Props
<Avatar>
| Prop | Type | Default | Description |
|---|---|---|---|
| name *required | string | — | |
| className | string | — | |
| shape | 'circle' | 'square' | 'circle' | |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | |
| src | string | — | |
| status | 'online' | 'away' | 'busy' | 'offline' | — |
<AvatarGroup>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| extra | number | — | Number of hidden people to show as "+N". |
| size | 'xs' | 'sm' | 'md' | 'lg' | 'sm' |
Also accepts HTML element props (277).
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: Base UI Avatar. Follow the primitive's docs for the full keyboard map.
Usage notes
Overlapping row of avatars for the people on a document or project. It doesn’t truncate on its own: render the first few and pass the rest as extra. To collapse by available width into a menu, use OverflowList.
const shown = editors.slice(0, 3)
<AvatarGroup role="group" aria-label={`${editors.length} editors`} extra={editors.length - shown.length}>
{shown.map((e) => <Avatar key={e.id} size="sm" name={e.name} src={e.photo} />)}
</AvatarGroup>
- The group is a plain
divand+Nis plain text with no description. Addrole="group"and anaria-labelwith the full count, such as “7 editors”. - The
+Nchip isn’t a button and has no tooltip. Show the full list elsewhere, such as in aPopover. - Children get a round ring in the page background color. Keep
shape="circle", and on another surface override it withclassName="[&>*]:ring-surface".
Example source · show· hide
import { Avatar, AvatarGroup } from './avatar'
const photo = (id: string) => `https://images.unsplash.com/photo-${id}?w=128&h=128&fit=crop&crop=faces&q=80`
const people = [
{ name: 'Maya Chen', src: photo('1494790108377-be9c29b29330') },
{ name: 'Charles Webb', src: photo('1500648767791-00dcc994a43e') },
{ name: 'Ada Lovelace' },
{ name: 'Grace Hopper' },
]
export const styles = {
Sizes: () => (
<div className="flex items-end gap-3">
<Avatar size="xs" {...people[0]!} />
<Avatar size="sm" {...people[0]!} />
<Avatar size="md" {...people[0]!} />
<Avatar size="lg" {...people[0]!} />
</div>
),
Fallback: () => (
<div className="flex items-center gap-3">
<Avatar name="Ada Lovelace" />
<Avatar name="Grace Hopper" shape="square" />
<Avatar name="Broken Image" src="https://example.invalid/nope.png" />
</div>
),
Status: () => (
<div className="flex items-center gap-4">
<Avatar {...people[0]!} status="online" />
<Avatar {...people[1]!} status="away" />
<Avatar name="Ada Lovelace" status="busy" />
<Avatar name="Grace Hopper" status="offline" />
</div>
),
Group: () => (
<AvatarGroup extra={5}>
{people.map((p) => (
<Avatar key={p.name} size="sm" {...p} />
))}
</AvatarGroup>
),
}Source: packages/ui/src/avatar/avatar.tsx
Catalog
- Category
- data-display
- Priority
- Core
- Primitive
- composed
- Base UI
- Avatar