Klarhimmel UI

Avatar group

Stable

People who share something, overlapped, with the rest collapsed into a named +N chip.

npx shadcn add @klarhimmel/avatar-group

When to use

  • Use for

    Members of a team, watchers of a booking, guests in a party.

  • Not for

    One person. Use Avatar. A list people act on. Use a list or Table.

  • Pairs with

    Avatar, Tooltip, Badge.

Preview

MSOLINJE

Six people on the events team.

avatar-group.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { AvatarGroup } from '@/components/klarhimmel/ui/avatar-group';

export default function Example() {
  return (
    <Theme theme="brand">
      <AvatarGroup people={[{ name: 'Maja Sund' }, { name: 'Oskar Lind' }, { name: 'Ida Nord' }]} max={2} />
    </Theme>
  );
}

Install

Import

import { AvatarGroup } from '@/components/klarhimmel/ui/avatar-group';
Lands in
components/klarhimmel/ui/avatar-group.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
Render in
Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.

Examples

  • Sizes

    MSOLIN
    MSOLIN
    MSOLIN
    import { AvatarGroup } from '@/components/klarhimmel/ui/avatar-group';
    
    const team = ['Maja Sund', 'Oskar Lind', 'Ida Nord', 'Jonas Ek', 'Sara Holm'].map((name) => ({ name }));
    
    export default function AvatarGroupSizes() {
      return (
        <div className="flex flex-col gap-4">
          <AvatarGroup people={team} size="xs" max={3} />
          <AvatarGroup people={team} size="sm" max={3} />
          <AvatarGroup people={team} size="md" max={3} />
        </div>
      );
    }
  • Overflow

    MSOL
    Everyone fits: no chip.
    MSOLIN
    The chip is named "5 more", not only drawn.
    MSOL
    With your own group name and chip words.
    import { AvatarGroup } from '@/components/klarhimmel/ui/avatar-group';
    
    const names = ['Maja Sund', 'Oskar Lind', 'Ida Nord', 'Jonas Ek', 'Sara Holm', 'Nils Dal', 'Eva Ström', 'Karin Voss'];
    
    export default function AvatarGroupOverflow() {
      return (
        <div className="flex flex-col gap-5">
          <div className="flex items-center gap-3">
            <AvatarGroup people={names.slice(0, 2).map((name) => ({ name }))} />
            <span className="text-kh-small text-kh-muted">Everyone fits: no chip.</span>
          </div>
          <div className="flex items-center gap-3">
            <AvatarGroup people={names.map((name) => ({ name }))} max={3} />
            <span className="text-kh-small text-kh-muted">The chip is named "5 more", not only drawn.</span>
          </div>
          <div className="flex items-center gap-3">
            <AvatarGroup people={names.map((name) => ({ name }))} max={2} aria-label="Watching this booking" moreLabel={(n) => `${n} others`} />
            <span className="text-kh-small text-kh-muted">With your own group name and chip words.</span>
          </div>
        </div>
      );
    }

API reference

PropTypeDefaultDescription
people{ name: string; src?: string }[]-Required. Names become the accessible names and the initials.
maxnumber4How many show before the +N chip.
size'xs' | 'sm' | 'md''sm'Avatar size.
aria-labelstringthe namesNames the group. The default lists who is in it and the chip.
moreLabel(n: number) => string'N more'The chip's name. Pass it translated.
classNamestring-Extra classes, merged after the component's own.

Accessibility

KeyDoes
TabNot interactive: nothing to focus

The group is named after who is in it, and the +N chip is named "N more", so the overflow is heard as well as seen.

Accessibility