Dropdown MenuupdateUPDATE

Displays a menu to the user, such as a set of actions or functions, triggered by a button.

The DropdownMenu component is composed of several parts, each with their own props.

The root element is the parent component that holds the dropdown menu. Using the autocomplete prop, you can enable autocomplete functionality. Built on top of Ariakit MenuProvider

PropTypeDefault
autocomplete
boolean
-
autocompleteMode
"auto" | "manual"
"auto"
searchValue
string
-
defaultSearchValue
string
-
onSearch
(value: string) => void
-
placement
"top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end" | "right" | "right-start" | "right-end"
"bottom-start""
focusLoop
boolean
true

The button that triggers the dropdown menu. Built on top of Ariakit MenuButton

PropTypeDefault
asChild
boolean
-

TriggerItem is a helper component that renders a DropdownMenu.Trigger as a DropdownMenu.MenuItem.

Accepts all DropdownMenu.Item props. The component is helpful to match styles for sub menu trigger. Use DropdownMenu.Trigger if you want more control.

The container that holds the dropdown menu items. Built on top of Ariakit Menu

PropTypeDefault
searchPlaceholder
string
"Search..."
gutter
number
4
shift
number
0
asChild
boolean
-

Individual clickable options within the dropdown menu. Built on top of Ariakit MenuItem.

Renders as an Ariakit ComboboxItem when used in an autocomplete dropdown. By default, the item's children is used for matching and selection, which can be overriden by passing a value prop.

PropTypeDefault
leadingIcon
ReactNode
-
trailingIcon
ReactNode
-
disabled
boolean
-
value
string
-
className
string
-
asChild
boolean
-

A way to group related menu items together. Built on top of Ariakit MenuGroup

PropTypeDefault
className
string
-
asChild
boolean
-

Renders a label in a menu group. This component should be wrapped with DropdownMenu.Group so the aria-labelledby is correctly set on the group element. Built on top of Ariakit MenuGroupLabel

PropTypeDefault
className
string
-
asChild
boolean
-

Visual divider between menu items or groups. Built on top of Ariakit MenuSeparator

PropTypeDefault
className
string
-
asChild
boolean
-

Placeholder content when there are no menu items to display.

PropTypeDefault
children
ReactNode
-
className
string
-

Examples

Basic Usage

A simple dropdown menu with basic functionality.

<DropdownMenu>
  <DropdownMenu.Trigger asChild>
    <Button color="neutral">Open Menu</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item>Profile</DropdownMenu.Item>
    <DropdownMenu.Item>Settings</DropdownMenu.Item>
    <DropdownMenu.Separator />
    <DropdownMenu.Item>Logout</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

With Icons

You can add icons to the dropdown items. Supports both leading and trailing icons.

<DropdownMenu>
  <DropdownMenu.Trigger asChild>
    <Button color="neutral">Actions</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item leadingIcon={<>📝</>}>Edit</DropdownMenu.Item>
    <DropdownMenu.Item leadingIcon={<>📋</>} trailingIcon={<>⌘C</>}>
      Copy
    </DropdownMenu.Item>
    <DropdownMenu.Separator />
    <DropdownMenu.Item leadingIcon={<>🗑️</>}>Delete</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

With Groups and Labels

Organize related menu items into sections with descriptive headers.

<DropdownMenu>
  <DropdownMenu.Trigger asChild>
    <Button color="neutral">More</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Label>Actions</DropdownMenu.Label>
    <DropdownMenu.Group>
      <DropdownMenu.Item>New File</DropdownMenu.Item>
      <DropdownMenu.Item>New Folder</DropdownMenu.Item>
    </DropdownMenu.Group>
    <DropdownMenu.Separator />
    <DropdownMenu.Label>Sort By</DropdownMenu.Label>
    <DropdownMenu.Group>
      <DropdownMenu.Item>Name</DropdownMenu.Item>
      <DropdownMenu.Item>Date</DropdownMenu.Item>
    </DropdownMenu.Group>
  </DropdownMenu.Content>
</DropdownMenu>

Autocomplete

To enable autocomplete, pass the autocomplete prop to the Dropdown root element. Each menu instance will manage its own autocomplete behavior.

By default, only the top-level menu items are filtered. For more advanced control, set autocompleteMode="manual" and implement your own custom filtering logic.

<DropdownMenu autocomplete>
  <DropdownMenu.Trigger asChild>
    <Button color="neutral">Default Autocomplete</Button>
  </DropdownMenu.Trigger>
  <DropdownMenu.Content searchPlaceholder="Search">
    <DropdownMenu.Group>
      <DropdownMenu.Label>Heading</DropdownMenu.Label>
      <DropdownMenu.Item>Assign member...</DropdownMenu.Item>
      <DropdownMenu.Item>Subscribe...</DropdownMenu.Item>
      <DropdownMenu.Item>Rename...</DropdownMenu.Item>
    </DropdownMenu.Group>
    <DropdownMenu.Separator />
    <DropdownMenu.Label>Actions</DropdownMenu.Label>
    <DropdownMenu autocomplete>
      <DropdownMenu.TriggerItem>Export</DropdownMenu.TriggerItem>
      <DropdownMenu.Content>
        <DropdownMenu.Item>All (.zip)</DropdownMenu.Item>
        <DropdownMenu>
          <DropdownMenu.TriggerItem>CSV</DropdownMenu.TriggerItem>
          <DropdownMenu.Content>
            <DropdownMenu.Item>All</DropdownMenu.Item>
            <DropdownMenu.Item>3 Months</DropdownMenu.Item>
            <DropdownMenu.Item>6 Months</DropdownMenu.Item>
          </DropdownMenu.Content>
        </DropdownMenu>
        <DropdownMenu>
          <DropdownMenu.TriggerItem>PDF</DropdownMenu.TriggerItem>
          <DropdownMenu.Content>
            <DropdownMenu.Item>All</DropdownMenu.Item>
            <DropdownMenu.Item>3 Months</DropdownMenu.Item>
            <DropdownMenu.Item>6 Months</DropdownMenu.Item>
          </DropdownMenu.Content>
        </DropdownMenu>
      </DropdownMenu.Content>
    </DropdownMenu>
    <DropdownMenu.Item disabled>Copy</DropdownMenu.Item>
    <DropdownMenu.Item
      value="remove"
      trailingIcon={
        <Text size="micro" variant="secondary">
          ⌘⇧D
        </Text>
      }
    >
      Delete...
    </DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

Linear inspired Dropdown

This is a Linear-inspired dropdown component that supports custom filtering and displays nested options. Users can search through all nested items using a single input field.

To closely replicate Linear-style filtering, the filtering logic should include result ranking. Using a utility like match-sorter can help achieve this by sorting filtered results based on relevance.

(function LinearDropdownDemo() {
  const [searchQuery, setSearchQuery] = useState("");
 
  const renderDropdownMenu = (items: DropdownMenuItem[], query: string) => {
    const filteredItems = filterDropdownMenuItems(items, query);
 
    if (searchQuery && filteredItems.length === 0) {
      return <div className="no-results">No results</div>;
    }
 
    return filteredItems.map((item, index) => {
      switch (item.type) {
        case "group":
          return (
            <DropdownMenu.Group key={index}>
              <DropdownMenu.Label>{item.label}</DropdownMenu.Label>
              {item.items && renderDropdownMenu(item.items, query)}
            </DropdownMenu.Group>
          );
        case "separator":
          return <DropdownMenu.Separator key={index} />;
        case "submenu":
          return (
            <DropdownMenu key={index}>
              <DropdownMenu.TriggerItem
                trailingIcon={item.trailingIcon}
                leadingIcon={item.leadingIcon}
              >
                {item.label}
              </DropdownMenu.TriggerItem>
              <DropdownMenu.Content>
                {item.items && renderDropdownMenu(item.items, query)}
              </DropdownMenu.Content>
            </DropdownMenu>
          );
        case "item":
          return (
            <DropdownMenu.Item
              key={index}
              disabled={item.disabled}
              trailingIcon={item.trailingIcon}
              leadingIcon={item.leadingIcon}
            >
              {Array.isArray(item.label)
                ? item.label.map((part, i) => (
                    <Fragment key={i}>
                      {i > 0 && <ChevronRight size={12} />}
                      {part}
                    </Fragment>
                  ))
                : item.label}
            </DropdownMenu.Item>
          );
        default:
          return null;
      }
    });
  };
 
  return (
    <DropdownMenu
      autocomplete
      autocompleteMode="manual"
      onSearch={(value: string) => setSearchQuery(value)}
    >
      <DropdownMenu.Trigger asChild>
        <Button>Actions</Button>
      </DropdownMenu.Trigger>
      <DropdownMenu.Content searchPlaceholder="Search">
        {renderDropdownMenu(dropdownMenuData, searchQuery)}
      </DropdownMenu.Content>
    </DropdownMenu>
  );
})

On this page