Components
Dropdown
Dropdown is a generic dropdown list. It lays the foundation for building menus and lists.
React
const Preview = () => { return ( <Dropdown.TriggerContext> <Dropdown.Trigger>Dropdown</Dropdown.Trigger> <Dropdown placement='bottom-end'> <Dropdown.Heading>First heading</Dropdown.Heading> <Dropdown.List> <Dropdown.Item> <Dropdown.Button>Button 1.1</Dropdown.Button> </Dropdown.Item> <Dropdown.Item> <Dropdown.Button>Button 1.2</Dropdown.Button> </Dropdown.Item> </Dropdown.List> <Dropdown.Heading>Second heading</Dropdown.Heading> <Dropdown.List> <Dropdown.Item> <Dropdown.Button>Button 2.1</Dropdown.Button> </Dropdown.Item> <Dropdown.Item> <Dropdown.Button>Button 2.2</Dropdown.Button> </Dropdown.Item> </Dropdown.List> </Dropdown> </Dropdown.TriggerContext> ); }; render(<Preview />)
See Popover for props.
Usage
Dropdown uses Popover internally.
React and popovertarget
When you use popover without Dropdown.TriggerContext, you link yourself trigger and popover.
Then popovertarget is used in lowercase, so that all versions of React correctly render the attribute.
When using @digdir/designsystemet-react we extend @types/react-dom to accept this.
Polyfill
Dropdown uses the Popover API (mozilla.org). This API is classified as Baseline:
Newly available (mozilla.org) as of April 2024,
with Firefox as the last browser to add it. In some cases, you may find that users are locked to older browser versions for various reasons, and then it may be appropriate to add a Popover-Polyfill (github.com) to ensure that Dropdown works for everyone.
Examples
Controlled
If you submit open, then you use Dropdown controlled. You can use onClose to get notified when Dropdown wants to close.
React
const ControlledEn = () => { const [open, setOpen] = useState(false); return ( <Dropdown.TriggerContext> <Dropdown.Trigger onClick={() => setOpen(!open)}> Dropdown {open ? <ChevronDownIcon aria-hidden /> : <ChevronUpIcon aria-hidden />} </Dropdown.Trigger> <Dropdown open={open} onClose={() => setOpen(false)}> <Dropdown.List> <Dropdown.Item> <Dropdown.Button onClick={() => setOpen(false)}> Click me to close </Dropdown.Button> </Dropdown.Item> <Dropdown.Item> <Dropdown.Button onClick={() => setOpen(false)}> I close too </Dropdown.Button> </Dropdown.Item> </Dropdown.List> </Dropdown> </Dropdown.TriggerContext> ); }; render(<ControlledEn />)
Without TriggerContext
Dropdown uses the popover API, so you can use Dropdown without Dropdown.Trigger.
You must then add popovertarget={id} to Dropdown, and id to Dropdown.
React
const WithoutTrigger = () => { return ( <> <Button popovertarget='dropdown'>Dropdown</Button> <Dropdown id='dropdown'> <Dropdown.List> <Dropdown.Item> <Dropdown.Button>Item</Dropdown.Button> </Dropdown.Item> </Dropdown.List> </Dropdown> </> ); }; render(<WithoutTrigger />)
HTML
You can use the native popover API directly in HTML. This can be used without JavaScript, if you don't want to polyfill.
Note that the element with popover="manual" uses two classes, ds-popover and ds-dropdown.
You choose whether you want to use popover="manual" or just popover to open the dropdown.
CSS variables and data attributes
| Name | Value |
|---|---|
| --dsc-dropdown-padding | var(--ds-size-3) var(--ds-size-2) |
| --dsc-dropdown-item-padding | var(--ds-size-2) var(--ds-size-4) |
| --dsc-dropdown-item-size | var(--ds-size-12) |
| --dsc-dropdown-background | var(--ds-color-neutral-surface-default) |
| --dsc-dropdown-border-width | var(--ds-border-width-default) |
| --dsc-dropdown-border-style | solid |
| --dsc-dropdown-border-color | var(--ds-color-neutral-border-subtle) |
| --dsc-popover-arrow-size | var(--ds-size-2) |
No relevant data attributes found.
References
We use ul and li tags in the dropdown, the choice is based on these:
- https://www.w3.org/WAI/tutorials/menus/flyout/#flyoutnavkbbtn
- https://www.w3.org/WAI/ARIA/apg/patterns/menu-button