Dropdown menu

A dropdown menu displays a list of actions or options to a user.

Neutral selected states

When the platform-dst-tokens-finesse feature flag is enabled, this component uses the new neutral treatment for selected states.

Motion in Early Access

Motion updates for this component are in Early Access and available behind the platform-dst-motion-uplift-popup feature flag.

Appearance

Default

Use default for the default dropdown menu appearance. The default menu will scroll after its height exceeds the pre-defined amount.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuDefaultExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuDefaultExample;

Density

Configure the density of the dropdown with the spacing prop. By default the spacing is cozy, but you can also apply compact depending on your use case.

import React from 'react'; import DropdownItemCheckbox from '@atlaskit/dropdown-menu/dropdown-item-checkbox'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; import { Inline } from '@atlaskit/primitives/compiled'; export default (): React.JSX.Element => ( <Inline space="space.600"> <DropdownMenu trigger="Compact density" testId="dropdown" spacing="compact" shouldRenderToParent > <DropdownItemGroup title="Modifications"> <DropdownItem>Copy task link</DropdownItem> <DropdownItem>Add flag</DropdownItem> <DropdownItem>Add label</DropdownItem> <DropdownItem>Add parent</DropdownItem> <DropdownItem>Print</DropdownItem> </DropdownItemGroup> <DropdownItemGroup hasSeparator title="Removal"> <DropdownItem>Remove from sprint</DropdownItem> <DropdownItem>Delete</DropdownItem> </DropdownItemGroup> <DropdownItemGroup hasSeparator title="Filters"> <DropdownItemCheckbox id="action">Spaces</DropdownItemCheckbox> <DropdownItemCheckbox id="filter">Issues</DropdownItemCheckbox> </DropdownItemGroup> </DropdownMenu> <DropdownMenu shouldRenderToParent trigger="Cozy density" testId="dropdown"> <DropdownItemGroup title="Modifications"> <DropdownItem>Copy task link</DropdownItem> <DropdownItem>Add flag</DropdownItem> <DropdownItem>Add label</DropdownItem> <DropdownItem>Add parent</DropdownItem> <DropdownItem>Print</DropdownItem> </DropdownItemGroup> <DropdownItemGroup hasSeparator title="Removal"> <DropdownItem>Remove from sprint</DropdownItem> <DropdownItem>Delete</DropdownItem> </DropdownItemGroup> <DropdownItemGroup hasSeparator title="Filters"> <DropdownItemCheckbox id="action-2">Spaces</DropdownItemCheckbox> <DropdownItemCheckbox id="filter-2">Issues</DropdownItemCheckbox> </DropdownItemGroup> </DropdownMenu> </Inline> );

Tall

Use tall to control the height of the menu. The tall menu will not scroll until the height exceeds the height of the viewport.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuTallExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" appearance="tall" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuTallExample;

Custom triggers

There are three recommended ways to customize a trigger.

Using trigger

Set trigger to a custom react component which accepts the provided props.

import React from 'react'; import IconButton from '@atlaskit/button/icon/button'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; import ShowMoreIcon from '@atlaskit/icon/core/show-more-horizontal'; const DropdownMenuCustomTriggerButtonExample = (): React.JSX.Element => { return ( <DropdownMenu<HTMLButtonElement> trigger={({ triggerRef, ...props }) => ( <IconButton {...props} icon={ShowMoreIcon} label="more" ref={triggerRef} /> )} shouldRenderToParent > <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuCustomTriggerButtonExample;

Use the trigger prop and pass in an html element.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuCustomTriggerExample = (): React.JSX.Element => { return ( <DropdownMenu<HTMLButtonElement> trigger={({ triggerRef, isSelected, testId, ...providedProps }) => ( <button type="button" {...providedProps} ref={triggerRef}> &lt;button/&gt; trigger{' '} </button> )} shouldRenderToParent > <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuCustomTriggerExample;

Use the trigger prop and pass in a string.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuDefaultExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuDefaultExample;

Nested dropdown menu

You can nest dropdown menus inside other dropdown menus.

However, be mindful that nested menus quickly become confusing, inaccessible, and difficult to navigate. We recommend limiting nesting to two layers only.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; import ChevronRightIcon from '@atlaskit/icon/core/chevron-right'; const NestedDropdown = () => { return ( <DropdownMenu placement="right-start" shouldRenderToParent trigger={({ triggerRef, ...triggerProps }) => ( <DropdownItem {...triggerProps} ref={triggerRef} elemAfter={<ChevronRightIcon label="" size="small" />} > <span>Nested Menu</span> </DropdownItem> )} > <DropdownItemGroup> <NestedDropdown /> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; const NestedDropdownMenuExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Nested" shouldRenderToParent> <DropdownItemGroup> <NestedDropdown /> <DropdownItem>One of many items</DropdownItem> <DropdownItem>One of many items</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default NestedDropdownMenuExample;

States

Loading

If isLoading is true, a spinner is rendered instead of the dropdown items.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuLoadingExample = (): React.JSX.Element => { return ( <DropdownMenu isLoading trigger="Page actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Loaded action</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuLoadingExample;

Open

Use isOpen to control the open state of the dropdown menu.

import React, { useState } from 'react'; import DropdownItemRadio from '@atlaskit/dropdown-menu/dropdown-item-radio'; import DropdownItemRadioGroup from '@atlaskit/dropdown-menu/dropdown-item-radio-group'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import { type OnOpenChangeArgs } from '@atlaskit/dropdown-menu/types'; const DropdownOpenExample = (): React.JSX.Element => { const [isOpen, setIsOpen] = useState(false); return ( <DropdownMenu isOpen={isOpen} onOpenChange={(attrs: OnOpenChangeArgs) => { setIsOpen(attrs.isOpen); }} trigger="Page actions" shouldRenderToParent > <DropdownItemRadioGroup id="actions"> <DropdownItemRadio id="edit">Edit</DropdownItemRadio> <DropdownItemRadio id="move">Move</DropdownItemRadio> </DropdownItemRadioGroup> </DropdownMenu> ); }; export default DropdownOpenExample;

Positioning

Default placement

By default, the dropdown menu will be placed next to your trigger.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuPositionDefaultExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuPositionDefaultExample;

Placement

Use placement to set the menu placement to the bottom end, for example.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuPositionExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" placement="bottom-end" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuPositionExample;

Should flip

If it doesn't fit in the viewport, use shouldFlip to place to the dropdown menu on the opposite side of its trigger.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuShouldFlipExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldFlip shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuShouldFlipExample;

Z-index

Use zIndex to resolve clashes with other layered components with competing z-index values, such as popup.

import React, { useState } from 'react'; import IconButton from '@atlaskit/button/icon/button'; import { cssMap } from '@atlaskit/css'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; import CommentAddIcon from '@atlaskit/icon/core/comment-add'; import { Popup } from '@atlaskit/popup/popup'; import { Box } from '@atlaskit/primitives/compiled'; import { token } from '@atlaskit/tokens'; const styles = cssMap({ container: { width: '2rem', height: '2rem', paddingBlockStart: token('space.100'), paddingInlineEnd: token('space.100'), paddingBlockEnd: token('space.100'), paddingInlineStart: token('space.100'), }, }); const DropdownMenuZIndex = (): React.JSX.Element => { const [isOpen, setIsOpen] = useState(false); return ( <Popup shouldRenderToParent isOpen={isOpen} onClose={() => setIsOpen(false)} placement="bottom-start" zIndex={600} content={() => ( <Box xcss={styles.container}> <DropdownMenu trigger="Page actions" zIndex={610} testId="dropdown" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> </DropdownItemGroup> </DropdownMenu> </Box> )} trigger={(triggerProps) => ( <IconButton {...triggerProps} isSelected={isOpen} onClick={() => setIsOpen(!isOpen)} value="Add" icon={CommentAddIcon} label="Add" testId="popup--trigger" /> )} /> ); }; export default DropdownMenuZIndex;

Content without portal

By default, the dropdown menu content is rendered inside React.Portal. Use shouldRenderToParent prop to render the content directly after the trigger element.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuWithoutPortalExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuWithoutPortalExample;

Full width dropdown menu

Use shouldFitContainer to fit the dropdown menu width to its parent's width. When set to true, the trigger and dropdown menu elements will be wrapped in a div with position: relative. The dropdown menu will be rendered as a sibling to the trigger element, and will be full width.

import React from 'react'; import Button from '@atlaskit/button/default/button'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuFullWidth = (): React.JSX.Element => { return ( <DropdownMenu<HTMLButtonElement> shouldFitContainer shouldRenderToParent trigger={({ triggerRef, ...triggerProps }) => ( <Button ref={triggerRef} {...triggerProps} shouldFitContainer> Page actions </Button> )} > <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuFullWidth;

Accessibility

Accessible trigger labels

Sometimes multiple instances of a dropdown menu with the same visible label are required. In order to provide more context to assistive technologies, you can specify a unique aria-label for each unique menu.

When providing the aria-label along with a visible label, make sure that the first few words of the aria-label match the visible label. This is to support Voice Input users that use the visible label to interact with controls.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownMenuLabelExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="More" label="More actions" shouldRenderToParent> <DropdownItemGroup> <DropdownItem>Edit</DropdownItem> <DropdownItem>Share</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> <DropdownItem>Delete</DropdownItem> <DropdownItem>Report</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownMenuLabelExample;

Accessible group labels

If multiple dropdown item groups are used, a title should be provided for the user to understand the menu's structure.

import React from 'react'; import DropdownMenu from '@atlaskit/dropdown-menu/dropdown-menu'; import DropdownItem from '@atlaskit/dropdown-menu/dropdown-menu-item'; import DropdownItemGroup from '@atlaskit/dropdown-menu/dropdown-menu-item-group'; const DropdownItemGroupTitleExample = (): React.JSX.Element => { return ( <DropdownMenu trigger="Page actions" shouldRenderToParent> <DropdownItemGroup title="Edit page"> <DropdownItem>Edit</DropdownItem> <DropdownItem>Move</DropdownItem> <DropdownItem>Clone</DropdownItem> </DropdownItemGroup> <DropdownItemGroup title="Tools"> <DropdownItem>Integrations</DropdownItem> <DropdownItem>Permissions</DropdownItem> </DropdownItemGroup> </DropdownMenu> ); }; export default DropdownItemGroupTitleExample;
Was this page helpful?
We use this feedback to improve our documentation.
  • Design system
    • Get started
    • Foundations
    • Components
    • Rovo UI
    • Tools
    • Release phases
    • Contact us
© 2026 AtlassianTrademark, (opens new window)Privacy, (opens new window)License