Dropdown
See React Bootstrap/Dropdowns for full documentation and props.
Dropdowns in react-bootstrap provide some level of accessibility but in most cases roles or ids will need to be specifically associated with the menu elements themselves.
Dropdowns can be created with a Dropdown.Toggle component or a DropdownButton component.
<div data-testid="pw-dropdown"> <Dropdown> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </Dropdown.Menu> </Dropdown> </div>
With headers and dividers
<div data-testid="pw-dropdown-header"> <Dropdown.Menu show className="position-relative"> <Dropdown.Header>Fruit</Dropdown.Header> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> <Dropdown.Divider /> <Dropdown.Header>Vegetables</Dropdown.Header> <Dropdown.Item>Asparagus</Dropdown.Item> <Dropdown.Item>Broccoli</Dropdown.Item> <Dropdown.Item>Carrot</Dropdown.Item> </Dropdown.Menu> </div>
With multiple columns
Columns can be created with layout options (flex, grid, etc.).
<Dropdown> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu role="menu"> <div className="d-flex align-items-stretch"> <div> <Dropdown.Header>Fruit</Dropdown.Header> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </div> <div className="vr" /> <div> <Dropdown.Header>Vegetables</Dropdown.Header> <Dropdown.Item>Asparagus</Dropdown.Item> <Dropdown.Item>Broccoli</Dropdown.Item> <Dropdown.Item>Carrot</Dropdown.Item> </div> </div> </Dropdown.Menu> </Dropdown>
With non-interactive items
The Dropdown.ItemText component can be used to create non-interactive items.
<Dropdown> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> <Dropdown.ItemText>There are no more fruit to see here.</Dropdown.ItemText> </Dropdown.Menu> </Dropdown>
With form inputs
Dropdown.Items are anchor tags by default, so it's important to use Dropdown.ItemText when putting inputs inside them to make sure clicking it doesn't append a # to the end of the page URL and scroll to the top of the page.
function Example() { const [show, setShow] = useState(false); return ( <Dropdown show={show} onToggle={setShow}> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu> <Dropdown.ItemText> <Radio label="Radio" onChange={() => setShow(false)} /> </Dropdown.ItemText> <Dropdown.ItemText> <Checkbox label="Checkbox" onChange={() => setShow(false)} /> </Dropdown.ItemText> <Dropdown.ItemText> <Switch label="Switch" onChange={() => setShow(false)} /> </Dropdown.ItemText> </Dropdown.Menu> </Dropdown> ); }
With icons, links, and helpers
<div data-testid="pw-dropdown-helper"> <Dropdown> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu> <Dropdown.Item> <ListGroup.Item.Header title="Menu Item" /> </Dropdown.Item> <Dropdown.Item> <ListGroup.Item.Header title="Menu Item w/Helper" helper="⌘C" /> </Dropdown.Item> <Dropdown.Item> <ListGroup.Item.Header title="Menu Item w/Helper and Action" helper="⌘C" actions={<a href="#">Link</a>} /> </Dropdown.Item> <Dropdown.Item> <ListGroup.Item.Header title="Menu Item w/Helper, Action, and Icon" helper="⌘C" actions={<a href="#">Link</a>} icon={<span className="icon-chevron-right" />} /> </Dropdown.Item> </Dropdown.Menu> </Dropdown> </div>
With nested items
function NestedItems() { const menu = { header: 'Very Awesome Column', options: [ { label: 'Option 1', value: 'option1', header: 'Awesome Sub-Column 1', options: [ { label: 'Option 1-1', value: 'option1-1', }, { label: 'Option 1-2', value: 'option1-2', }, ], }, { label: 'Option 2', value: 'option2', header: 'Awesome Sub-Column 2', options: [ { label: 'Option 2-1', value: 'option2-1', }, ], }, { label: 'Option 3', value: 'option3', header: 'Awesome Sub-Column 3', options: [ { label: 'Option 3-1', value: 'option3-1', }, { label: 'Option 3-2', value: 'option3-2', }, { label: 'Option 3-3', value: 'option3-3', }, { label: 'Option 4-3', value: 'option4-3', }, ], }, { label: 'Option 4', value: 'option4', }, ], }; const [activeOption, setActiveOption] = useState(null); const activeColumn = menu.options.find((column) => column.value === activeOption); return ( <Dropdown onToggle={() => setActiveOption(null)}> <Dropdown.Toggle>Nested Dropdown</Dropdown.Toggle> <Dropdown.Menu> <div className="d-flex align-items-stretch"> <div> <Dropdown.Header>{menu.header}</Dropdown.Header> {menu.options.map((column, index) => ( <Dropdown.Item key={index} active={activeOption === column.value} onClick={(e) => { e.stopPropagation(); setActiveOption(column.value); }} > <ListGroup.Item.Header title={column.label} icon={<span className="icon-chevron-right" />} /> </Dropdown.Item> ))} </div> {activeColumn && activeColumn.options && ( <> <div className="vr"></div> <div> <Dropdown.Header>{activeColumn.header}</Dropdown.Header> {activeColumn.options.map((option, index) => ( <Dropdown.Item key={index}>{option.label}</Dropdown.Item> ))} </div> </> )} </div> </Dropdown.Menu> </Dropdown> ); }
Split Dropdowns
<Dropdown as={ButtonGroup}> <Button variant="primary">Split Button</Button> <Dropdown.Toggle split variant="primary" /> <Dropdown.Menu> <Dropdown.Item onClick={() => console.log('foo')}>Action</Dropdown.Item> <Dropdown.Item onClick={() => console.log('foo')}>Another action</Dropdown.Item> <Dropdown.Item onClick={() => console.log('foo')}>Something else</Dropdown.Item> </Dropdown.Menu> </Dropdown>
Size variants
The Dropdown.Menu component can be sized with the size
prop.
<div className="d-flex gap-3"> <Dropdown> <Dropdown.Toggle>Small</Dropdown.Toggle> <Dropdown.Menu role="menu" size="sm"> <Dropdown.Header>Fruits and Melons</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Apple" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Banana" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Divider /> <Dropdown.Header>Berries</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Strawberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Raspberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown> <Dropdown> <Dropdown.Toggle>Medium</Dropdown.Toggle> <Dropdown.Menu role="menu" size="md"> <Dropdown.Header>Fruits and Melons</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Apple" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Banana" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Divider /> <Dropdown.Header>Berries</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Strawberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Raspberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown> <Dropdown> <Dropdown.Toggle>Large</Dropdown.Toggle> <Dropdown.Menu role="menu" size="lg"> <Dropdown.Header>Fruits and Melons</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Apple" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Banana" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Divider /> <Dropdown.Header>Berries</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Strawberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Raspberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown> <Dropdown> <Dropdown.Toggle>Extra Large</Dropdown.Toggle> <Dropdown.Menu role="menu" size="xl"> <Dropdown.Header>Fruits and Melons</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Apple" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Banana" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Divider /> <Dropdown.Header>Berries</Dropdown.Header> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Strawberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Raspberry" icon={<span className="icon-chevron-right" />} /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown> </div>
With ListGroupItem
It is possible to use the ListGroup.Item.Template, Header, and Body components to create more complex dropdowns with headers, descriptions, icons, and other details. See ListGroup for more options.
<Dropdown> <Dropdown.Toggle>Dropdown</Dropdown.Toggle> <Dropdown.Menu role="menu"> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Apple" helper="🍎" />} body={ <ListGroup.Item.Body description="An apple is a round, edible fruit that typically grows on trees." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Banana" helper="🍌" />} body={ <ListGroup.Item.Body description="A banana is an elongated, curved fruit with a thick, usually yellow peel that encases soft, sweet flesh. " /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Cantaloupe" helper="🍈" />} body={ <ListGroup.Item.Body description="Cantaloupe is a type of muskmelon with sweet, orange flesh and a rough, netted rind, often round or oblong in shape." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Watermelon" helper="🍉" />} body={ <ListGroup.Item.Body description="A watermelon is a large, round or oblong fruit with a hard, green rind, typically striped or mottled." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Strawberry" helper="🍓" />} body={ <ListGroup.Item.Body description="A strawberry is a bright red, heart-shaped fruit with a distinctive aroma and sweet-tart flavor." /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown>
Other examples
<Dropdown> <Dropdown.Toggle>Dropdown</Dropdown.Toggle> <Dropdown.Menu role="menu"> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Title" helper="Helper" icon="Icon" actions={<a href="#">Link</a>} /> } body={ <ListGroup.Item.Body description="Description" footer="Footer" alerts={<Alert variant="secondary">Alerts</Alert>} actions={ <div className="d-flex gap-2"> <Button variant="outline-primary" size="xs"> Action 1 </Button> <Button variant="outline-secondary" size="xs"> Action 2 </Button> </div> } /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Title" helper="Helper" icon="Icon" actions={<a href="#">Link</a>} /> } body={ <ListGroup.Item.Body description="Description" footer="Footer" alerts={<Alert variant="secondary">Alerts</Alert>} actions={ <div className="d-flex gap-2"> <a href="#">Link</a> <a href="#">Link</a> </div> } /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown>
As a checklist
<Dropdown> <Dropdown.Toggle>Dropdown</Dropdown.Toggle> <Dropdown.Menu role="menu"> <Dropdown.Item as="div" active> <ListGroup.Item.Template header={ <ListGroup.Item.Header title={ <> Apple{' '} <Badge variant="primary" className="ms-2"> Rated Best </Badge> </> } helper="🍎" actions={ <IconButton variant="outline-secondary" size="xs" iconClassName="icon-thumbs-up" onClick={(e) => { e.stopPropagation(); console.log('Apple action clicked'); }} /> } icon={<span className="icon-check" />} /> } body={ <ListGroup.Item.Body description="An apple is a round, edible fruit that typically grows on trees." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Banana" helper="🍌" />} body={ <ListGroup.Item.Body description="A banana is an elongated, curved fruit with a thick, usually yellow peel that encases soft, sweet flesh. " /> } /> </Dropdown.Item> <Dropdown.Item as="div" active> <ListGroup.Item.Template header={ <ListGroup.Item.Header title="Cantaloupe" helper="🍈" actions={ <IconButton variant="outline-secondary" size="xs" iconClassName="icon-thumbs-up" onClick={(e) => { e.stopPropagation(); console.log('Cantaloupe action clicked'); }} /> } icon={<span className="icon-check" />} /> } body={ <ListGroup.Item.Body description="Cantaloupe is a type of muskmelon with sweet, orange flesh and a rough, netted rind, often round or oblong in shape." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Watermelon" helper="🍉" />} body={ <ListGroup.Item.Body description="A watermelon is a large, round or oblong fruit with a hard, green rind, typically striped or mottled." /> } /> </Dropdown.Item> <Dropdown.Item as="div"> <ListGroup.Item.Template header={<ListGroup.Item.Header title="Strawberry" helper="🍓" />} body={ <ListGroup.Item.Body description="A strawberry is a bright red, heart-shaped fruit with a distinctive aroma and sweet-tart flavor." /> } /> </Dropdown.Item> </Dropdown.Menu> </Dropdown>
Using IconButton
<div className="d-flex gap-3"> <Dropdown> <Dropdown.Toggle as={IconButton} iconClassName="icon-settings-01" aria-label="Toggle" /> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </Dropdown.Menu> </Dropdown> <Dropdown> <Dropdown.Toggle variant="link" as={IconButton} iconClassName="icon-settings-01" aria-label="Toggle" /> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </Dropdown.Menu> </Dropdown> </div>
Hiding the chevron
To hide the chevron icon in the dropdown toggle, use the hideChevron
prop.
<div className="d-flex gap-3"> <Dropdown hideChevron> <Dropdown.Toggle as={IconButton} iconClassName="icon-settings-01" aria-label="Toggle" /> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </Dropdown.Menu> </Dropdown> <Dropdown hideChevron> <Dropdown.Toggle variant="link" as={IconButton} iconClassName="icon-settings-01" aria-label="Toggle" /> <Dropdown.Menu> <Dropdown.Item>Apple</Dropdown.Item> <Dropdown.Item>Banana</Dropdown.Item> <Dropdown.Item>Cantaloupe</Dropdown.Item> </Dropdown.Menu> </Dropdown> </div>
Large lists of items
function Example() { const [activeItemId, setActiveItemId] = useState(null); return ( <Dropdown> <Dropdown.Toggle>Toggle</Dropdown.Toggle> <Dropdown.Menu className="overflow-auto" style={{ maxHeight: '300px' }}> {Array.from({ length: 100 }, (_, i) => { const itemId = `item-${i + 1}`; return ( <Dropdown.Item active={activeItemId === itemId} id={itemId} onClick={() => setActiveItemId(itemId)} key={i} > Item {i + 1} </Dropdown.Item> ); })} </Dropdown.Menu> </Dropdown> ); }
Analytics
The DropdownItem component is trackable through Kyber Analytics. This is the default analytics config.
export default {
value: 'DropdownItem',
actions: {
onClick: { type: 'DROPDOWNITEM_CLICK', payload: 'Click' },
},
};
Props
Dropdown
DropdownItem
DropdownItemContent
🛑 We recommend using ListGroup.Item.Template, ListGroup.Item.Header, and ListGroup.Item.Body to create more complex dropdown items. These components provide more customization and better fit for the Design System.
MultiLineDropdownItem
The MultiLineDropdownItem component is trackable through Kyber Analytics. This is the default analytics config.
export default {
value: 'MultiLineDropdownItem',
actions: {
onClick: { type: 'DROPDOWNITEM_CLICK', payload: 'Click' },
},
};