import { Story, ArgTypes, Canvas, Meta } from '@storybook/blocks'; import Dropdown from '../Dropdown'; import DropdownSkeleton from './Dropdown.Skeleton'; import * as DropdownStories from './Dropdown.stories';
Source code | Usage guidelines | Accessibility
{/* */}
{/* */}
Dropdowns present a list of options from which a user can select one option, or several. A selected option can represent a value in a form, or can be used as an action to filter or sort existing content.
You can place a Dropdown
inline with other content by using the inline
variant
You can use the DropdownSkeleton
component to render a skeleton variant of a
Dropdown
. This is useful to display on initial page load or when data needs to
be fetched from an external API.
When a Dropdown
is near the bottom of a page, you may want to render the menu
to the top of the screen. To do this, specify direction="top"
<Dropdown items={[ { id: 'option-0', text: 'Option 0' }, { id: 'option-1', text: 'Option 1', }, { id: 'option-2', text: 'Option 2' }, ]} itemToString={(item) => (item ? item.text : '')} label="Select an option..." direction="top" id="direction" titleText="Dropdown label" />
<Dropdown direction="top" />
Our Dropdown
component utilizes Downshift
under the hood to help provide complex yet accessible custom dropdown
components. We provide access to the built in Downshift features with this prop.
Use with caution: anything you define here overrides the components' internal handling of that prop. Downshift internals are subject to change, and in some cases they can not be shimmed to shield you from potentially breaking changes.
For more information, checkout the Downshift prop documentation
If you want the Dropdown
to render with a value already selected, but do not
want to fully control the component, you can use initialSelectedItem
.
const items = ['Option 1', 'Option 2', 'Option 3']
<Dropdown initialSelectedItem={items[2]} />
The Dropdown
takes in an items
array and can then be formatted by
itemToElement
and itemToString
. itemToElement
allows you to wrap each
dropdown item in a custom element. The
itemToString
prop can be used with this to provide
the text of the item in the input on selection.
<Dropdown items={[ { id: 'option-0', text: 'Option 0' }, { id: 'option-1', text: 'Option 1' }, { id: 'option-2', text: 'Option 2' }, ]} itemToElement={(item) => item ? ( <span className="test" style={{ color: 'red' }}> {item.text} 🔥 ) : ( '' ) } label="Select an option..." id="item-to-element" titleText="Dropdown label" />
<Dropdown
items={[
{ id: 'option-0', text: 'Option 0' },
{ id: 'option-1', text: 'Option 1' },
{ id: 'option-2', text: 'Option 2' },
]}
itemToElement={(item) =>
item ? (
<span className="test" style={{ color: 'red' }}>
{item.text} 🔥
</span>
) : (
''
)
}
label="Select an option..."
titleText="Dropdown label"
/>
If the items
array is not an array of strings, you'll need to use
itemToString
to grab the text to be used as the Dropdown
item text.
<Dropdown items={[ { id: 'option-0', text: 'Option 0' }, { id: 'option-1', text: 'Option 1' }, { id: 'option-2', text: 'Option 2' }, ]} itemToString={(item) => (item ? item.text : '')} itemToElement={(item) => item ? ( <span className="test" style={{ color: 'red' }}> {item.text} 🔥 ) : ( '' ) } label="Select an option..." id="item-to-element" titleText="Dropdown label" />
<Dropdown
items={[
{ id: 'option-0', text: 'Option 0' },
{ id: 'option-1', text: 'Option 1' },
{ id: 'option-2', text: 'Option 2' },
]}
itemToString={(item) => (item ? item.text : '')}
itemToElement={(item) =>
item ? (
<span className="test" style={{ color: 'red' }}>
{item.text} 🔥
</span>
) : (
''
)
}
label="Select an option..."
id="item-to-element"
titleText="Dropdown label"
/>
This is the data that will be rendered as options for the Dropdown
. If items
is simply an array of strings, no further formatting is required. If items
is
an array of objects, you'll need to pass in an itemToString
function as well.
<Dropdown
items={['Option 0', 'Option 1', 'Option 2']}
/>
<Dropdown
items={[
{ id: 'option-0', text: 'Option 0' },
{ id: 'option-1', text: 'Option 1' },
{ id: 'option-2', text: 'Option 2' },
]}
itemToString={(item) => (item ? item.text : '')}
/>
In certain circumstances, a Dropdown
will exist on a container element with
the same background color. To improve contrast, you can use the light
property
to toggle the light variant of the Dropdown
. light
is now deprecated, we
recommend using the new Layer
component instead.
<Dropdown light>...</Dropdown>
You can pass a selectedItem
to the Dropdown
to set a value on initial load.
Keep in mind, if you set a value the Dropdown
will become a controlled
component and you will need to handle state management.
const [currentItem, setCurrentItem] = useState(items[4]);
...
<Dropdown
items={items}
itemToString={(item) => (item ? item.text : '')}
onChange={({ selectedItem }) => setCurrentItem(selectedItem)}
selectedItem={currentItem}
/>
There are three sizes of Dropdown
available: sm
, lg
(the default), and
xl
.
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
size="sm"
label="Small [sm]"
id="sm"
titleText="Dropdown label"
/>
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
label="Medium [md]"
id="md"
size="md"
titleText="Dropdown label"
/>
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
size="lg"
label="Large [lg]"
id="lg"
titleText="Dropdown label"
/>
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
size="sm"
label="Small [sm]"
titleText="Dropdown label"
/>
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
label="Medium [md]"
size="md"
titleText="Dropdown label"
/>
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
size="lg"
label="Large [lg]"
titleText="Dropdown label"
/>
This is the text that will be used as a label for the Dropdown
<Dropdown titleText="This is the Dropdown label" />
Sometimes you will need to place a Dropdown
inline with other content. To do
that, pass in type="inline"
to the Dropdown
<Dropdown items={['Option 1', 'Option 2', 'Option 3']} label="Inline" type="inline" id="inline" titleText="Dropdown label" />
<Dropdown
items={['Option 1', 'Option 2', 'Option 3']}
label="Inline"
type="inline"
is="inline"
titleText="Dropdown label"
/>
Help us improve this component by providing feedback, asking questions on Slack, or updating this file on GitHub.