Components
Avatar stack
Avatar stack stacks a collection of avatar elements
Avatar stack is under development. If you have feedback or suggestions, please report them on Github or in Slack.
Unable to parse html
const Preview = () => ( <EXPERIMENTAL_AvatarStack> <Avatar aria-label='cat'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label='briefcase'> <BriefcaseIcon /> </Avatar> <Avatar aria-label='Søren Magnussen'>sm</Avatar> <Avatar aria-label='Mark Downright'>md</Avatar> <Avatar aria-label='Ola Nordman'>on</Avatar> </EXPERIMENTAL_AvatarStack> ); render(<Preview />)
Use avatar stack when
- A group of people or entities should be displayed together, but space is limited.
- You need to signal that multiple people are involved, without showing everyone at full size.
Avoid avatar stack when
- There is only ever a single avatar to display.
- Each person or entity must be clearly identifiable by name or role at the same time.
Examples
Customization
Avatar stack is designed to be flexible enough to cover many different needs and use cases.
Unable to parse html
const Playground = () => { const [expandable, setExpandable] = useState<undefined | true>(undefined); const [square, setSquare] = useState(false); const [size, setSize] = useState(64); const [overlap, setOverlap] = useState(50); const [gap, setGap] = useState(2); const labelStyle = { display: 'flex', flexDirection: 'column', gap: 'var(--ds-size-2)', accentColor: 'var(--ds-color-base-default)', } as const; return ( <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--ds-size-8)', minHeight: '370px', }} > <fieldset style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 320px), 1fr))', gap: 'var(--ds-size-4)', }} > <div style={{ display: 'flex', gap: 'var(--ds-size-3)', alignItems: 'center', }} > <Checkbox label='Expandable' checked={expandable !== undefined} onChange={() => setExpandable((prev) => (prev ? undefined : true))} /> <Checkbox label='square' checked={square} onChange={() => setSquare((prev) => !prev)} /> </div> <Label style={labelStyle}> avatarSize {`${size}px`} <input min='24' max='150' step='0.1' type='range' value={size} onChange={(e) => setSize(Number((e.target as HTMLInputElement).value)) } /> </Label> <Label style={labelStyle}> Overlap {`${overlap}`} <input min='-10' max='100' step='1' type='range' value={overlap} onChange={(e) => setOverlap(Number((e.target as HTMLInputElement).value)) } /> </Label> <Label style={labelStyle}> Gap {`${gap}px`} <input min='0' max='15' step='1' type='range' value={gap} onChange={(e) => setGap(Number((e.target as HTMLInputElement).value)) } /> </Label> </fieldset> <EXPERIMENTAL_AvatarStack overlap={overlap} data-suffix={`+10`} gap={`${gap}px`} avatarSize={`${size}px`} expandable={expandable} > <Avatar aria-label='' variant={square ? 'square' : 'circle'}> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label='' variant={square ? 'square' : 'circle'}> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label='' variant={square ? 'square' : 'circle'}> md </Avatar> <Avatar aria-label='' variant={square ? 'square' : 'circle'}> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label='' variant={square ? 'square' : 'circle'}> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </div> ); }; render(<Playground />)
Variants
Avatar stack supports both round and square variants, but only one variant per stack.
Unable to parse html
const ShapeVariants = () => ( <EXPERIMENTAL_AvatarStack aria-label='example of square avatars' overlap={40} gap='4px' expandable > <Avatar variant='square' aria-label='variant square' /> <Avatar variant='square' aria-label='Ola Nordmann'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar variant='square' aria-label='Ola Nordmann'> <img src='/img/component-docs/cats/cat2.webp' alt='' /> </Avatar> <Avatar variant='square' aria-label='Ola Nordmann'> <img src='/img/component-docs/cats/cat3.webp' alt='' /> </Avatar> <Avatar variant='square' aria-label='Ola Nordmann'> <img src='/img/component-docs/cats/cat4.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> ); render(<ShapeVariants />)
Indicating avatars not shown
When there are more avatars than can be displayed in the stack, there are two different ways to indicate this.
Unable to parse html
const AdditionalAvatars = () => ( <> <EXPERIMENTAL_AvatarStack overlap={30}> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <BriefcaseIcon /> </Avatar> <Avatar aria-label='' initials='sm' /> <Avatar data-color='neutral' aria-label='' style={{ '--dsc-avatar-font-size': '1.1rem' } as React.CSSProperties} > +14 </Avatar> </EXPERIMENTAL_AvatarStack> <EXPERIMENTAL_AvatarStack suffix={'+14'}> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <BriefcaseIcon /> </Avatar> <Avatar aria-label='' initials='sm' /> <Avatar aria-label='' initials='on' /> </EXPERIMENTAL_AvatarStack> </> ); render(<AdditionalAvatars />)
Tooltips and links
Avatars in avatar stack can have tooltips and be links, but be aware of accessibility considerations.
Unable to parse html
const WithTooltipAndLink = () => ( <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--ds-size-4)' }}> <fieldset> <legend>Link + Tooltip</legend> <EXPERIMENTAL_AvatarStack overlap={20} aria-label='contributors'> <Tooltip content='Ola Katt'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Kari Katt'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Katt 2'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Børge Katt'> <Avatar aria-label='' asChild> <a href='#'>BK</a> </Avatar> </Tooltip> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>Link + Tooltip expandable</legend> <EXPERIMENTAL_AvatarStack overlap={50} expandable='fixed' aria-label='contributors' > <Tooltip content='Ola Katt'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Kari Katt'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Katt 2'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Børge Katt'> <Avatar aria-label='' asChild> <a href='#'>BK</a> </Avatar> </Tooltip> </EXPERIMENTAL_AvatarStack> </fieldset> </div> ); render(<WithTooltipAndLink />)
Guidelines
Avatar stack should be used with caution, as it can be challenging for users to identify individual avatars in a tightly packed stack. Ensure that the use of avatar stack makes sense in the context of the user experience and does not compromise accessibility or usability.
Text
Remember to provide context to screen readers about what the stack represents, for example "Meeting participants" or "Team members".
Edit this page on github.com (opens in a new tab)