Components
AvatarStack
AvatarStack stacks a collection of Avatar elements
AvatarStack is under development. If you have feedback or suggestions, please report them on Github or in Slack.
React
Unable to parse html
const Preview = () => ( <EXPERIMENTAL_AvatarStack> <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=''>md</Avatar> <Avatar aria-label='' initials='on' /> </EXPERIMENTAL_AvatarStack> ); render(<Preview />)
- gap
- Description
Adjusts gap-mask between avatars in the stack. Must be a valid css length value (px, em, rem, var(--ds-size-1) etc.)
- Type
string- Default
2px
- avatarSize
- Description
Control the size of the avatars. Must be a valid css length value (px, em, rem, var(--ds-size-12) etc.)
- Type
string- Default
'var(--ds-size-12)'
- overlap
- Description
A number which represents the percentage value of how much avatars should overlap.
- Type
number- Default
50
- suffix
- Description
Text to the right of the avatars to show a number representing additional avatars not shown such as '+5'".
- Type
string
- expandable
- Description
Expand on hover to show full avatars. 'fixed': AvatarStack physical width does not change when avatars are expanded.
- Type
true | "fixed"- Default
undefined
| Name | Type | Default | Description |
|---|---|---|---|
| gap | string | 2px | Adjusts gap-mask between avatars in the stack. Must be a valid css length value (px, em, rem, var(--ds-size-1) etc.) |
| avatarSize | string | 'var(--ds-size-12)' | Control the size of the avatars. Must be a valid css length value (px, em, rem, var(--ds-size-12) etc.) |
| overlap | number | 50 | A number which represents the percentage value of how much avatars should overlap. |
| suffix | string | - | Text to the right of the avatars to show a number representing additional avatars not shown such as '+5'". |
| expandable | true | "fixed" | undefined | Expand on hover to show full avatars. 'fixed': AvatarStack physical width does not change when avatars are expanded. |
Usage
Examples
Customization
AvatarStack is designed to be flexible enough to cover many different needs and use cases.
React
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 />)
Expandable
expandable animates overlap to 0 on hover or focus. Use expandable="fixed" to expand with overflow without changing the physical width.
React
Unable to parse html
const Expandable = () => ( <div style={{ display: 'flex', flexDirection: 'row', gap: 'var(--ds-size-4)', flexWrap: 'wrap', }} > <fieldset> <legend>expandable</legend> <EXPERIMENTAL_AvatarStack expandable> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>expandable="fixed"</legend> <EXPERIMENTAL_AvatarStack expandable='fixed'> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </fieldset> </div> ); render(<Expandable />)
Indicating avatars not shown
AvatarStack does not support wrapping across multiple lines. If there are more avatars than can fit in the stack, you can use suffix to indicate this as text to the right of the stack. This automatically scales with the avatar size.
You can also use an Avatar with +xx as initials or child, but you should override the font size on this avatar with --dsc-avatar-font-size if there is to be room for two-digit or higher numbers.
React
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 />)
Sizes
You cannot use data-size to change the size of avatars in an AvatarStack. Instead, the size is controlled via the avatarSize prop on AvatarStack. This must be specified in a valid CSS length unit (px, em, rem, var(--ds-size-6), etc.).
React
Unable to parse html
const DataSize = () => ( <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--ds-size-8)' }}> <fieldset> <legend>avatarSize='var(--ds-size-8)'</legend> <EXPERIMENTAL_AvatarStack avatarSize={'var(--ds-size-8)'}> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>avatarSize='3em'</legend> <EXPERIMENTAL_AvatarStack avatarSize='3em'> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>avatarSize='clamp(2rem, 1.5rem + 2vw, 4rem)'</legend> <EXPERIMENTAL_AvatarStack avatarSize='clamp(2rem, 1.5rem + 2vw, 4rem)'> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </Avatar> <Avatar aria-label=''> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </Avatar> </EXPERIMENTAL_AvatarStack> </fieldset> </div> ); render(<DataSize />)
Gap
AvatarStack uses CSS mask to create the visible space between avatars. The default is 2px but can be customized with gap
React
Unable to parse html
const Gap = () => ( <div style={{ display: 'flex', flexWrap: 'wrap', gap: 'var(--ds-size-8)' }}> <fieldset> <legend>gap='2px'</legend> <EXPERIMENTAL_AvatarStack avatarSize='3rem' gap='2px'> <Avatar aria-label='' initials='AA' /> <Avatar aria-label='' initials='BB' /> <Avatar aria-label='' initials='CC' /> <Avatar aria-label='' initials='DD' /> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>gap='4px'</legend> <EXPERIMENTAL_AvatarStack avatarSize='3rem' gap='4px'> <Avatar aria-label='' initials='AA' /> <Avatar aria-label='' initials='BB' /> <Avatar aria-label='' initials='CC' /> <Avatar aria-label='' initials='DD' /> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>gap='6px'</legend> <EXPERIMENTAL_AvatarStack avatarSize='3rem' gap='6px'> <Avatar aria-label='' initials='AA' /> <Avatar aria-label='' initials='BB' /> <Avatar aria-label='' initials='CC' /> <Avatar aria-label='' initials='DD' /> </EXPERIMENTAL_AvatarStack> </fieldset> </div> ); render(<Gap />)
Links and Tooltips
Avatars in AvatarStack can have tooltips and be links, but be aware of accessibility considerations. Use asChild to make an Avatar a link.
React
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 Nordmann'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Kari Nordmann'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Person 2'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Person 3'> <Avatar aria-label='' asChild> <a href='#'>BR</a> </Avatar> </Tooltip> </EXPERIMENTAL_AvatarStack> </fieldset> <fieldset> <legend>Link + Tooltip expandable</legend> <EXPERIMENTAL_AvatarStack overlap={50} expandable='fixed' aria-label='contributors' > <Tooltip content='Ola Nordmann'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Kari Nordmann'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat1.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Person 2'> <Avatar aria-label='' asChild> <a href='#'> <img src='/img/component-docs/cats/cat6.webp' alt='' /> </a> </Avatar> </Tooltip> <Tooltip content='Person 3'> <Avatar aria-label='' asChild> <a href='#'>BR</a> </Avatar> </Tooltip> </EXPERIMENTAL_AvatarStack> </fieldset> </div> ); render(<WithTooltipAndLink />)
HTML
To create an AvatarStack in plain HTML, use the ds-avatar-stack class on a <figure>. Inside this, place elements with the ds-avatar class. Note that if you want to use data-expandable="fixed", the number of avatars must be specified via --dsc-avatar-count: <number> to correctly calculate the fixed width. Use data-suffix to add a text indicator for hidden avatars.
To override the default gap/size/overlap, use these CSS variables:
CSS variables and data attributes
| Name | Value |
|---|---|
| --dsc-avatar-stack-size | var(--ds-size-12) |
| --dsc-avatar-stack-gap | 2px |
| --dsc-avatar-stack-overlap | 50 |
| --dsc-avatar-count | initial |
| --dsc-avatar-size | var(--dsc-avatar-stack-size) |
| --dsc-avatar-font-size | var(--_font-size) |
| Name | Value |
|---|---|
| data-expandable | fixed |
| data-suffix | |
| data-variant | square |