<DropdownMenu> <DropdownMenu.Trigger> {(attributes) => <Button attributes={attributes}>Edit</Button>} </DropdownMenu.Trigger> <DropdownMenu.Content> <DropdownMenu.Section> <DropdownMenu.Item endSlot="NL" selected={true}>Dutch</DropdownMenu.Item> <DropdownMenu.Item endSlot="⌘C">Copy</DropdownMenu.Item> <DropdownMenu.Item endSlot="⌘V">Paste</DropdownMenu.Item> </DropdownMenu.Section> <DropdownMenu.Section> <DropdownMenu.Item endSlot="⌘Z">Undo</DropdownMenu.Item> <DropdownMenu.Item endSlot="⌘Y">Redo</DropdownMenu.Item> </DropdownMenu.Section> </DropdownMenu.Content> </DropdownMenu>
DropdownMenu exposes multiple compound components that you can use to achieve any menu composition you need. They are all 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 serves as the root wrapper for the component.
Both components work similarly to how the Popover components work but provide additional features compared to the default Popover and MenuItem implementations.
DropdownMenu supports most of the properties Popover does, allowing you to use its event handlers or position it differently. It will automatically try to fit into the viewport, using the position you pass as a default. If you want to use that position even when the DropdownMenu content doesn't fit into the viewport, use the forcePosition 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 using the 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 focus trapping for 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 the DropdownMenu content width with its trigger. This is helpful when using a 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 mount and use its internal state afterward.
If you pass the active flag, the controlled mode will be activated, and you will need to manage the component's state manually. This means you must control the state using onOpen and onClose handlers, allowing you to add custom logic before updating the state.