Skip to content
Docs

Dropdown Menu

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

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

<DropdownMenu.root id="dropdown-primitive">
  <DropdownMenu.trigger
    id="dropdown-trigger"
    content_id="dropdown-content"
    class="DemoIconButton"
    aria-label="Customise options"
  >
    <svg
      width="15"
      height="15"
      viewBox="0 0 15 15"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
    >
      <path
        d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386 13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5 8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z"
        fill="currentColor"
        fill-rule="evenodd"
        clip-rule="evenodd"
      >
      </path>
    </svg>
  </DropdownMenu.trigger>
  <DropdownMenu.content
    id="dropdown-content"
    class="DemoDropdownMenuContent"
    side_offset={5}
  >
    <DropdownMenu.item
      class="DemoDropdownMenuItem"
      text_value="New Tab"
    >
      New Tab
      <div class="DemoRightSlot">⌘+T</div>
    </DropdownMenu.item>
    <DropdownMenu.item
      class="DemoDropdownMenuItem"
      text_value="New Window"
    >
      New Window
      <div class="DemoRightSlot">⌘+N</div>
    </DropdownMenu.item>
    <DropdownMenu.item
      class="DemoDropdownMenuItem"
      disabled
      text_value="New Private Window"
    >
      New Private Window
      <div class="DemoRightSlot">⇧+⌘+N</div>
    </DropdownMenu.item>
    <DropdownMenu.sub>
      <DropdownMenu.sub_trigger
        class="DemoDropdownMenuSubTrigger"
        text_value="More Tools"
      >
        More Tools
        <div class="DemoRightSlot">
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.61514 7.15788C10.7954 7.3502 10.7954 7.64949 10.61514 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z"
              fill="currentColor"
              fill-rule="evenodd"
              clip-rule="evenodd"
            >
            </path>
          </svg>
        </div>
      </DropdownMenu.sub_trigger>
      <DropdownMenu.sub_content
        class="DemoDropdownMenuSubContent"
        side_offset={2}
      >
        <DropdownMenu.item
          class="DemoDropdownMenuItem"
          text_value="Save Page As"
        >
          Save Page As…
          <div class="DemoRightSlot">⌘+S</div>
        </DropdownMenu.item>
        <DropdownMenu.item
          class="DemoDropdownMenuItem"
          text_value="Create Shortcut"
        >
          Create Shortcut…
        </DropdownMenu.item>
        <DropdownMenu.item
          class="DemoDropdownMenuItem"
          text_value="Name Window"
        >
          Name Window…
        </DropdownMenu.item>
        <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
        <DropdownMenu.item
          class="DemoDropdownMenuItem"
          text_value="Developer Tools"
        >
          Developer Tools
        </DropdownMenu.item>
      </DropdownMenu.sub_content>
    </DropdownMenu.sub>

    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />

    <DropdownMenu.checkbox_item
      class="DemoDropdownMenuCheckboxItem"
      checked
      text_value="Show Bookmarks"
    >
      <DropdownMenu.item_indicator
        class="DemoDropdownMenuItemIndicator"
        force_mount
      >
        <svg
          width="15"
          height="15"
          viewBox="0 0 15 15"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
        >
          <path
            d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z"
            fill="currentColor"
            fill-rule="evenodd"
            clip-rule="evenodd"
          >
          </path>
        </svg>
      </DropdownMenu.item_indicator>
      Show Bookmarks
      <div class="DemoRightSlot">⌘+B</div>
    </DropdownMenu.checkbox_item>
    <DropdownMenu.checkbox_item
      class="DemoDropdownMenuCheckboxItem"
      text_value="Show Full URLs"
    >
      <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">
        <svg
          width="15"
          height="15"
          viewBox="0 0 15 15"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
        >
          <path
            d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z"
            fill="currentColor"
            fill-rule="evenodd"
            clip-rule="evenodd"
          >
          </path>
        </svg>
      </DropdownMenu.item_indicator>
      Show Full URLs
    </DropdownMenu.checkbox_item>

    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />

    <DropdownMenu.label class="DemoDropdownMenuLabel">People</DropdownMenu.label>
    <DropdownMenu.radio_group value="pedro">
      <DropdownMenu.radio_item
        class="DemoDropdownMenuRadioItem"
        value="pedro"
        checked
      >
        <DropdownMenu.item_indicator
          class="DemoDropdownMenuItemIndicator"
          force_mount
        >
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z"
              fill="currentColor"
            >
            </path>
          </svg>
        </DropdownMenu.item_indicator>
        Pedro Duarte
      </DropdownMenu.radio_item>
      <DropdownMenu.radio_item
        class="DemoDropdownMenuRadioItem"
        value="colm"
      >
        <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z"
              fill="currentColor"
            >
            </path>
          </svg>
        </DropdownMenu.item_indicator>
        Colm Tuite
      </DropdownMenu.radio_item>
    </DropdownMenu.radio_group>

    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.item
      class="DemoDropdownMenuItem"
      text_value="Close"
    >
      Close
    </DropdownMenu.item>

    <DropdownMenu.arrow class="DemoDropdownMenuArrow" />
  </DropdownMenu.content>
</DropdownMenu.root>
Can be controlled or uncontrolled.
Supports submenus with configurable reading direction.
Supports items, labels, groups of items.
Supports checkable items (single or multiple) with optional indeterminate state.
Supports modal and non-modal modes.
Customize side, alignment, offsets, collision handling.
Optionally render a pointing arrow.
Focus is fully managed.
Full keyboard navigation.
Typeahead support.
Dismissing and layering behavior is highly customizable.

Anatomy

Import all parts and piece them together.

<DropdownMenu.root id="…">
  <DropdownMenu.trigger content_id="…" />
  <DropdownMenu.portal>
    <DropdownMenu.content id="…">
      <DropdownMenu.label />
      <DropdownMenu.item />
      <DropdownMenu.group>
        <DropdownMenu.item />
      </DropdownMenu.group>
      <DropdownMenu.checkbox_item>
        <DropdownMenu.item_indicator />
      </DropdownMenu.checkbox_item>
      <DropdownMenu.radio_group>
        <DropdownMenu.radio_item>
          <DropdownMenu.item_indicator />
        </DropdownMenu.radio_item>
      </DropdownMenu.radio_group>
      <DropdownMenu.sub>
        <DropdownMenu.sub_trigger />
        <DropdownMenu.sub_content />
      </DropdownMenu.sub>
      <DropdownMenu.separator />
      <DropdownMenu.arrow />
    </DropdownMenu.content>
  </DropdownMenu.portal>
</DropdownMenu.root>

Anatomy

Root
Contains all the parts of a dropdown menu.
Trigger
The button that toggles the dropdown menu.
Portal
Portals the content into the document (default `body`).
Content
The component that pops out when the menu is open.
Item
An actionable menu item.
Checkbox Item
An item that can be checked or unchecked.
Radio Group
Groups mutually exclusive `radio_item` parts.
Radio Item
An item that can be selected among a radio group.
Item Indicator
Renders when a checkbox or radio item is checked.
Label
A non-focusable section label.
Separator
Visually separates groups of items.
Group
Groups multiple items.
Arrow
Optional pointer linking the trigger to the content.
Sub
Contains all the parts of a submenu.
Sub Trigger
An item that opens a submenu.
Sub Content
The submenu panel.

API Reference

Root

Contains all the parts of a dropdown menu.

Prop Type Default Description
default_open boolean false
dir string "ltr"
id string
modal boolean true
on_open_change string nil
open boolean false
default_open
Type boolean Default false
dir
Type string Default "ltr"
id
Type string Default
modal
Type boolean Default true
on_open_change
Type string Default nil
open
Type boolean Default false

Trigger

The button that toggles the dropdown menu. By default, DropdownMenu.content positions itself against the trigger.

Prop Type Default Description
as string "button"
content_id string nil
disabled boolean false
id string nil
as
Type string Default "button"
content_id
Type string Default nil
disabled
Type boolean Default false
id
Type string Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the menu is open.
[data-disabled] Present when disabled Present when the trigger is disabled.

Portal

When used, portals the content part into the target (default body).

Prop Type Default Description
class any nil
container string "div"
id string
target string "body"
class
Type any Default nil
container
Type string Default "div"
id
Type string Default
target
Type string Default "body"

Content

The component that pops out when the dropdown menu is open.

Prop Type Default Description
align string "start"
id string nil
loop boolean true
side string "bottom"
side_offset integer 4
align
Type string Default "start"
id
Type string Default nil
loop
Type boolean Default true
side
Type string Default "bottom"
side_offset
Type integer Default 4

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the menu is open.
[data-side] left | right | bottom | top The side of the trigger the content rendered against.
[data-align] start | end | center The alignment against the trigger.
[data-orientation] vertical | horizontal The orientation of the menu.

| CSS variable | Description | | --- | --- | | --radix-dropdown-menu-content-transform-origin | The transform-origin computed from content and arrow positions/offsets | | --radix-dropdown-menu-content-available-width | Remaining width between the trigger and the boundary edge | | --radix-dropdown-menu-content-available-height | Remaining height between the trigger and the boundary edge | | --radix-dropdown-menu-trigger-width | The width of the trigger | | --radix-dropdown-menu-trigger-height | The height of the trigger |

Item

The component that contains the dropdown menu items.

Prop Type Default Description
disabled boolean false
id string nil
text_value string nil
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-orientation] vertical | horizontal The orientation of the menu.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Checkbox Item

An item that can be controlled and rendered like a checkbox.

Prop Type Default Description
checked boolean false
disabled boolean false
id string nil
text_value string nil
checked
Type boolean Default false
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the checked state.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Radio Group

Used to group multiple DropdownMenu.radio_item parts.

Prop Type Default Description
id string nil
value string nil
id
Type string Default nil
value
Type string Default nil

Radio Item

An item that can be controlled and rendered like a radio.

Prop Type Default Description
checked boolean false
disabled boolean false
id string nil
text_value string nil
value string
checked
Type boolean Default false
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil
value
Type string Default

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the selected state.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Item Indicator

Renders when the parent checkbox_item or radio_item is checked. Style directly or wrap an icon.

Prop Type Default Description
force_mount boolean false
id string nil
force_mount
Type boolean Default false
id
Type string Default nil

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the checked state of the parent item.

Label

Used to render a label. It won't be focusable using arrow keys.

Prop Type Default Description
id string nil
id
Type string Default nil

Separator

Used to visually separate items in the dropdown menu.

Prop Type Default Description
decorative boolean true
id string nil
decorative
Type boolean Default true
id
Type string Default nil

Group

Used to group multiple DropdownMenu.item parts.

Prop Type Default Description
id string nil
id
Type string Default nil

Arrow

An optional arrow element rendered alongside the content to visually link the trigger.

Prop Type Default Description
id string nil
id
Type string Default nil

Sub

Contains all the parts of a submenu.

Prop Type Default Description
id string nil
open boolean false
id
Type string Default nil
open
Type boolean Default false

Sub Trigger

An item that opens a submenu. Must be rendered inside DropdownMenu.sub.

Prop Type Default Description
disabled boolean false
id string nil
text_value string nil
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the submenu is open.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Sub Content

The component that pops out when a submenu is open. Must be rendered inside DropdownMenu.sub.

Prop Type Default Description
align string "start"
id string nil
side string "right"
side_offset integer 0
align
Type string Default "start"
id
Type string Default nil
side
Type string Default "right"
side_offset
Type integer Default 0

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the submenu is open.
[data-side] left | right | bottom | top The side the submenu rendered against.
[data-align] start | end | center The alignment of the submenu.
[data-orientation] vertical | horizontal The orientation of the submenu.

Examples

With submenus

You can create submenus by using DropdownMenu.sub in combination with its parts.

<DropdownMenu.root id="dropdown-sub">
  <DropdownMenu.trigger id="dropdown-sub-trigger" content_id="dropdown-sub-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-sub-content">
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.sub>
      <DropdownMenu.sub_trigger class="DemoDropdownMenuSubTrigger">Sub menu →</DropdownMenu.sub_trigger>
      <DropdownMenu.sub_content class="DemoDropdownMenuSubContent">
        <DropdownMenu.item class="DemoDropdownMenuItem">Sub menu item</DropdownMenu.item>
        <DropdownMenu.item class="DemoDropdownMenuItem">Sub menu item</DropdownMenu.item>
        <DropdownMenu.arrow class="DemoDropdownMenuArrow" />
      </DropdownMenu.sub_content>
    </DropdownMenu.sub>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
  </DropdownMenu.content>
</DropdownMenu.root>

With disabled items

You can add special styles to disabled items via the data-disabled attribute.

<DropdownMenu.root id="dropdown-disabled">
  <DropdownMenu.trigger id="dropdown-disabled-trigger" content_id="dropdown-disabled-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-disabled-content">
    <DropdownMenu.item class="DemoDropdownMenuItem" disabled>…</DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
  </DropdownMenu.content>
</DropdownMenu.root>
.DemoDropdownMenuItem[data-disabled] {
  color: gainsboro;
}

With separators

Use the separator part to add a separator between items.

<DropdownMenu.root id="dropdown-separators">
  <DropdownMenu.trigger id="dropdown-separators-trigger" content_id="dropdown-separators-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-separators-content">
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
  </DropdownMenu.content>
</DropdownMenu.root>

With labels

Use the label part to help label a section.

<DropdownMenu.root id="dropdown-labels">
  <DropdownMenu.trigger id="dropdown-labels-trigger" content_id="dropdown-labels-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-labels-content">
    <DropdownMenu.label class="DemoDropdownMenuLabel">Label</DropdownMenu.label>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
  </DropdownMenu.content>
</DropdownMenu.root>

With checkbox items

Use the checkbox_item part to add an item that can be checked. Pass checked from LiveView assigns to control state.

<DropdownMenu.root id="dropdown-checkbox">
  <DropdownMenu.trigger id="dropdown-checkbox-trigger" content_id="dropdown-checkbox-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-checkbox-content">
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">…</DropdownMenu.item>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.checkbox_item checked={@checked} class="DemoDropdownMenuCheckboxItem" text_value="Checkbox item">
      <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">✓</DropdownMenu.item_indicator>
      Checkbox item
    </DropdownMenu.checkbox_item>
  </DropdownMenu.content>
</DropdownMenu.root>

With radio items

Use the radio_group and radio_item parts to add an item that can be checked amongst others.

<DropdownMenu.root id="dropdown-radio">
  <DropdownMenu.trigger id="dropdown-radio-trigger" content_id="dropdown-radio-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-radio-content">
    <DropdownMenu.radio_group value={@color}>
      <DropdownMenu.radio_item value="red" checked={@color == "red"} class="DemoDropdownMenuRadioItem">
        <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">●</DropdownMenu.item_indicator>
        Red
      </DropdownMenu.radio_item>
      <DropdownMenu.radio_item value="blue" checked={@color == "blue"} class="DemoDropdownMenuRadioItem">
        <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">●</DropdownMenu.item_indicator>
        Blue
      </DropdownMenu.radio_item>
      <DropdownMenu.radio_item value="green" checked={@color == "green"} class="DemoDropdownMenuRadioItem">
        <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">●</DropdownMenu.item_indicator>
        Green
      </DropdownMenu.radio_item>
    </DropdownMenu.radio_group>
  </DropdownMenu.content>
</DropdownMenu.root>

With complex items

You can add extra decorative elements in the item parts, such as images.

<DropdownMenu.root id="dropdown-complex">
  <DropdownMenu.trigger id="dropdown-complex-trigger" content_id="dropdown-complex-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-complex-content">
    <DropdownMenu.item class="DemoDropdownMenuItem">
      <img src="…" alt="" />
      Adolfo Hess
    </DropdownMenu.item>
    <DropdownMenu.item class="DemoDropdownMenuItem">
      <img src="…" alt="" />
      Miyah Myles
    </DropdownMenu.item>
  </DropdownMenu.content>
</DropdownMenu.root>

Constrain the content/sub-content size

You may want to constrain the width of the content (or sub-content) so that it matches the trigger width, or constrain its height to not exceed the viewport.

We expose several CSS custom properties such as --radix-dropdown-menu-trigger-width and --radix-dropdown-menu-content-available-height to support this. Use them to constrain the content dimensions.

<DropdownMenu.root id="dropdown-constrain">
  <DropdownMenu.trigger id="dropdown-constrain-trigger" content_id="dropdown-constrain-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-constrain-content" class="DemoDropdownMenuContent" side_offset={5}>
    …
  </DropdownMenu.content>
</DropdownMenu.root>
.DemoDropdownMenuContent {
  width: var(--radix-dropdown-menu-trigger-width);
  max-height: var(--radix-dropdown-menu-content-available-height);
}

Origin-aware animations

We expose a CSS custom property --radix-dropdown-menu-content-transform-origin. Use it to animate the content from its computed origin based on side, side_offset, align, and any collisions.

<DropdownMenu.root id="dropdown-origin">
  <DropdownMenu.trigger id="dropdown-origin-trigger" content_id="dropdown-origin-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-origin-content" class="DemoDropdownMenuContent">
    …
  </DropdownMenu.content>
</DropdownMenu.root>
.DemoDropdownMenuContent {
  transform-origin: var(--radix-dropdown-menu-content-transform-origin);
  animation: scaleIn 0.5s ease-out;
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

Collision-aware animations

We expose data-side and data-align attributes. Their values change at runtime to reflect collisions. Use them to create collision and direction-aware animations.

<DropdownMenu.root id="dropdown-collision">
  <DropdownMenu.trigger id="dropdown-collision-trigger" content_id="dropdown-collision-content">…</DropdownMenu.trigger>
  <DropdownMenu.content id="dropdown-collision-content" class="DemoDropdownMenuContent">
    …
  </DropdownMenu.content>
</DropdownMenu.root>
.DemoDropdownMenuContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.DemoDropdownMenuContent[data-side="top"] {
  animation-name: slideUp;
}
.DemoDropdownMenuContent[data-side="bottom"] {
  animation-name: slideDown;
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

Accessibility

Adheres to the Menu Button WAI-ARIA design pattern and uses roving tabindex to manage focus movement among menu items.

Keyboard Interactions

Keyboard Interactions

Key Description
Space When focus is on `DropdownMenu.trigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item.
Enter When focus is on `DropdownMenu.trigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item.
ArrowDown When focus is on `DropdownMenu.trigger`, opens the dropdown menu. When focus is on an item, moves focus to the next item.
ArrowUp When focus is on an item, moves focus to the previous item.
ArrowRight, ArrowLeft When focus is on `DropdownMenu.sub_trigger`, opens or closes the submenu depending on reading direction.
Esc Closes the dropdown menu and moves focus to `DropdownMenu.trigger`.

Custom APIs

Create your own API by abstracting the primitive parts into your own component.

Abstract the arrow and item indicators

This example abstracts DropdownMenu.arrow and DropdownMenu.item_indicator. It also wraps implementation details for checkbox_item and radio_item.

Usage

<.dropdown_menu id="my-menu">
  <:trigger>DropdownMenu trigger</:trigger>
  <:content>
    <DropdownMenu.item class="DemoDropdownMenuItem">Item</DropdownMenu.item>
    <DropdownMenu.label class="DemoDropdownMenuLabel">Label</DropdownMenu.label>
    <.dropdown_menu_checkbox_item checked={@checked}>Checkbox item</.dropdown_menu_checkbox_item>
    <DropdownMenu.separator class="DemoDropdownMenuSeparator" />
    <DropdownMenu.radio_group value={@color}>
      <.dropdown_menu_radio_item value="a" checked={@color == "a"}>Radio A</.dropdown_menu_radio_item>
      <.dropdown_menu_radio_item value="b" checked={@color == "b"}>Radio B</.dropdown_menu_radio_item>
    </DropdownMenu.radio_group>
  </:content>
</.dropdown_menu>

Implementation

def dropdown_menu(assigns) do
  ~H"""
  <DropdownMenu.root id={@id}>
    <DropdownMenu.trigger id={"#{@id}-trigger"} content_id={"#{@id}-content"}>
      {render_slot(@trigger)}
    </DropdownMenu.trigger>
    <DropdownMenu.content id={"#{@id}-content"} class="DemoDropdownMenuContent">
      {render_slot(@content)}
      <DropdownMenu.arrow class="DemoDropdownMenuArrow" />
    </DropdownMenu.content>
  </DropdownMenu.root>
  """
end

def dropdown_menu_checkbox_item(assigns) do
  ~H"""
  <DropdownMenu.checkbox_item checked={@checked} class="DemoDropdownMenuCheckboxItem" {@rest}>
    {render_slot(@inner_block)}
    <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">✓</DropdownMenu.item_indicator>
  </DropdownMenu.checkbox_item>
  """
end

def dropdown_menu_radio_item(assigns) do
  ~H"""
  <DropdownMenu.radio_item value={@value} checked={@checked} class="DemoDropdownMenuRadioItem" {@rest}>
    {render_slot(@inner_block)}
    <DropdownMenu.item_indicator class="DemoDropdownMenuItemIndicator">●</DropdownMenu.item_indicator>
  </DropdownMenu.radio_item>
  """
end