Dropdown menu

Import
import { DropdownMenu } from "reshaped";
import type { DropdownMenuProps } from "reshaped";
Related components
Can be controlled and uncontrolled
Automatically traps focus when opened

Automatically fits the menu into the viewport or locks it to the position value you provide

Full keyboard navigation
Supports menu sections
Supports custom width
Supports custom trigger element rendering


DropdownMenu exposes multiple compound components that you can use to achieve any menu composition you need. They all are available through the DropdownMenu component.

<DropdownMenu>
  <DropdownMenu.Trigger>
    {(attributes) => <Button attributes={attributes}>Open</Button>}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item>Action 1</DropdownMenu.Item>
    <DropdownMenu.Item>Action 2</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

DropdownMenu itself here serves as the root wrapper for the component.

  • DropdownMenu.Trigger is a trigger providing all required attributes and handlers for your component, like Button in this example.
  • DropdownMenu.Content is a wrapper for the overlaying content with menu items. Both components work similarly to how the Popover components work but provide additional features for the default Popover and MenuItem implementations.
  • DropdownMenu.Item implementation is based on the MenuItem component. It has className, size and roundedCorners properties predefined and supports all other MenuItem properties to be passed to it.

DropdownMenu supports most of the properties Popover does, which means you can use its event handlers or position it differently. In the same way, you can turn it into a controlled component by using active property.

<DropdownMenu position="top-end" onClose={() => console.log("Closed")}>
  <DropdownMenu.Trigger>
    {(attributes) => <Button attributes={attributes}>Open</Button>}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item>Action 1</DropdownMenu.Item>
    <DropdownMenu.Item>Action 2</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

DropdownMenu supports separating items into sections by using DropdownMenu.Section component.

<DropdownMenu>
  <DropdownMenu.Trigger>
    {(attributes) => <Button attributes={attributes}>Open</Button>}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Section>
      <DropdownMenu.Item>Action 1</DropdownMenu.Item>
      <DropdownMenu.Item>Action 2</DropdownMenu.Item>
    </DropdownMenu.Section>
    <DropdownMenu.Section>
      <DropdownMenu.Item>Action 3</DropdownMenu.Item>
      <DropdownMenu.Item>Action 4</DropdownMenu.Item>
    </DropdownMenu.Section>
  </DropdownMenu.Content>
</DropdownMenu>

You can create one or multiple submenus inside your DropdownMenu using DropdownMenu.SubMenu and DropdownMenu.SubTrigger. It automatically handles the focus trapping for the multiple levels of nesting.

<DropdownMenu>
  <DropdownMenu.Trigger>
    {(attributes) => <Button attributes={attributes}>Open</Button>}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item onClick={() => {}}>Item 1</DropdownMenu.Item>
    <DropdownMenu.SubMenu>
      <DropdownMenu.SubTrigger>Item 2</DropdownMenu.SubTrigger>
      <DropdownMenu.Content>
        <DropdownMenu.Item onClick={() => {}}>SubItem 1</DropdownMenu.Item>
        <DropdownMenu.Item onClick={() => {}}>SubItem 2</DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu.SubMenu>
    <DropdownMenu.Item onClick={() => {}}>Item 3</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

You can either pass a literal width value like 200px or a trigger value to align DropdownMenu content width with its trigger. This is helpful when you're using fullWidth Button component or Select / TextField together with DropdownMenu.

<DropdownMenu width="trigger">
  <DropdownMenu.Trigger>
    {(attributes) => (
      <Select
        name="animal"
        placeholder="Select an animal"
        inputAttributes={attributes}
      />
    )}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item>Turtle</DropdownMenu.Item>
    <DropdownMenu.Item>Cat</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>

If you pass the defaultActive flag to the component, it will open the menu on the component mount and use its internal state afterward.

If you pass the active flag, the controlled mode will turn on, and you will have to change the component's state manually. It means that you have to control the state using onOpen and onClose handlers, and you can add any custom logic before updating the state.

  • It's essential to pass the attributes provided by the DropdownMenu component to your interactive trigger component. That way you will ensure that all the user events and aria attributes are assigned correctly.

  • DropdownMenu manages the navigation and focus when used with the keyboard. After opening the menu, the focus is moved to the first menu item, and next/previous item can be selected with arrow keys. Pressing Tab, Esc, or clicking outside will close the menu and return the focus back to the trigger.

  • DropdownMenu.SubMenu adds additional hotkeys to open them. You can use Right arrow or Enter on the SubTrigger to open the submenu. Then you can use Left arrow or Esc to dismiss it.