> Native Solid 2 fork. Original documentation and designs © WorkOS; historical posts retain their original context.

# Dropdown Menu

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

## Features

- 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.

```jsx
import { DropdownMenu } from "@radix-solid/primitives";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger />



		<DropdownMenu.Portal>

			<DropdownMenu.Content>

				<DropdownMenu.Label />

				<DropdownMenu.Item />



				<DropdownMenu.Group>

					<DropdownMenu.Item />

				</DropdownMenu.Group>



				<DropdownMenu.CheckboxItem>

					<DropdownMenu.ItemIndicator />

				</DropdownMenu.CheckboxItem>



				<DropdownMenu.RadioGroup>

					<DropdownMenu.RadioItem value="item">

						<DropdownMenu.ItemIndicator />

					</DropdownMenu.RadioItem>

				</DropdownMenu.RadioGroup>



				<DropdownMenu.Sub>

					<DropdownMenu.SubTrigger />

					<DropdownMenu.Portal>

						<DropdownMenu.SubContent />

					</DropdownMenu.Portal>

				</DropdownMenu.Sub>



				<DropdownMenu.Separator />

				<DropdownMenu.Arrow />

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</DropdownMenu.Root>;
```

## API Reference

### Root

Contains all the parts of a dropdown menu.

| Prop                                                                                                                                                                      | Type       | Default |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `defaultOpen`The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state.                                       | `boolean`  | —       |
| `open`The controlled open state of the dropdown menu. Must be used in conjunction with `onOpenChange`.                                                                    | `boolean`  | —       |
| `onOpenChange`Event handler called when the open state of the dropdown menu changes.                                                                                      | `function` | —       |
| `modal`The modality of the dropdown menu. When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. | `boolean`  | `true`  |
| `dir`The reading direction of submenus when applicable. If omitted, inherits globally from `DirectionProvider` or assumes LTR (left-to-right) reading mode.               | `enum`     | —       |

### Trigger

The button that toggles the dropdown menu. By default, the `DropdownMenu.Content` will position itself against the trigger.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

| Data attribute    | Values                |
| ----------------- | --------------------- |
| `[data-state]`    | `"open" \| "closed"`  |
| `[data-disabled]` | Present when disabled |

### Portal

When used, portals the content part into the `body`.

| Prop                                                                                                                                                                                                                                                          | Type          | Default         |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | --------------- |
| `forceMount`Used to force mounting when more control is needed. Useful when controlling animation with Solid-compatible animation libraries. If used on this part, it will be inherited by `DropdownMenu.Content` and `DropdownMenu.SubContent` respectively. | `boolean`     | —               |
| `container`Specify a container element to portal the content into.                                                                                                                                                                                            | `HTMLElement` | `document.body` |

### Content

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

| Prop                                                                                                                                                                                                                              | Type                | Default     |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                                           | `boolean`           | `false`     |
| `loop`When `true`, keyboard navigation will loop from last item to first, and vice versa.                                                                                                                                         | `boolean`           | `false`     |
| `onCloseAutoFocus`Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`.                                                                                      | `function`          | —           |
| `onEscapeKeyDown`Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`                                                                                                          | `function`          | —           |
| `onPointerDownOutside`Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                                                | `function`          | —           |
| `onFocusOutside`Event handler called when focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                                                                 | `function`          | —           |
| `onInteractOutside`Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                          | `function`          | —           |
| `forceMount`Used to force mounting when more control is needed. Useful when controlling animation with Solid-compatible animation libraries. It inherits from `DropdownMenu.Portal`.                                              | `boolean`           | —           |
| `side`The preferred side of the trigger to render against when open. Will be reversed when collisions occur and `avoidCollisions` is enabled.                                                                                     | `enum`              | `"bottom"`  |
| `sideOffset`The distance in pixels from the trigger.                                                                                                                                                                              | `number`            | `0`         |
| `align`The preferred alignment against the trigger. May change when collisions occur.                                                                                                                                             | `enum`              | `"center"`  |
| `alignOffset`An offset in pixels from the `"start"` or `"end"` alignment options.                                                                                                                                                 | `number`            | `0`         |
| `avoidCollisions`When `true`, overrides the `side` and`align` preferences to prevent collisions with boundary edges.                                                                                                              | `boolean`           | `true`      |
| `collisionBoundary`The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.                                                        | `Boundary`          | `[]`        |
| `collisionPadding`The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: `{ top: 20, left: 20 }`.                | `number \| Padding` | `0`         |
| `arrowPadding`The padding between the arrow and the edges of the content. If your content has `border-radius`, this will prevent it from overflowing the corners.                                                                 | `number`            | `0`         |
| `sticky`The sticky behavior on the align axis. `"partial"` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst `"always"` will keep the content in the boundary regardless. | `enum`              | `"partial"` |
| `hideWhenDetached`Whether to hide the content when the trigger becomes fully occluded.                                                                                                                                            | `boolean`           | `false`     |

| Data attribute       | Values                                   |
| -------------------- | ---------------------------------------- |
| `[data-state]`       | `"open" \| "closed"`                     |
| `[data-side]`        | `"left" \| "right" \| "bottom" \| "top"` |
| `[data-align]`       | `"start" \| "end" \| "center"`           |
| `[data-orientation]` | `"vertical" \| "horizontal"`             |

| CSS Variable                                     | Description                                                                  |
| ------------------------------------------------ | ---------------------------------------------------------------------------- |
| `--radix-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--radix-dropdown-menu-content-available-width`  | The remaining width between the trigger and the boundary edge                |
| `--radix-dropdown-menu-content-available-height` | The 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                                                    |

### Arrow

An optional arrow element to render alongside the dropdown menu. This can be used to help visually link the trigger with the `DropdownMenu.Content`. Must be rendered inside `DropdownMenu.Content`.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |
| `width`The width of the arrow in pixels.                                                                                                                                | `number`  | `10`    |
| `height`The height of the arrow in pixels.                                                                                                                              | `number`  | `5`     |

### Item

The component that contains the dropdown menu items.

| Prop                                                                                                                                                                                                           | Type       | Default |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                        | `boolean`  | `false` |
| `disabled`When `true`, prevents the user from interacting with the item.                                                                                                                                       | `boolean`  | —       |
| `onSelect`Event handler called when the user selects an item (via mouse or keyboard). Calling `event.preventDefault` in this handler will prevent the dropdown menu from closing when selecting that item.     | `function` | —       |
| `textValue`Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. Use this when the content is complex, or you have non-textual content inside. | `string`   | —       |

| Data attribute       | Values                       |
| -------------------- | ---------------------------- |
| `[data-orientation]` | `"vertical" \| "horizontal"` |
| `[data-highlighted]` | Present when highlighted     |
| `[data-disabled]`    | Present when disabled        |

### Group

Used to group multiple `DropdownMenu.Item`s.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

### Label

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

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

### CheckboxItem

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

| Prop                                                                                                                                                                                                           | Type                         | Default |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                        | `boolean`                    | `false` |
| `checked`The controlled checked state of the item. Must be used in conjunction with `onCheckedChange`.                                                                                                         | `boolean \| 'indeterminate'` | —       |
| `onCheckedChange`Event handler called when the checked state changes.                                                                                                                                          | `function`                   | —       |
| `disabled`When `true`, prevents the user from interacting with the item.                                                                                                                                       | `boolean`                    | —       |
| `onSelect`Event handler called when the user selects an item (via mouse or keyboard). Calling `event.preventDefault` in this handler will prevent the dropdown menu from closing when selecting that item.     | `function`                   | —       |
| `textValue`Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. Use this when the content is complex, or you have non-textual content inside. | `string`                     | —       |

| Data attribute       | Values                                        |
| -------------------- | --------------------------------------------- |
| `[data-state]`       | `"checked" \| "unchecked" \| "indeterminate"` |
| `[data-highlighted]` | Present when highlighted                      |
| `[data-disabled]`    | Present when disabled                         |

### RadioGroup

Used to group multiple `DropdownMenu.RadioItem`s.

| Prop                                                                                                                                                                    | Type       | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean`  | `false` |
| `value`The value of the selected item in the group.                                                                                                                     | `string`   | —       |
| `onValueChange`Event handler called when the value changes.                                                                                                             | `function` | —       |

### RadioItem

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

| Prop                                                                                                                                                                                                           | Type       | Default |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                        | `boolean`  | `false` |
| `value*`The unique value of the item.                                                                                                                                                                          | `string`   | —       |
| `disabled`When `true`, prevents the user from interacting with the item.                                                                                                                                       | `boolean`  | —       |
| `onSelect`Event handler called when the user selects an item (via mouse or keyboard). Calling `event.preventDefault` in this handler will prevent the dropdown menu from closing when selecting that item.     | `function` | —       |
| `textValue`Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. Use this when the content is complex, or you have non-textual content inside. | `string`   | —       |

| Data attribute       | Values                                        |
| -------------------- | --------------------------------------------- |
| `[data-state]`       | `"checked" \| "unchecked" \| "indeterminate"` |
| `[data-highlighted]` | Present when highlighted                      |
| `[data-disabled]`    | Present when disabled                         |

### ItemIndicator

Renders when the parent `DropdownMenu.CheckboxItem` or `DropdownMenu.RadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |
| `forceMount`Used to force mounting when more control is needed. Useful when controlling animation with Solid-compatible animation libraries.                            | `boolean` | —       |

| Data attribute | Values                                        |
| -------------- | --------------------------------------------- |
| `[data-state]` | `"checked" \| "unchecked" \| "indeterminate"` |

### Separator

Used to visually separate items in the dropdown menu.

| Prop                                                                                                                                                                    | Type      | Default |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details. | `boolean` | `false` |

### Sub

Contains all the parts of a submenu.

| Prop                                                                                                                          | Type       | Default |
| ----------------------------------------------------------------------------------------------------------------------------- | ---------- | ------- |
| `defaultOpen`The open state of the submenu when it is initially rendered. Use when you do not need to control its open state. | `boolean`  | —       |
| `open`The controlled open state of the submenu. Must be used in conjunction with `onOpenChange`.                              | `boolean`  | —       |
| `onOpenChange`Event handler called when the open state of the submenu changes.                                                | `function` | —       |

### SubTrigger

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

| Prop                                                                                                                                                                                                           | Type      | Default |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                        | `boolean` | `false` |
| `disabled`When `true`, prevents the user from interacting with the item.                                                                                                                                       | `boolean` | —       |
| `textValue`Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item. Use this when the content is complex, or you have non-textual content inside. | `string`  | —       |

| Data attribute       | Values                   |
| -------------------- | ------------------------ |
| `[data-state]`       | `"open" \| "closed"`     |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]`    | Present when disabled    |

| CSS Variable                                     | Description                                                                  |
| ------------------------------------------------ | ---------------------------------------------------------------------------- |
| `--radix-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--radix-dropdown-menu-content-available-width`  | The remaining width between the trigger and the boundary edge                |
| `--radix-dropdown-menu-content-available-height` | The 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                                                    |

### SubContent

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

| Prop                                                                                                                                                                                                                              | Type                | Default     |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------- |
| `asChild`Render through a single-target factory, merging props and behavior with the chosen host. Read our [Composition](../guides/composition) guide for more details.                                                           | `boolean`           | `false`     |
| `loop`When `true`, keyboard navigation will loop from last item to first, and vice versa.                                                                                                                                         | `boolean`           | `false`     |
| `onEscapeKeyDown`Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`                                                                                                          | `function`          | —           |
| `onPointerDownOutside`Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                                                | `function`          | —           |
| `onFocusOutside`Event handler called when focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                                                                 | `function`          | —           |
| `onInteractOutside`Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`.                                          | `function`          | —           |
| `forceMount`Used to force mounting when more control is needed. Useful when controlling animation with Solid-compatible animation libraries. It inherits from `DropdownMenu.Portal`.                                              | `boolean`           | —           |
| `sideOffset`The distance in pixels from the trigger.                                                                                                                                                                              | `number`            | `0`         |
| `align`The direction the submenu appears from its anchor item. May change when collisions occur.                                                                                                                                  | `enum`              | `"start"`   |
| `alignOffset`An offset in pixels from the `"start"` or `"end"` alignment options.                                                                                                                                                 | `number`            | `0`         |
| `avoidCollisions`When `true`, overrides the `side` and`align` preferences to prevent collisions with boundary edges.                                                                                                              | `boolean`           | `true`      |
| `collisionBoundary`The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.                                                        | `Boundary`          | `[]`        |
| `collisionPadding`The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: `{ top: 20, left: 20 }`.                | `number \| Padding` | `0`         |
| `arrowPadding`The padding between the arrow and the edges of the content. If your content has `border-radius`, this will prevent it from overflowing the corners.                                                                 | `number`            | `0`         |
| `sticky`The sticky behavior on the align axis. `"partial"` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst `"always"` will keep the content in the boundary regardless. | `enum`              | `"partial"` |
| `hideWhenDetached`Whether to hide the content when the trigger becomes fully occluded.                                                                                                                                            | `boolean`           | `false`     |

| Data attribute       | Values                                   |
| -------------------- | ---------------------------------------- |
| `[data-state]`       | `"open" \| "closed"`                     |
| `[data-side]`        | `"left" \| "right" \| "bottom" \| "top"` |
| `[data-align]`       | `"start" \| "end" \| "center"`           |
| `[data-orientation]` | `"vertical" \| "horizontal"`             |

## Examples

### With submenus

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

```jsx
<DropdownMenu.Root>

	<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

	<DropdownMenu.Portal>

		<DropdownMenu.Content>

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Separator />

			<DropdownMenu.Sub>

				<DropdownMenu.SubTrigger>Sub menu →</DropdownMenu.SubTrigger>

				<DropdownMenu.Portal>

					<DropdownMenu.SubContent>

						<DropdownMenu.Item>Sub menu item</DropdownMenu.Item>

						<DropdownMenu.Item>Sub menu item</DropdownMenu.Item>

						<DropdownMenu.Arrow />

					</DropdownMenu.SubContent>

				</DropdownMenu.Portal>

			</DropdownMenu.Sub>

			<DropdownMenu.Separator />

			<DropdownMenu.Item>…</DropdownMenu.Item>

		</DropdownMenu.Content>

	</DropdownMenu.Portal>

</DropdownMenu.Root>
```

### With disabled items

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

```jsx
// index.tsx

import { DropdownMenu } from "@radix-solid/primitives";

import "./styles.css";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

		<DropdownMenu.Portal>

			<DropdownMenu.Content>

				<DropdownMenu.Item class="DropdownMenuItem" disabled>

					…

				</DropdownMenu.Item>

				<DropdownMenu.Item class="DropdownMenuItem">…</DropdownMenu.Item>

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</DropdownMenu.Root>;
```

```css
/* styles.css */

.DropdownMenuItem[data-disabled] {

	color: gainsboro;

}
```

### With separators

Use the `Separator` part to add a separator between items.

```jsx
<DropdownMenu.Root>

	<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

	<DropdownMenu.Portal>

		<DropdownMenu.Content>

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Separator />

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Separator />

			<DropdownMenu.Item>…</DropdownMenu.Item>

		</DropdownMenu.Content>

	</DropdownMenu.Portal>

</DropdownMenu.Root>
```

### With labels

Use the `Label` part to help label a section.

```jsx
<DropdownMenu.Root>

	<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

	<DropdownMenu.Portal>

		<DropdownMenu.Content>

			<DropdownMenu.Label>Label</DropdownMenu.Label>

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Item>…</DropdownMenu.Item>

			<DropdownMenu.Item>…</DropdownMenu.Item>

		</DropdownMenu.Content>

	</DropdownMenu.Portal>

</DropdownMenu.Root>
```

### With checkbox items

Use the `CheckboxItem` part to add an item that can be checked.

```jsx
import { createSignal } from "solid-js";

import { CheckIcon } from "@radix-solid/icons";

import { DropdownMenu } from "@radix-solid/primitives";

export default () => {

  const [checked, setChecked] = createSignal(true);

  return <DropdownMenu.Root>

			<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

			<DropdownMenu.Portal>

				<DropdownMenu.Content>

					<DropdownMenu.Item>…</DropdownMenu.Item>

					<DropdownMenu.Item>…</DropdownMenu.Item>

					<DropdownMenu.Separator />

					<DropdownMenu.CheckboxItem checked={checked()} onCheckedChange={setChecked}>

						<DropdownMenu.ItemIndicator>

							<CheckIcon />

						</DropdownMenu.ItemIndicator>

						Checkbox item

					</DropdownMenu.CheckboxItem>

				</DropdownMenu.Content>

			</DropdownMenu.Portal>

		</DropdownMenu.Root>;

};
```

### With radio items

Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others.

```jsx
import { createSignal } from "solid-js";

import { CheckIcon } from "@radix-solid/icons";

import { DropdownMenu } from "@radix-solid/primitives";

export default () => {

  const [color, setColor] = createSignal("blue");

  return <DropdownMenu.Root>

			<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

			<DropdownMenu.Portal>

				<DropdownMenu.Content>

					<DropdownMenu.RadioGroup value={color()} onValueChange={setColor}>

						<DropdownMenu.RadioItem value="red">

							<DropdownMenu.ItemIndicator>

								<CheckIcon />

							</DropdownMenu.ItemIndicator>

							Red

						</DropdownMenu.RadioItem>

						<DropdownMenu.RadioItem value="blue">

							<DropdownMenu.ItemIndicator>

								<CheckIcon />

							</DropdownMenu.ItemIndicator>

							Blue

						</DropdownMenu.RadioItem>

						<DropdownMenu.RadioItem value="green">

							<DropdownMenu.ItemIndicator>

								<CheckIcon />

							</DropdownMenu.ItemIndicator>

							Green

						</DropdownMenu.RadioItem>

					</DropdownMenu.RadioGroup>

				</DropdownMenu.Content>

			</DropdownMenu.Portal>

		</DropdownMenu.Root>;

};
```

### With complex items

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

```jsx
import { DropdownMenu } from "@radix-solid/primitives";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

		<DropdownMenu.Portal>

			<DropdownMenu.Content>

				<DropdownMenu.Item>

					<img src="…" />

					Adolfo Hess

				</DropdownMenu.Item>

				<DropdownMenu.Item>

					<img src="…" />

					Miyah Myles

				</DropdownMenu.Item>

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</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 (or sub-trigger) width. You may also want to 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.

```jsx
// index.tsx

import { DropdownMenu } from "@radix-solid/primitives";

import "./styles.css";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

		<DropdownMenu.Portal>

			<DropdownMenu.Content class="DropdownMenuContent" sideOffset={5}>

				…

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</DropdownMenu.Root>;
```

```css
/* styles.css */

.DropdownMenuContent {

	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`, `sideOffset`, `align`, `alignOffset` and any collisions.

```jsx
// index.tsx

import { DropdownMenu } from "@radix-solid/primitives";

import "./styles.css";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

		<DropdownMenu.Portal>

			<DropdownMenu.Content class="DropdownMenuContent">

				…

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</DropdownMenu.Root>;
```

```css
/* styles.css */

.DropdownMenuContent {

	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 will change at runtime to reflect collisions. Use them to create collision and direction-aware animations.

```jsx
// index.tsx

import { DropdownMenu } from "@radix-solid/primitives";

import "./styles.css";

export default () => <DropdownMenu.Root>

		<DropdownMenu.Trigger>…</DropdownMenu.Trigger>

		<DropdownMenu.Portal>

			<DropdownMenu.Content class="DropdownMenuContent">

				…

			</DropdownMenu.Content>

		</DropdownMenu.Portal>

	</DropdownMenu.Root>;
```

```css
/* styles.css */

.DropdownMenuContent {

	animation-duration: 0.6s;

	animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);

}

.DropdownMenuContent[data-side="top"] {

	animation-name: slideUp;

}

.DropdownMenuContent[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](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/) and uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex) to manage focus movement among menu items.

### 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.SubTrigger`, 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 the `DropdownMenu.Arrow` and `DropdownMenu.ItemIndicator` parts. It also wraps implementation details for `CheckboxItem` and `RadioItem`.

#### Usage

```jsx
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuGroup, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator } from "./your-dropdown-menu";

export default () => <DropdownMenu>

		<DropdownMenuTrigger>DropdownMenu trigger</DropdownMenuTrigger>

		<DropdownMenuContent>

			<DropdownMenuItem>Item</DropdownMenuItem>

			<DropdownMenuLabel>Label</DropdownMenuLabel>

			<DropdownMenuGroup>Group</DropdownMenuGroup>

			<DropdownMenuCheckboxItem>CheckboxItem</DropdownMenuCheckboxItem>

			<DropdownMenuSeparator>Separator</DropdownMenuSeparator>

			<DropdownMenuRadioGroup>

				<DropdownMenuRadioItem value="first">First item</DropdownMenuRadioItem>

				<DropdownMenuRadioItem value="second">Second item</DropdownMenuRadioItem>

			</DropdownMenuRadioGroup>

		</DropdownMenuContent>

	</DropdownMenu>;
```

#### Implementation

```jsx
import { omit, type ComponentProps } from "solid-js";

// your-dropdown-menu.tsx



import { DropdownMenu as DropdownMenuPrimitive } from "@radix-solid/primitives";

import { CheckIcon, DividerHorizontalIcon } from "@radix-solid/icons";

export const DropdownMenu = DropdownMenuPrimitive.Root;

export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;

export const DropdownMenuContent = (p: Extract<ComponentProps<typeof DropdownMenuPrimitive.Content>, {

  asChild?: false;

}>) => {

  return <DropdownMenuPrimitive.Portal>

				<DropdownMenuPrimitive.Content {...omit(p, "children", "class")} ref={p.ref}>

					{p.children}

					<DropdownMenuPrimitive.Arrow />

				</DropdownMenuPrimitive.Content>

			</DropdownMenuPrimitive.Portal>;

};

export const DropdownMenuLabel = DropdownMenuPrimitive.Label;

export const DropdownMenuItem = DropdownMenuPrimitive.Item;

export const DropdownMenuGroup = DropdownMenuPrimitive.Group;

export const DropdownMenuCheckboxItem = (p: Extract<ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>, {

  asChild?: false;

}>) => {

  return <DropdownMenuPrimitive.CheckboxItem {...omit(p, "children", "class")} ref={p.ref}>

				{p.children}

				<DropdownMenuPrimitive.ItemIndicator>

					{omit(p, "children", "class").checked === "indeterminate" && <DividerHorizontalIcon />}

					{omit(p, "children", "class").checked === true && <CheckIcon />}

				</DropdownMenuPrimitive.ItemIndicator>

			</DropdownMenuPrimitive.CheckboxItem>;

};

export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;

export const DropdownMenuRadioItem = (p: Extract<ComponentProps<typeof DropdownMenuPrimitive.RadioItem>, {

  asChild?: false;

}>) => {

  return <DropdownMenuPrimitive.RadioItem {...omit(p, "children", "class")} ref={p.ref}>

				{p.children}

				<DropdownMenuPrimitive.ItemIndicator>

					<CheckIcon />

				</DropdownMenuPrimitive.ItemIndicator>

			</DropdownMenuPrimitive.RadioItem>;

};

export const DropdownMenuSeparator = DropdownMenuPrimitive.Separator;
```
