# Menu Primitive

Menu is a Starwind Runtime primitive in the composite-menu-overlay contract family.
Astro and React share one semantic component API. React coordinates reactive state through controlled and default props plus callbacks. Astro renders initial state and coordinates later changes through DOM events and Runtime methods. Raw HTML uses Runtime attributes, DOM events, and imperative methods.
## Anatomy
### Astro
Use the Astro primitive adapter to render Menu anatomy with the Runtime wiring included.
```astro
---
import { Menu } from "@starwind-ui/astro/menu";
---

<Menu.Root>
  <Menu.Trigger>Open menu</Menu.Trigger>
  <Menu.Positioner>
    <Menu.Popup>
      <Menu.Item>Edit</Menu.Item>
    </Menu.Popup>
  </Menu.Positioner>
</Menu.Root>
```

### React
Use the React primitive adapter when Menu state participates in React rendering.
```tsx
import { Menu } from "@starwind-ui/react/menu";

export function Example() {
  return (
    <Menu.Root>
      <Menu.Trigger>Open menu</Menu.Trigger>
      <Menu.Positioner>
        <Menu.Popup>
          <Menu.Item>Edit</Menu.Item>
        </Menu.Popup>
      </Menu.Positioner>
    </Menu.Root>
  );
}
```

### HTML
Render the Menu data-sw-* contract yourself, then initialize createMenu.
```html
<div data-sw-menu>
  <button data-sw-menu-trigger type="button" aria-haspopup="menu">Open menu</button>
  <div data-sw-menu-positioner>
    <div data-sw-menu-popup role="menu" tabindex="-1" hidden>
      <div data-sw-menu-item role="menuitem" tabindex="0">Edit</div>
    </div>
  </div>
</div>

<script type="module">
  import { createMenu } from "@starwind-ui/runtime/menu";

  const root = document.querySelector("[data-sw-menu]");
  if (root) {
    createMenu(root);
  }
</script>
```

### Vue
Use the Vue 3.5 beta adapter to render Menu anatomy.
```vue
<script setup lang="ts">
import Menu from "@starwind-ui/vue/menu";
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Popup>
        <Menu.Item>Edit</Menu.Item>
      </Menu.Popup>
    </Menu.Positioner>
  </Menu.Root>
</template>
```
## Menu Behavior
Menu uses a trigger, popup, and item parts to coordinate open state, keyboard navigation, floating placement, and item activation from one Runtime-owned root.
## Floating Behavior
| Fact | Value |
| --- | --- |
| Anchor part | trigger |
| Positioner part | positioner |
| Popup part | popup |
| Portal part | portal |
| Option props | side, align, sideOffset, avoidCollisions |
## API Reference
### Root
The main element that owns the Menu Runtime instance.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| open | `boolean` | - | control | Controls whether Menu is open. | **React:** Use open for controlled state and defaultOpen for default state, and onOpenChange for change proposals.<br>**Astro:** Use open or defaultOpen for initial state, listen for starwind:open-change, and call setOpen for later updates.<br>**Runtime / HTML:** Use data-default-open for initial state, listen for starwind:open-change, and call setOpen for later updates. |
| defaultOpen | `boolean` | false | control | Sets whether Menu starts open. | **React:** Use open for controlled state and defaultOpen for default state, and onOpenChange for change proposals.<br>**Astro:** Use open or defaultOpen for initial state, listen for starwind:open-change, and call setOpen for later updates.<br>**Runtime / HTML:** Use data-default-open for initial state, listen for starwind:open-change, and call setOpen for later updates. |
| disabled | `boolean` | false | option | Disables the Root part. | - |
| modal | `boolean` | false | option | Makes Menu behave as a modal overlay. | - |
| openOnHover | `boolean` | false | option | Configures the open on hover option for the Root part. | - |
| closeDelay | `number` | 200 | option | Sets how long Menu waits before closing. | - |
| onCloseComplete | `(open: boolean, details: MenuCloseCompleteDetails) => void` | - | callback | Runs after Menu has finished closing. | - |
| onOpenChange | `(open: boolean, details: MenuOpenChangeDetails) => void` | - | callback | Runs when Menu opens or closes. | **React:** Use open for controlled state and defaultOpen for default state, and onOpenChange for change proposals.<br>**Astro:** Use open or defaultOpen for initial state, listen for starwind:open-change, and call setOpen for later updates.<br>**Runtime / HTML:** Use data-default-open for initial state, listen for starwind:open-change, and call setOpen for later updates. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu` | runtime | - | Marks the Root part so Starwind Runtime can find it. |
| `data-default-open` | prop | - | Reflects the default open prop on the Root part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Root part. |
| `data-modal` | prop | - | Reflects the modal prop on the Root part. |
| `data-open-on-hover` | prop | - | Reflects the open on hover prop on the Root part. |
| `data-close-delay` | prop | - | Reflects the close delay prop on the Root part. |
| `data-state` | state | - | Reflects the current state on the Root part. |
#### State
| State | Value Type | Controlled Prop | Default Prop | Initial Attribute | Runtime Getter | Runtime Setter | Description | State Control Support |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| open | `boolean` | open | defaultOpen | `data-default-open` | `getOpen` | `setOpen` | Tracks whether Menu is open. | **React:** Use open for controlled state and defaultOpen for default state, and onOpenChange for change proposals.<br>**Astro:** Use open or defaultOpen for initial state, listen for starwind:open-change, and call setOpen for later updates.<br>**Runtime / HTML:** Use data-default-open for initial state, listen for starwind:open-change, and call setOpen for later updates. |
| checked | `boolean` | checked | defaultChecked | `data-default-checked` | - | - | Tracks whether Menu is checked. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| radioValue | `string` | value | defaultValue | `data-value` | - | - | Tracks the selected radio value for Menu. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
#### Events
| Event | Callback | DOM Event | Value | Details | Timing | Cancelable | Description | Cancellation Sequence |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| openChange | onOpenChange | starwind:open-change | open: `boolean` | MenuOpenChangeDetails | before-state-commit | Yes | Fires when Menu opens or closes. | 1. Check internal eligibility and intent.<br>2. Create one details object for the proposal.<br>3. Call the Runtime callback with the details object when the controller exposes one.<br>4. Dispatch the cancelable DOM event with the same details object, including when the callback canceled it.<br>5. Read details.isCanceled, including cancellation caused by preventDefault().<br>6. Apply the accepted state.<br>7. Notify Runtime subscribers and other accepted-only observers. |
| closeComplete | onCloseComplete | starwind:close-complete | open: `boolean` | MenuCloseCompleteDetails | after-state-commit | No | Fires after Menu has finished closing. | - |
#### Runtime Setters
| Method | Target | Options | Suppresses Emit | Description |
| --- | --- | --- | --- | --- |
| `setOpen` | state: open | emit: false | Yes | Opens or closes Menu from Runtime code. |
#### Refs
| Part | Public |
| --- | --- |
| root | Yes |
#### Context
| Name | Direction | Values |
| --- | --- | --- |
| menu-radio-group | provides | value, defaultValue, onValueChange |
| menu-radio-group | consumes | value |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu`, `data-default-open`, `data-disabled`, `data-modal`, `data-open-on-hover`, `data-close-delay`, `data-state` | The menu root needs open, disabled, modal, hover, delay, and initial state markers before hydration. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | No |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### Trigger
The control that opens, closes, or targets the Menu content.
| Fact | Value |
| --- | --- |
| Default element | `button` |
| Discovery hook | `data-sw-menu-trigger` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| asChild | `boolean` | false | rendering | Merges behavior onto your child element instead of rendering the default Trigger element. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-trigger` | runtime | - | Marks the Trigger part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Trigger part. |
#### Refs
| Part | Public |
| --- | --- |
| trigger | Yes |
#### asChild
| Part | Merged Props |
| --- | --- |
| trigger | aria, className, data, ref |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-trigger`, `type`, `aria-haspopup`, `aria-expanded`, `data-state` | Triggers need button semantics, menu affordances, and initial closed state before listeners attach. |

### Portal
Moves Menu overlay content to the document body when needed.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-portal` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-portal` | runtime | - | Marks the Portal part so Starwind Runtime can find it. |
| `data-container` | prop | - | Reflects the container prop on the Portal part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Portal part. |
| `data-sw-portal-placement` | constant | `runtime` | Identifies Portal metadata for styling and selectors. |
| `data-placement` | runtime | - | Marks the Portal part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| portal | Yes |

### Positioner
Positions the Menu content relative to its trigger.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-positioner` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| side | `"top" \| "right" \| "bottom" \| "left"` | "bottom" | option | Sets the preferred side for Menu content. | - |
| align | `"start" \| "center" \| "end"` | "start" | option | Sets how Menu content aligns to its trigger. | - |
| sideOffset | `number` | 4 | option | Sets the distance between Menu content and its trigger. | - |
| avoidCollisions | `boolean` | true | option | Allows Menu content to shift or flip to stay visible. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-positioner` | runtime | - | Marks the Positioner part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Positioner part. |
| `data-side` | prop | - | Reflects the side prop on the Positioner part. |
| `data-align` | prop | - | Reflects the align prop on the Positioner part. |
| `data-side-offset` | prop | - | Reflects the side offset prop on the Positioner part. |
| `data-avoid-collisions` | prop | - | Reflects the avoid collisions prop on the Positioner part. |
#### Refs
| Part | Public |
| --- | --- |
| positioner | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-positioner`, `data-state`, `data-side`, `data-align`, `data-side-offset`, `data-avoid-collisions` | The floating positioner carries initial placement hints used by the shared floating runtime. |

### Popup
The floating content container for Menu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-popup` |
| Role | `menu` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| side | `"top" \| "right" \| "bottom" \| "left"` | "bottom" | option | Sets the preferred side for Menu content. | - |
| align | `"start" \| "center" \| "end"` | "start" | option | Sets how Menu content aligns to its trigger. | - |
| sideOffset | `number` | 4 | option | Sets the distance between Menu content and its trigger. | - |
| avoidCollisions | `boolean` | true | option | Allows Menu content to shift or flip to stay visible. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-popup` | runtime | - | Marks the Popup part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Popup part. |
| `data-side` | prop | - | Reflects the side prop on the Popup part. |
| `data-align` | prop | - | Reflects the align prop on the Popup part. |
| `data-side-offset` | prop | - | Reflects the side offset prop on the Popup part. |
| `data-avoid-collisions` | prop | - | Reflects the avoid collisions prop on the Popup part. |
#### Refs
| Part | Public |
| --- | --- |
| popup | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-popup`, `role`, `tabindex`, `data-state`, `data-side`, `data-align`, `data-side-offset`, `data-avoid-collisions`, `hidden` | The popup starts hidden and closed with menu semantics and placement hints before runtime positioning. |
#### Presence
| Fact | Value |
| --- | --- |
| Initial hidden | Yes |
| Unmount policy | runtime-owned |
| Keep mounted prop | - |

### Item
An interactive item inside the Menu collection.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-item` |
| Role | `menuitem` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| disabled | `boolean` | false | option | Disables the Item part. | - |
| closeOnClick | `boolean` | true | option | Closes Menu after the item is clicked. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-item` | runtime | - | Marks the Item part so Starwind Runtime can find it. |
| `data-close-on-click` | prop | - | Reflects the close on click prop on the Item part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Item part. |
#### Refs
| Part | Public |
| --- | --- |
| item | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-item`, `role`, `tabindex`, `data-close-on-click`, `aria-disabled`, `data-disabled` | Regular menu items need menu item semantics, disabled markers, and optional close behavior markers before activation. |

### Link Item
A link-style item inside the Menu collection.
| Fact | Value |
| --- | --- |
| Default element | `a` |
| Discovery hook | `data-sw-menu-link-item` |
| Role | `menuitem` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| disabled | `boolean` | false | option | Disables the Link Item part. | - |
| closeOnClick | `boolean` | false | option | Closes Menu after the item is clicked. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-link-item` | runtime | - | Marks the Link Item part so Starwind Runtime can find it. |
| `data-close-on-click` | prop | - | Reflects the close on click prop on the Link Item part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Link Item part. |
#### Refs
| Part | Public |
| --- | --- |
| linkItem | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-link-item`, `role`, `tabindex`, `data-close-on-click`, `aria-disabled`, `data-disabled` | Link menu items need anchor semantics, disabled markers, and optional close behavior markers before activation. |

### Checkbox Item
A checkbox-style item inside the Menu collection.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-checkbox-item` |
| Role | `menuitemcheckbox` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| disabled | `boolean` | false | option | Disables the Checkbox Item part. | - |
| checked | `boolean` | - | control | Controls whether Menu is checked. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| defaultChecked | `boolean` | false | control | Sets whether Menu starts checked for uncontrolled usage. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| closeOnClick | `boolean` | false | option | Closes Menu after the item is clicked. | - |
| onCheckedChange | `(checked: boolean, details: MenuCheckedChangeDetails) => void` | - | callback | Runs when the Menu checked state changes. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-checkbox-item` | runtime | - | Marks the Checkbox Item part so Starwind Runtime can find it. |
| `data-default-checked` | state | - | Reflects the default checked state on the Checkbox Item part. |
| `data-close-on-click` | prop | - | Reflects the close on click prop on the Checkbox Item part. |
| `data-checked` | state | - | Reflects the checked state on the Checkbox Item part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Checkbox Item part. |
| `data-unchecked` | state | - | Reflects the unchecked state on the Checkbox Item part. |
#### State
| State | Value Type | Controlled Prop | Default Prop | Initial Attribute | Runtime Getter | Runtime Setter | Description | State Control Support |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| checked | `boolean` | checked | defaultChecked | `data-default-checked` | - | - | Tracks whether Menu is checked. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
#### Events
| Event | Callback | DOM Event | Value | Details | Timing | Cancelable | Description | Cancellation Sequence |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| checkedChange | onCheckedChange | starwind:checked-change | checked: `boolean` | MenuCheckedChangeDetails | before-state-commit | Yes | Fires when the checked state changes for Menu. | 1. Check internal eligibility and intent.<br>2. Create one details object for the proposal.<br>3. Call the Runtime callback with the details object when the controller exposes one.<br>4. Dispatch the cancelable DOM event with the same details object, including when the callback canceled it.<br>5. Read details.isCanceled, including cancellation caused by preventDefault().<br>6. Apply the accepted state.<br>7. Notify Runtime subscribers and other accepted-only observers. |
#### Refs
| Part | Public |
| --- | --- |
| checkboxItem | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-checkbox-item`, `data-default-checked`, `data-close-on-click`, `role`, `aria-checked`, `aria-disabled`, `data-checked`, `data-disabled`, `data-unchecked`, `tabindex` | Checkbox menu items need checked, disabled, and close behavior markers before item activation. |

### Checkbox Item Indicator
Shows the checked state for a Menu checkbox item.
| Fact | Value |
| --- | --- |
| Default element | `span` |
| Discovery hook | `data-sw-menu-checkbox-item-indicator` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-checkbox-item-indicator` | runtime | - | Marks the Checkbox Item Indicator part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Checkbox Item Indicator part. |
#### Refs
| Part | Public |
| --- | --- |
| checkboxItemIndicator | Yes |

### Radio Group
Groups related radio items inside Menu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-radio-group` |
| Role | `group` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| value | `string` | - | control | Controls the current Menu value. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
| defaultValue | `string` | - | control | Sets the initial Menu value for uncontrolled usage. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
| onValueChange | `(value: string, details: MenuValueChangeDetails) => void` | - | callback | Runs when the Menu value changes. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-radio-group` | runtime | - | Marks the Radio Group part so Starwind Runtime can find it. |
| `data-value` | state | - | Reflects the value state on the Radio Group part. |
#### State
| State | Value Type | Controlled Prop | Default Prop | Initial Attribute | Runtime Getter | Runtime Setter | Description | State Control Support |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| radioValue | `string` | value | defaultValue | `data-value` | - | - | Tracks the selected radio value for Menu. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
#### Events
| Event | Callback | DOM Event | Value | Details | Timing | Cancelable | Description | Cancellation Sequence |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| valueChange | onValueChange | starwind:value-change | value: `string` | MenuValueChangeDetails | before-state-commit | Yes | Fires when the value changes for Menu. | 1. Check internal eligibility and intent.<br>2. Create one details object for the proposal.<br>3. Call the Runtime callback with the details object when the controller exposes one.<br>4. Dispatch the cancelable DOM event with the same details object, including when the callback canceled it.<br>5. Read details.isCanceled, including cancellation caused by preventDefault().<br>6. Apply the accepted state.<br>7. Notify Runtime subscribers and other accepted-only observers. |
#### Refs
| Part | Public |
| --- | --- |
| radioGroup | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-radio-group`, `role`, `data-value` | Radio groups need a value marker before runtime normalizes descendant radio item state. |

### Radio Item
A radio-style item inside the Menu collection.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-radio-item` |
| Role | `menuitemradio` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| disabled | `boolean` | false | option | Disables the Radio Item part. | - |
| checked | `boolean` | - | control | Controls whether Menu is checked. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| defaultChecked | `boolean` | false | control | Sets whether Menu starts checked for uncontrolled usage. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| closeOnClick | `boolean` | false | option | Closes Menu after the item is clicked. | - |
| value | `string` | - | option | Controls the current Menu value. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-radio-item` | runtime | - | Marks the Radio Item part so Starwind Runtime can find it. |
| `data-value` | prop | - | Reflects the value prop on the Radio Item part. |
| `data-default-checked` | state | - | Reflects the default checked state on the Radio Item part. |
| `data-close-on-click` | prop | - | Reflects the close on click prop on the Radio Item part. |
| `data-checked` | state | - | Reflects the checked state on the Radio Item part. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Radio Item part. |
| `data-unchecked` | state | - | Reflects the unchecked state on the Radio Item part. |
#### State
| State | Value Type | Controlled Prop | Default Prop | Initial Attribute | Runtime Getter | Runtime Setter | Description | State Control Support |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| checked | `boolean` | checked | defaultChecked | `data-default-checked` | - | - | Tracks whether Menu is checked. | **React:** Use checked for controlled state and defaultChecked for default state, and onCheckedChange for change proposals.<br>**Astro:** Use checked or defaultChecked for initial state and listen for starwind:checked-change.<br>**Runtime / HTML:** Use data-default-checked for initial state and listen for starwind:checked-change. |
| radioValue | `string` | value | defaultValue | `data-value` | - | - | Tracks the selected radio value for Menu. | **React:** Use value for controlled state and defaultValue for default state, and onValueChange for change proposals.<br>**Astro:** Use value or defaultValue for initial state and listen for starwind:value-change.<br>**Runtime / HTML:** Use data-value for initial state and listen for starwind:value-change. |
#### Refs
| Part | Public |
| --- | --- |
| radioItem | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-radio-item`, `data-value`, `data-default-checked`, `data-close-on-click`, `role`, `aria-checked`, `aria-disabled`, `data-checked`, `data-disabled`, `data-unchecked`, `tabindex` | Radio menu items need value, checked, disabled, and close behavior markers before item activation. |

### Radio Item Indicator
Shows the selected state for a Menu radio item.
| Fact | Value |
| --- | --- |
| Default element | `span` |
| Discovery hook | `data-sw-menu-radio-item-indicator` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-radio-item-indicator` | runtime | - | Marks the Radio Item Indicator part so Starwind Runtime can find it. |
| `data-state` | state | - | Reflects the current state on the Radio Item Indicator part. |
#### Refs
| Part | Public |
| --- | --- |
| radioItemIndicator | Yes |

### Group
Groups related Menu items.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-group` |
| Role | `group` |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-group` | runtime | - | Marks the Group part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| group | Yes |

### Label
Text label associated with Menu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-label` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-label` | runtime | - | Marks the Label part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| label | Yes |

### Separator
Separates groups of Menu items.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-separator` |
| Role | `separator` |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-separator` | runtime | - | Marks the Separator part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| separator | Yes |

### Shortcut
Displays keyboard shortcut text for a Menu item.
| Fact | Value |
| --- | --- |
| Default element | `span` |
| Discovery hook | `data-sw-menu-shortcut` |
| Role | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-shortcut` | runtime | - | Marks the Shortcut part so Starwind Runtime can find it. |
#### Refs
| Part | Public |
| --- | --- |
| shortcut | Yes |

### Submenu Root
Owns a nested submenu inside Menu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-submenu-root` |
| Role | - |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| closeDelay | `number` | 200 | option | Sets how long Menu waits before closing. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-submenu-root` | runtime | - | Marks the Submenu Root part so Starwind Runtime can find it. |
| `data-close-delay` | prop | - | Reflects the close delay prop on the Submenu Root part. |
| `data-state` | state | - | Reflects the current state on the Submenu Root part. |
#### Refs
| Part | Public |
| --- | --- |
| submenuRoot | Yes |

### Submenu Trigger
Opens a nested submenu inside Menu.
| Fact | Value |
| --- | --- |
| Default element | `div` |
| Discovery hook | `data-sw-menu-submenu-trigger` |
| Role | `menuitem` |
#### Props
| Prop | Type | Default | Kind | Description | Framework Behavior |
| --- | --- | --- | --- | --- | --- |
| disabled | `boolean` | false | option | Disables the Submenu Trigger part. | - |
#### Data Attributes
| Attribute | Source | Value | Description |
| --- | --- | --- | --- |
| `data-sw-menu-submenu-trigger` | runtime | - | Marks the Submenu Trigger part so Starwind Runtime can find it. |
| `data-disabled` | prop | - | Reflects the disabled prop on the Submenu Trigger part. |
| `data-state` | state | - | Reflects the current state on the Submenu Trigger part. |
#### Refs
| Part | Public |
| --- | --- |
| submenuTrigger | Yes |
#### Initial Markup
| Attributes | Reason |
| --- | --- |
| `data-sw-menu-submenu-trigger`, `role`, `aria-haspopup`, `aria-expanded`, `aria-disabled`, `data-disabled`, `data-state`, `tabindex` | Submenu triggers need menu item semantics and closed disclosure state before nested menu listeners attach. |
## Runtime API
| Fact | Value |
| --- | --- |
| Factory | [`createMenu`](/docs/runtime/#create-menu) |
| Import | `@starwind-ui/runtime/menu` |
| Root part | root |
| Option props | closeDelay, defaultOpen, disabled, modal, onCloseComplete, onOpenChange, open, openOnHover |
| Option lifecycles | closeDelay: constructor-only, defaultOpen: constructor-only, disabled: constructor-only, modal: constructor-only, onCloseComplete: constructor-only, onOpenChange: constructor-only, open: setter-backed, openOnHover: constructor-only |
## Related Styled Components
| Component | Relationship |
| --- | --- |
| [Dropdown](/docs/components/dropdown/) | Renamed Primitive |
## Exports
| Group | Import | Exports |
| --- | --- | --- |
| Runtime | `@starwind-ui/runtime/menu` | `createMenu` |
| Astro Primitive | `@starwind-ui/astro/menu` | `Menu`, `MenuRoot`, `MenuTrigger`, `MenuPortal`, `MenuPositioner`, `MenuPopup`, `MenuItem`, `MenuLinkItem`, `MenuCheckboxItem`, `MenuCheckboxItemIndicator`, `MenuRadioGroup`, `MenuRadioItem`, `MenuRadioItemIndicator`, `MenuGroup`, `MenuLabel`, `MenuSeparator`, `MenuShortcut`, `MenuSubmenuRoot`, `MenuSubmenuTrigger` |
| React Primitive | `@starwind-ui/react/menu` | `Menu`, `MenuRoot`, `MenuTrigger`, `MenuPortal`, `MenuPositioner`, `MenuPopup`, `MenuItem`, `MenuLinkItem`, `MenuCheckboxItem`, `MenuCheckboxItemIndicator`, `MenuRadioGroup`, `MenuRadioItem`, `MenuRadioItemIndicator`, `MenuGroup`, `MenuLabel`, `MenuSeparator`, `MenuShortcut`, `MenuSubmenuRoot`, `MenuSubmenuTrigger` |
## Canonical Names
| Kind | Name |
| --- | --- |
| namespace | `Menu` |
| runtime-factory | `createMenu` |
| part | `Menu.Root` |
| part | `Menu.Trigger` |
| part | `Menu.Portal` |
| part | `Menu.Positioner` |
| part | `Menu.Popup` |
| part | `Menu.Item` |
| part | `Menu.LinkItem` |
| part | `Menu.CheckboxItem` |
| part | `Menu.CheckboxItemIndicator` |
| part | `Menu.RadioGroup` |
| part | `Menu.RadioItem` |
| part | `Menu.RadioItemIndicator` |
| part | `Menu.Group` |
| part | `Menu.Label` |
| part | `Menu.Separator` |
| part | `Menu.Shortcut` |
| part | `Menu.SubmenuRoot` |
| part | `Menu.SubmenuTrigger` |
## Changelog
### v1.1.1
- Removed obsolete private-release warnings from generated Vue adapters and normalized the resulting blank line in vendored Primitive indexes.
- Connected owned group headings to their groups with aria-labelledby so assistive technology can identify each group.
### v1.1.0
- Added portable Portal container and disabled controls, with deterministic framework and Runtime placement reporting for nested floating content.
### v1.0.0
- Promoted this Primitive's vendoring version to the stable 1.0.0 baseline. Its existing API and Runtime behavior carry forward from the previous release.
### v0.1.2
- Marked generated React Primitive files as client modules so vendored installs preserve client boundaries in React server frameworks.
- Kept generated React state-change callbacks and DOM events cancelable until the Runtime accepts the proposed state, then synchronized rendered state.
### v0.1.1
- Added opt-in modal background-scroll locking while the menu is open.
### v0.1.0
- Introduced action and link items, keyboard navigation, checked items, submenus, and floating placement.