# Avatar group

Overlapping avatars for the people on a project or a thread, and a count of the rest.

Block: `smbk-avatar-group`. Status: experimental. Figma: the Figma file, https://www.figma.com/community/file/1688324308358870630. Desktop and mobile: differ by presentation only.

## Options

| Axis | Values | Default | Meaning |
|---|---|---|---|

Parts: `smbk-avatar-group__item`, `smbk-avatar-group__more`, `smbk-avatar-group__hidden`

## Markup

```html
<ul role="list" aria-label="6 people" class="smbk-avatar-group">
  <li class="smbk-avatar-group__item">
    <span
      class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-brand smbk-avatar--type-initials"
      role="img"
      aria-label="Sofia Ribeiro"
    >
      <span class="smbk-avatar__initials" aria-hidden="true">SR</span>
    </span>
  </li>
  <li class="smbk-avatar-group__item">
    <span
      class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-brand smbk-avatar--type-initials"
      role="img"
      aria-label="Ana Silva"
    >
      <span class="smbk-avatar__initials" aria-hidden="true">AS</span>
    </span>
  </li>
  <li class="smbk-avatar-group__item">
    <span
      class="smbk-avatar smbk-avatar--size-xs smbk-avatar--tone-brand smbk-avatar--type-initials"
      role="img"
      aria-label="Jonas Turner"
    >
      <span class="smbk-avatar__initials" aria-hidden="true">JT</span>
    </span>
  </li>
  <li class="smbk-avatar-group__more">
    <span aria-hidden="true">+3</span>
    <span class="smbk-avatar-group__hidden">and 3 more</span>
  </li>
</ul>
```

## React

```tsx
import { AvatarGroup } from './design-system/components/avatar-group/avatar-group.js';

<AvatarGroup people={[{ name: "Sofia Ribeiro" }, { name: "Ana Silva" }, { name: "Jonas Turner" }, { name: "Kim Lee" }, { name: "Dana Novak" }, { name: "Rui Costa" }]} label="6 people" />
```

## Stylesheet

```css
/* smbk-avatar-group — Avatar group. Figma "Avatar group" 7580:1856 (Count: 3, 4, 5; More text; Show more).
 * Extra small avatars in a row, each in a ring of the default surface (the
 * 2 step around it), overlapping the one before by 6, then a count of the
 * rest: a solid pill, the sunken shade over the default surface, in Label SM
 * and the subtle text color, in the same ring. Each later face sits over the one before. The overlap is
 * written from the start edge, so it mirrors in right-to-left text. The
 * avatars keep their own classes; this stylesheet adds the ring, the overlap
 * and the count. */

.smbk-avatar-group {
  display: inline-flex;
  align-items: center;
  vertical-align: middle;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The block frames the words it hides for screen readers, so they stay inside it wherever it is placed: without a
   frame they hang from the page itself and stretch it, past the end of an area that scrolls. No weight, so a parent
   that places the block keeps its say. */
:where(.smbk-avatar-group) {
  position: relative;
}

.smbk-avatar-group__item {
  display: inline-flex;
  padding: var(--smbk-space-2);
  border-radius: var(--smbk-radius-full);
  background: var(--smbk-color-surface-default);
}

.smbk-avatar-group > :not(:first-child) {
  margin-inline-start: calc(-1 * var(--smbk-space-6));
}

/* The count: as tall as an avatar inside the same ring, so the row's faces and the count line up. Solid: the
   see-through sunken shade over the ring's own surface, so the face it overlaps never shows through it. */
.smbk-avatar-group__more {
  box-sizing: content-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--smbk-size-24);
  height: var(--smbk-size-24);
  padding-inline: var(--smbk-space-6);
  border: var(--smbk-border-width-emphasis) solid var(--smbk-color-surface-default);
  border-radius: var(--smbk-radius-full);
  background: linear-gradient(var(--smbk-color-surface-sunken), var(--smbk-color-surface-sunken)), var(--smbk-color-surface-default);
  background-clip: padding-box;
  color: var(--smbk-color-text-subtle);
  font-family: var(--smbk-typography-label-sm-font-family);
  font-size: var(--smbk-typography-label-sm-font-size);
  font-weight: var(--smbk-typography-label-sm-font-weight);
  line-height: var(--smbk-typography-label-sm-line-height);
  letter-spacing: var(--smbk-typography-label-sm-letter-spacing);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Words for screen readers only: "and 3 more" behind the visible "+3". */
/* .smbk-avatar-group__hidden: hidden from view, kept for screen readers and the keyboard, by the shared rule in visually-hidden/visually-hidden.css. */

/* ---- high contrast (forced colors) ---- */
/* In Windows high-contrast mode the browser drops fills and shadows; this puts the meaning back with the
   user's own colors. Nothing here applies outside that mode. */

@media (forced-colors: active) {
  /* The ring is a fill and would vanish, leaving the faces running into each other; it takes the
     palette's background, and the count its text color as an edge. */
  .smbk-avatar-group__item {
    forced-color-adjust: none;
    background: Canvas;
  }

  .smbk-avatar-group__more {
    border-color: CanvasText;
  }
}
```

## Tokens it reads

```json
{
  "space": {
    "2": {
      "$type": "dimension",
      "$value": "2px",
      "$description": "Raw space step, 2 px. Only for fixed distances inside a component; spacing that follows density uses space/inset, stack or inline."
    },
    "6": {
      "$type": "dimension",
      "$value": "6px",
      "$description": "Raw space step, 6 px. Only for fixed distances inside a component; spacing that follows density uses space/inset, stack or inline."
    }
  },
  "radius": {
    "full": {
      "$type": "dimension",
      "$value": "{{radius.9999}}",
      "$description": "Capsule: pills, chips, switches."
    }
  },
  "color": {
    "surface": {
      "default": {
        "$type": "color",
        "$value": "{{color.grey.100}}",
        "$description": "Standard surface: cards, panels, the header."
      },
      "sunken": {
        "$type": "color",
        "$value": "{{color.alpha.grey-800.5}}",
        "$description": "Recessed wells: fields, tracks, code. See-through, so a well always shows one step below what it sits on: the page, a card or a panel."
      }
    },
    "text": {
      "subtle": {
        "$type": "color",
        "$value": "{{color.grey.700}}",
        "$description": "Secondary text: descriptions, metadata."
      }
    }
  },
  "size": {
    "24": {
      "$type": "dimension",
      "$value": "24px",
      "$description": "Raw size step, 24 px. Only for fixed sizes inside a component; semantic sizes (size/control, icon, mark) point here."
    }
  },
  "border-width": {
    "emphasis": {
      "$type": "dimension",
      "$value": "{{border-width.2}}",
      "$description": "Two-pixel edges for emphasis: a chosen card, a focus ring."
    }
  },
  "typography": {
    "label-sm": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Geist, Geist Fallback, system-ui, sans-serif",
        "fontSize": "12px",
        "fontWeight": 500,
        "lineHeight": 1.4,
        "letterSpacing": "0px"
      },
      "$description": "Label SM: labels on controls and short UI text (buttons, chips, tabs, menu headings). Geist Medium, sentence case. Code and keys use Code SM and Code MD."
    }
  }
}
```

## Purpose

Shows the people on a project, a task or a thread in little room: a few overlapping avatars and a count of the rest, such as "+3". It says who is involved at a glance; the full list lives elsewhere.

## Anatomy

- The block, a list of people in a row as wide as its content.
- The item part, one person: the avatar component at its extra small size, in a ring of the page's surface color that keeps it apart from the face it overlaps. Each face sits over the one before it.
- The more part (optional), the count of the people not drawn, as a small gray pill in the same ring.

## When to use

- On a card, a row or a header, to show who works on something or who took part.
- Where three to five faces are enough and the names are one step away.

## When not to use

- For one person. Use an [avatar with name](avatar-with-name.md).
- When the reader needs every name. List the people instead.
- As a button. The group takes no action; a page that opens the full list puts a separate button or link beside it.

## Behavior

The group draws the first people it is given, three by default, then the count of the rest. With no one left over, there is no count. A picture that fails to load gives way to that person's initials, as the avatar's does. Nothing moves and nothing takes focus.

## Accessibility

### What it does for you

- The group is a list named by how many people it holds, "8 people" by default, or by a name the page gives, such as "Assigned to 8 people".
- Each avatar is named by the person's name. The count is read as words, "and 3 more", not "+3".
- In high contrast mode the rings take the page's background color and the count an edge in the text color.

### What you must do

- Give the group a name that says who the people are when "8 people" is not enough, such as "Assigned to 8 people".
- Give the words the group says by itself, such as the count of the rest read aloud, in the page's own language. They keep their English unless the page gives its own.
- Put a separate button or link beside the group when a page opens the full list. The group itself takes no action.

### How to test

- With a screen reader, the group is read as a list with its name, each person by name, then the count of the rest as "and 3 more".
- Tab past it: the group takes no focus.
- In a forced-color mode, the rings and the count stay visible.
- With text at 200% and the page 320 pixels wide, the count stays whole beside the avatars.

## Usage rules

### Do

- Show three to five faces, and count the rest.
- Name the group by what the people do there, with how many they are.

### Don't

- Squeeze in more faces than fit; they stop being faces.
- Rely on the faces alone: give the full list one step away.
