Marble UI
← Components

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>

PropTypeDefaultDescription
name *requiredstring—
classNamestring—
shape'circle' | 'square''circle'
size'xs' | 'sm' | 'md' | 'lg''md'
srcstring—
status'online' | 'away' | 'busy' | 'offline'—

<AvatarGroup>

PropTypeDefaultDescription
children *requiredReactNode—
extranumber—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 div and +N is plain text with no description. Add role="group" and an aria-label with the full count, such as “7 editors”.
  • The +N chip isn’t a button and has no tooltip. Show the full list elsewhere, such as in a Popover.
  • Children get a round ring in the page background color. Keep shape="circle", and on another surface override it with className="[&>*]:ring-surface".
Example source · show
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