---
title: Menu
description: A list of actions in a dropdown, enhanced with keyboard navigation.
links:
  doc: https://base-ui.com/react/components/menu
  anatomy: https://base-ui.com/react/components/menu#anatomy
  api: https://base-ui.com/react/components/menu#api-reference
---

```tsx
"use client";

import { useState } from "react";

import {
  IconBell,
  IconCreditCard,
  IconDeviceDesktop,
  IconDeviceFloppy,
  IconDots,
  IconDownload,
  IconEye,
  IconFile,
  IconFileCode,
  IconFileText,
  IconFolder,
  IconFolderOpen,
  IconFolderSearch,
  IconHelpCircle,
  IconKeyboard,
  IconLanguage,
  IconLayout,
  IconLogout,
  IconMail,
  IconMoon,
  IconPalette,
  IconSettings,
  IconShield,
  IconSun,
  IconUser,
} from "@tabler/icons-react";

import { Button } from "@/components/ui/button";
import {
  Menu,
  MenuCheckboxItem,
  MenuGroup,
  MenuGroupLabel,
  MenuItem,
  MenuPopup,
  MenuRadioGroup,
  MenuRadioItem,
  MenuSeparator,
  MenuShortcut,
  MenuSub,
  MenuSubPopup,
  MenuSubTrigger,
  MenuTrigger,
} from "@/components/ui/menu";

export function MenuDemo() {
  const [notifications, setNotifications] = useState({
    email: true,
    sms: false,
    push: true,
  });
  const [theme, setTheme] = useState("light");

  return (
    <Menu>
      <MenuTrigger render={<Button variant="outline">Menu</Button>} />
      <MenuPopup>
        <MenuGroup>
          <MenuGroupLabel>File</MenuGroupLabel>
          <MenuItem>
            <IconFile />
            New File
            <MenuShortcut>⌘N</MenuShortcut>
          </MenuItem>
          <MenuItem>
            <IconFolder />
            New Folder
            <MenuShortcut>⇧⌘N</MenuShortcut>
          </MenuItem>
          <MenuSub>
            <MenuSubTrigger>
              <IconFolderOpen />
              Open Recent
            </MenuSubTrigger>
            <MenuSubPopup>
              <MenuGroup>
                <MenuGroupLabel>Recent Projects</MenuGroupLabel>
                <MenuItem>
                  <IconFileCode />
                  Project Alpha
                </MenuItem>
                <MenuItem>
                  <IconFileCode />
                  Project Beta
                </MenuItem>
                <MenuSub>
                  <MenuSubTrigger>
                    <IconDots />
                    More Projects
                  </MenuSubTrigger>
                  <MenuSubPopup>
                    <MenuItem>
                      <IconFileCode />
                      Project Gamma
                    </MenuItem>
                    <MenuItem>
                      <IconFileCode />
                      Project Delta
                    </MenuItem>
                  </MenuSubPopup>
                </MenuSub>
              </MenuGroup>
              <MenuSeparator />
              <MenuGroup>
                <MenuItem>
                  <IconFolderSearch />
                  Browse...
                </MenuItem>
              </MenuGroup>
            </MenuSubPopup>
          </MenuSub>
          <MenuSeparator />
          <MenuItem>
            <IconDeviceFloppy />
            Save
            <MenuShortcut>⌘S</MenuShortcut>
          </MenuItem>
          <MenuItem>
            <IconDownload />
            Export
            <MenuShortcut>⇧⌘E</MenuShortcut>
          </MenuItem>
        </MenuGroup>
        <MenuSeparator />
        <MenuGroup>
          <MenuGroupLabel>View</MenuGroupLabel>
          <MenuCheckboxItem>
            <IconLayout />
            Show Sidebar
          </MenuCheckboxItem>
          <MenuCheckboxItem>
            <IconEye />
            Show Status Bar
          </MenuCheckboxItem>
          <MenuSub>
            <MenuSubTrigger>
              <IconPalette />
              Theme
            </MenuSubTrigger>
            <MenuSubPopup>
              <MenuGroup>
                <MenuGroupLabel>Appearance</MenuGroupLabel>
                <MenuRadioGroup value={theme} onValueChange={setTheme}>
                  <MenuRadioItem value="light">
                    <IconSun />
                    Light
                  </MenuRadioItem>
                  <MenuRadioItem value="dark">
                    <IconMoon />
                    Dark
                  </MenuRadioItem>
                  <MenuRadioItem value="system">
                    <IconDeviceDesktop />
                    System
                  </MenuRadioItem>
                </MenuRadioGroup>
              </MenuGroup>
            </MenuSubPopup>
          </MenuSub>
        </MenuGroup>
        <MenuSeparator />
        <MenuGroup>
          <MenuGroupLabel>Account</MenuGroupLabel>
          <MenuItem>
            <IconUser />
            Profile
            <MenuShortcut>⇧⌘P</MenuShortcut>
          </MenuItem>
          <MenuItem disabled>
            <IconCreditCard />
            Billing
          </MenuItem>
          <MenuSub>
            <MenuSubTrigger>
              <IconSettings />
              Settings
            </MenuSubTrigger>
            <MenuSubPopup>
              <MenuGroup>
                <MenuGroupLabel>Preferences</MenuGroupLabel>
                <MenuItem>
                  <IconKeyboard />
                  Keyboard Shortcuts
                </MenuItem>
                <MenuItem>
                  <IconLanguage />
                  Language
                </MenuItem>
                <MenuSub>
                  <MenuSubTrigger>
                    <IconBell />
                    Notifications
                  </MenuSubTrigger>
                  <MenuSubPopup>
                    <MenuGroup>
                      <MenuGroupLabel>Notification Types</MenuGroupLabel>
                      <MenuCheckboxItem
                        variant="switch"
                        checked={notifications.push}
                        onCheckedChange={(checked) =>
                          setNotifications({
                            ...notifications,
                            push: checked === true,
                          })
                        }
                      >
                        <IconBell />
                        Push Notifications
                      </MenuCheckboxItem>
                      <MenuCheckboxItem
                        variant="switch"
                        checked={notifications.email}
                        onCheckedChange={(checked) =>
                          setNotifications({
                            ...notifications,
                            email: checked === true,
                          })
                        }
                      >
                        <IconMail />
                        Email Notifications
                      </MenuCheckboxItem>
                    </MenuGroup>
                  </MenuSubPopup>
                </MenuSub>
              </MenuGroup>
              <MenuSeparator />
              <MenuGroup>
                <MenuItem>
                  <IconShield />
                  Privacy & Security
                </MenuItem>
              </MenuGroup>
            </MenuSubPopup>
          </MenuSub>
        </MenuGroup>
        <MenuSeparator />
        <MenuGroup>
          <MenuItem>
            <IconHelpCircle />
            Help & Support
          </MenuItem>
          <MenuItem>
            <IconFileText />
            Documentation
          </MenuItem>
        </MenuGroup>
        <MenuSeparator />
        <MenuGroup>
          <MenuItem variant="danger">
            <IconLogout />
            Sign Out
            <MenuShortcut>⇧⌘Q</MenuShortcut>
          </MenuItem>
        </MenuGroup>
      </MenuPopup>
    </Menu>
  );
}
```

## Installation

<ComponentSource name="menu" title="components/ui/menu.tsx" />

## Usage

```tsx
import {
  Menu,
  MenuCheckboxItem,
  MenuGroup,
  MenuGroupLabel,
  MenuItem,
  MenuPopup,
  MenuRadioGroup,
  MenuRadioItem,
  MenuSeparator,
  MenuShortcut,
  MenuSub,
  MenuSubPopup,
  MenuSubTrigger,
  MenuTrigger,
} from "@/registry/default/ui/menu";
```

```tsx
<Menu>
  <MenuTrigger>Menu</MenuTrigger>
  <MenuPopup>
    <MenuGroup>
      <MenuGroupLabel>File</MenuGroupLabel>
      <MenuItem>
        New File
        <MenuShortcut>⌘N</MenuShortcut>
      </MenuItem>
      <MenuItem>
        New Folder
        <MenuShortcut>⇧⌘N</MenuShortcut>
      </MenuItem>
      <MenuSub>
        <MenuSubTrigger>Open Recent</MenuSubTrigger>
        <MenuSubPopup>
          <MenuGroup>
            <MenuGroupLabel>Recent Projects</MenuGroupLabel>
            <MenuItem>Project Alpha</MenuItem>
            <MenuItem>Project Beta</MenuItem>
          </MenuGroup>
        </MenuSubPopup>
      </MenuSub>
    </MenuGroup>
    <MenuSeparator />
    <MenuGroup>
      <MenuGroupLabel>View</MenuGroupLabel>
      <MenuSub>
        <MenuSubTrigger>Theme</MenuSubTrigger>
        <MenuSubPopup>
          <MenuGroup>
            <MenuGroupLabel>Appearance</MenuGroupLabel>
            <MenuRadioGroup>
              <MenuRadioItem value="light">Light</MenuRadioItem>
              <MenuRadioItem value="dark">Dark</MenuRadioItem>
              <MenuRadioItem value="system">System</MenuRadioItem>
            </MenuRadioGroup>
          </MenuGroup>
        </MenuSubPopup>
      </MenuSub>
    </MenuGroup>
    <MenuSeparator />
    <MenuGroup>
      <MenuGroupLabel>Account</MenuGroupLabel>
      <MenuItem>Profile</MenuItem>
      <MenuItem>Billing</MenuItem>
      <MenuSub>
        <MenuSubTrigger>Settings</MenuSubTrigger>
        <MenuSeparator />
        <MenuGroup>
          <MenuGroupLabel>Notifications</MenuGroupLabel>
          <MenuCheckboxItem variant="switch">Push Notifications</MenuCheckboxItem>
          <MenuCheckboxItem variant="switch">Email Notifications</MenuCheckboxItem>
        </MenuGroup>
      </MenuSub>
    </MenuGroup>
    <MenuSeparator />
    <MenuGroup>
      <MenuItem variant="danger">
        Sign Out
        <MenuShortcut>⇧⌘Q</MenuShortcut>
      </MenuItem>
    </MenuGroup>
  </MenuPopup>
</Menu>
```

## Examples

### Open on hover

Enable opening the menu when hovering over the trigger by setting the `openOnHover` prop on `MenuTrigger`.

```tsx
import { Button } from "@/components/ui/button";
import { Menu, MenuItem, MenuPopup, MenuTrigger } from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <Menu>
      <MenuTrigger openOnHover render={<Button variant="outline">Hover</Button>} />
      <MenuPopup>
        <MenuItem>New File</MenuItem>
        <MenuItem>New Folder</MenuItem>
        <MenuItem>Open recent</MenuItem>
      </MenuPopup>
    </Menu>
  );
}
```

### With Checkbox

```tsx
import { Button } from "@/components/ui/button";
import { Menu, MenuCheckboxItem, MenuPopup, MenuTrigger } from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <Menu>
      <MenuTrigger render={<Button variant="outline">Settings</Button>} />
      <MenuPopup>
        <MenuCheckboxItem>Sidebar</MenuCheckboxItem>
        <MenuCheckboxItem>Status bar</MenuCheckboxItem>
        <MenuCheckboxItem>Activity bar</MenuCheckboxItem>
      </MenuPopup>
    </Menu>
  );
}
```

### With Radio group

```tsx
import { Button } from "@/components/ui/button";
import {
  Menu,
  MenuPopup,
  MenuRadioGroup,
  MenuRadioItem,
  MenuTrigger,
} from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <Menu>
      <MenuTrigger render={<Button variant="outline" />}>Theme</MenuTrigger>
      <MenuPopup>
        <MenuRadioGroup>
          <MenuRadioItem value="light">Light</MenuRadioItem>
          <MenuRadioItem value="dark">Dark</MenuRadioItem>
          <MenuRadioItem value="system">System</MenuRadioItem>
        </MenuRadioGroup>
      </MenuPopup>
    </Menu>
  );
}
```

### Switch variant & indicator position

Menu checkbox items support a `switch` variant and an `indicatorPosition` prop to position the indicator at the start or end of the item. Default `indicatorPosition` is `end`.

Menu radio items support an `indicatorPosition` prop to position the indicator at the start or end of the item.
Default `indicatorPosition` is `end`.

```tsx
import { Button } from "@/components/ui/button";
import {
  Menu,
  MenuCheckboxItem,
  MenuGroup,
  MenuGroupLabel,
  MenuPopup,
  MenuRadioGroup,
  MenuRadioItem,
  MenuTrigger,
} from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <Menu>
      <MenuTrigger render={<Button variant="outline" />}>Dropdown menu</MenuTrigger>
      <MenuPopup>
        <MenuGroup>
          <MenuGroupLabel>View</MenuGroupLabel>
          <MenuCheckboxItem>Sidebar</MenuCheckboxItem>
          <MenuCheckboxItem>Status bar</MenuCheckboxItem>
          <MenuCheckboxItem>Activity bar</MenuCheckboxItem>
        </MenuGroup>
        <MenuGroup>
          <MenuGroupLabel>Theme</MenuGroupLabel>
          <MenuRadioGroup>
            <MenuRadioItem indicatorPosition="start" value="light">
              Light
            </MenuRadioItem>
            <MenuRadioItem indicatorPosition="start" value="dark">
              Dark
            </MenuRadioItem>
            <MenuRadioItem indicatorPosition="start" value="system">
              System
            </MenuRadioItem>
          </MenuRadioGroup>
        </MenuGroup>
        <MenuGroup>
          <MenuGroupLabel>Notifications</MenuGroupLabel>
          <MenuCheckboxItem variant="switch" indicatorPosition="start">
            Email notifications
          </MenuCheckboxItem>
          <MenuCheckboxItem variant="switch" indicatorPosition="start">
            Push notifications
          </MenuCheckboxItem>
          <MenuCheckboxItem variant="switch" indicatorPosition="start">
            SMS notifications
          </MenuCheckboxItem>
        </MenuGroup>
      </MenuPopup>
    </Menu>
  );
}
```

### Menu popup side and align

To change the side and alignment of the menu popup, use the `positionerProps` prop of `MenuPopup` and pass the desired `side` and `align` values.

```tsx
import { Button } from "@/components/ui/button";
import { Menu, MenuItem, MenuPopup, MenuTrigger } from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <div className="flex flex-col gap-5">
      <div>
        <p className="mb-2">Side</p>
        <div className="flex items-center gap-5">
          <Menu>
            <MenuTrigger render={<Button variant="outline">Top</Button>} />
            <MenuPopup positionerProps={{ side: "top" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
          <Menu>
            <MenuTrigger render={<Button variant="outline">Bottom</Button>} />
            <MenuPopup positionerProps={{ side: "bottom" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
          <Menu>
            <MenuTrigger render={<Button variant="outline">Left</Button>} />
            <MenuPopup positionerProps={{ side: "left" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
          <Menu>
            <MenuTrigger render={<Button variant="outline">Right</Button>} />
            <MenuPopup positionerProps={{ side: "right" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
        </div>
      </div>
      <div>
        <p className="mb-2">Align</p>
        <div className="flex items-center gap-5">
          <Menu>
            <MenuTrigger render={<Button variant="outline">Start</Button>} />
            <MenuPopup positionerProps={{ align: "start" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
          <Menu>
            <MenuTrigger render={<Button variant="outline">Center</Button>} />
            <MenuPopup positionerProps={{ align: "center" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
          <Menu>
            <MenuTrigger render={<Button variant="outline">End</Button>} />
            <MenuPopup positionerProps={{ align: "end" }}>
              <MenuItem>New File</MenuItem>
              <MenuItem>New Folder</MenuItem>
              <MenuItem>Open recent</MenuItem>
            </MenuPopup>
          </Menu>
        </div>
      </div>
    </div>
  );
}
```

### Menu item close on click

By default, menu items close the menu when clicked because for `MenuItem` the default value of the `closeOnClick` prop is `true`.

But for `MenuCheckboxItem` and `MenuRadioItem`, the default value of the `closeOnClick` prop is `false`.
You can change this behavior by setting the `closeOnClick` prop to `true`.

```tsx
import { Button } from "@/components/ui/button";
import {
  Menu,
  MenuCheckboxItem,
  MenuGroup,
  MenuGroupLabel,
  MenuPopup,
  MenuRadioGroup,
  MenuRadioItem,
  MenuTrigger,
} from "@/components/ui/menu";

export function MenuDemo() {
  return (
    <Menu>
      <MenuTrigger render={<Button variant="outline">Settings</Button>} />
      <MenuPopup>
        <MenuGroup>
          <MenuGroupLabel>View</MenuGroupLabel>
          <MenuCheckboxItem closeOnClick>Sidebar</MenuCheckboxItem>
          <MenuCheckboxItem closeOnClick>Status bar</MenuCheckboxItem>
          <MenuCheckboxItem closeOnClick>Activity bar</MenuCheckboxItem>
        </MenuGroup>
        <MenuGroup>
          <MenuGroupLabel>Theme</MenuGroupLabel>
          <MenuRadioGroup>
            <MenuRadioItem closeOnClick value="light">
              Light
            </MenuRadioItem>
            <MenuRadioItem closeOnClick value="dark">
              Dark
            </MenuRadioItem>
            <MenuRadioItem closeOnClick value="system">
              System
            </MenuRadioItem>
          </MenuRadioGroup>
        </MenuGroup>
      </MenuPopup>
    </Menu>
  );
}
```

### Menu with dialog

```tsx
"use client";

import { useState } from "react";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogPopup,
  DialogTitle,
} from "@/components/ui/dialog";
import { Menu, MenuItem, MenuPopup, MenuTrigger } from "@/components/ui/menu";

export function MenuDemo() {
  const [dialogOpen, setDialogOpen] = useState(false);

  return (
    <>
      <Menu>
        <MenuTrigger render={<Button variant="outline" />}>Menu</MenuTrigger>
        <MenuPopup>
          <MenuItem>New File</MenuItem>
          <MenuItem>New Folder</MenuItem>
          <MenuItem onClick={() => setDialogOpen(true)}>Open settings</MenuItem>
        </MenuPopup>
      </Menu>
      <Dialog onOpenChange={setDialogOpen} open={dialogOpen}>
        <DialogPopup>
          <DialogHeader>
            <DialogTitle>Settings</DialogTitle>
            <DialogDescription>Change your preferences</DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <DialogClose render={<Button variant="ghost" />}>Close</DialogClose>
          </DialogFooter>
        </DialogPopup>
      </Dialog>
    </>
  );
}
```

## API Reference

### Menu popup props

<ApiReferenceAccordion
  type={{
    scrollArea: {
      description:
        "Whether to wrap the list in a scroll area. If false, native scrollbar will be shown if the list exceeds the max height.",
      type: "boolean",
      default: `false`,
    },
    positionerProps: {
      description: "Props to pass to the underlying Positioner component.",
      type: `React.ComponentProps<typeof MenuPositioner>`,
    },
  }}
/>

### Menu item props

<ApiReferenceAccordion
  type={{
    variant: {
      description: "The variant of the menu item.",
      type: "'default' | 'danger'",
      default: `'default'`,
    },
  }}
/>

### Menu checkbox item props

<ApiReferenceAccordion
  type={{
    variant: {
      description: "The variant of the checkbox item.",
      type: "'default' | 'switch'",
      default: `'default'`,
    },
    indicatorPosition: {
      description: "The position of the indicator.",
      type: "'start' | 'end'",
      default: `'end'`,
    },
  }}
/>

### Menu radio item props

<ApiReferenceAccordion
  type={{
    indicatorPosition: {
      description: "The position of the indicator.",
      type: "'start' | 'end'",
      default: `'end'`,
    },
  }}
/>
