---
title: "Menu"
description: "A contextual action menu for a row or record. It is non-modal, navigated with arrows, and supports actions, links and separators."
kind: component
id: C-033
registry: "menu"
docs: "https://koten.codehive.com.co/components/menu"
markdown: "https://koten.codehive.com.co/md/components/menu.md"
install: "npx shadcn@latest add https://koten.codehive.com.co/r/menu.json"
language: en
---

# Menu · メニュー

> Component C-033 in the Koten UI catalog.

A contextual action menu for a row or record. It is non-modal, navigated with arrows, and supports actions, links and separators.

> Japanese labels in this page are documentation metadata. Keep the consumer UI in the product's language and do not add Japanese decoration unless the user asks (R-031).

## Install

Install `koten-theme` first when the project does not have Koten tokens yet. Use the runner of your project.

```bash
# Node
npx shadcn@latest add https://koten.codehive.com.co/r/menu.json

# Bun
bunx shadcn@latest add https://koten.codehive.com.co/r/menu.json
```

## Files

- `@/components/ui/menu.tsx`
- `@/lib/koten/cn.ts`
- `@/lib/koten/format.ts`
- `@/lib/koten/intl.ts`
- `@/lib/koten/labels.ts`
- `@/lib/koten/provider.tsx`

## Requirements

- **portal** — Portaled popup: The popup mounts in BaseMenu.Portal and is placed by Positioner, so the table around it does not clip it.

## Reference

- Upstream primitive: https://base-ui.com/react/components/menu

## Examples

### Row actions

Four actions with a separator before the destructive one; the trigger keeps its own styling.

```tsx
<Menu
  trigger={<Button variant="outline">Actions</Button>}
  items={[
    { label: "View details", onSelect: () => openOrder() },
    { label: "Edit", onSelect: () => editOrder() },
    { label: "Duplicate", onSelect: () => duplicateOrder() },
    { label: "Delete", onSelect: () => removeOrder(), separatorBefore: true },
  ]}
/>
```

## Props

| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| `trigger` | `ReactElement` | `—` | The element that opens the menu; it receives aria-haspopup and the expanded state. |
| `items` | `readonly MenuItem[]` | `—` | Each item accepts label, onSelect, href, disabled and separatorBefore. |
| `modal` | `boolean` | `false` | Koten keeps it non-modal so it blocks neither scroll nor clicks outside the popup. |
| `className` | `string` | `—` | Applied to the popup, not to the trigger. |

## Accessibility

- The trigger announces aria-haspopup and aria-expanded; the popup uses the menu role.
- Arrows move focus, Enter runs the item, Escape closes and returns focus to the trigger.
- Separators are not focus stops and disabled items are announced as disabled.
- Being non-modal, opening it neither traps focus nor blocks the rest of the page.

## Sources

- Catalog page: https://koten.codehive.com.co/components/menu
- Markdown: https://koten.codehive.com.co/md/components/menu.md
- Repository: https://github.com/codehive-colombia/koten
