# Menu

> A temporary list of choices or actions that opens from a button or a field.

- Category: Selection and input
- API status: Expressive
- Compose APIs: `DropdownMenu`, `DropdownMenuPopup`, `DropdownMenuGroup`, `DropdownMenuItem`, `ExposedDropdownMenuBox`, `MenuDefaults`
- Interactive page: https://m3e.ljzapps.app/#components/menu

## When to use

Use a dropdown menu for actions related to an element, an exposed dropdown to choose a value in a form, and the grouped expressive menu when actions belong to distinct sections.

Menus close when an item is chosen, when the user clicks outside or presses Escape.

## Playground

The interactive page has a playground with live property controls for this component and generated code.

## Examples

### Standard

```kotlin
var expanded by remember { mutableStateOf(false) }

Box(Modifier.fillMaxWidth().height(220.dp), contentAlignment = Alignment.TopStart) {
    IconButton(onClick = { expanded = true }) {
        Icon(Icons.Rounded.MoreVert, contentDescription = "More options")
    }
    DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        DropdownMenuItem(
            text = { Text("Edit") },
            onClick = { expanded = false },
            leadingIcon = { Icon(Icons.Rounded.Edit, contentDescription = null) },
        )
        DropdownMenuItem(
            text = { Text("Delete") },
            onClick = { expanded = false },
            leadingIcon = { Icon(Icons.Rounded.Delete, contentDescription = null) },
        )
    }
}
```

### Grouped, expressive

Items in separate rounded groups.

```kotlin
var expanded by remember { mutableStateOf(false) }

Box(Modifier.fillMaxWidth().height(300.dp), contentAlignment = Alignment.TopStart) {
    IconButton(onClick = { expanded = true }) {
        Icon(Icons.Rounded.MoreVert, contentDescription = "More options")
    }
    DropdownMenuPopup(expanded = expanded, onDismissRequest = { expanded = false }) {
        val groups = listOf(
            listOf("Edit" to Icons.Rounded.Edit, "Copy" to Icons.Rounded.ContentCopy),
            listOf("Share" to Icons.Rounded.Share, "Delete" to Icons.Rounded.Delete),
        )
        groups.forEachIndexed { groupIndex, items ->
            DropdownMenuGroup(shapes = MenuDefaults.groupShape(groupIndex, groups.size)) {
                items.forEachIndexed { itemIndex, (label, icon) ->
                    DropdownMenuItem(
                        text = { Text(label) },
                        onClick = { expanded = false },
                        shape = MenuDefaults.itemShape(itemIndex, items.size).shape,
                        leadingIcon = { Icon(icon, contentDescription = null) },
                    )
                }
            }
        }
    }
}
```

### Select

An exposed dropdown inside a text field.

```kotlin
val options = listOf("Light", "Dark", "System default")
var expanded by remember { mutableStateOf(false) }
var selected by rememberSaveable { mutableStateOf(options.last()) }

ExposedDropdownMenuBox(
    expanded = expanded,
    onExpandedChange = { expanded = it },
    modifier = Modifier.widthIn(max = 320.dp),
) {
    OutlinedTextField(
        value = selected,
        onValueChange = {},
        readOnly = true,
        label = { Text("Theme") },
        trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
        modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
    )
    ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
        options.forEach { option ->
            DropdownMenuItem(
                text = { Text(option) },
                onClick = {
                    selected = option
                    expanded = false
                },
            )
        }
    }
}
```

## Parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `expanded` | `Boolean` |  | Whether the menu is showing. |
| `onDismissRequest` | `() -> Unit` |  | Called on outside click or Escape. |
| `offset` | `DpOffset` | `DpOffset(0.dp, 0.dp)` | Moves the popup relative to its anchor. |
| `DropdownMenuItem.leadingIcon` | `@Composable (() -> Unit)?` | `null` | Icon before the text. |

## Guidelines

Do:
- Group related items.
- Put destructive items last.

Don't:
- Do not nest menus more than one level.
- Do not use a menu for primary navigation.

## Accessibility

- Menu items are focusable and navigable by arrow keys. Focus moves to the first item on open.
- Exposed dropdowns announce the expanded state of the field.
- Keep labels short, and add a trailing shortcut hint only when one exists.

## Related components

- [Split button](https://m3e.ljzapps.app/docs/components/split-button.md)
- [Icon button](https://m3e.ljzapps.app/docs/components/icon-button.md)
- [Text field](https://m3e.ljzapps.app/docs/components/text-field.md)
