# Menu

A floating context menu with positioning, selection groups, and multiple presentation modes.

## Import

```tsx
import { Menu, SubMenu } from 'heroui-native';
```

## Anatomy

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover">
      <Menu.Close />
      <Menu.Label>...</Menu.Label>
      <Menu.Group>
        <Menu.Item>
          <Menu.ItemIndicator />
          <Menu.ItemTitle>...</Menu.ItemTitle>
          <Menu.ItemDescription>...</Menu.ItemDescription>
        </Menu.Item>
      </Menu.Group>
      <SubMenu>
        <SubMenu.Trigger textValue="...">
          <SubMenu.TriggerIndicator />
          ...
        </SubMenu.Trigger>
        <SubMenu.Content>
          <Menu.Item>...</Menu.Item>
          <Menu.Item>...</Menu.Item>
        </SubMenu.Content>
      </SubMenu>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

- **Menu**: Main container that manages open/close state, positioning, and provides context to child components.
- **Menu.Trigger**: Clickable element that toggles the menu visibility.
- **Menu.Portal**: Renders menu content in a portal layer above other content.
- **Menu.Overlay**: Optional background overlay to capture outside clicks and close the menu.
- **Menu.Content**: Container for menu content with two presentation modes: floating popover with positioning and collision detection, or bottom sheet modal.
- **Menu.Close**: Close button that dismisses the menu when pressed.
- **Menu.Label**: Non-interactive section heading text within the menu.
- **Menu.Group**: Groups menu items with optional selection state (none, single, multiple).
- **Menu.Item**: Pressable menu item with animated press feedback. Standalone or within a Group for selection.
- **Menu.ItemTitle**: Primary label text for a menu item.
- **Menu.ItemDescription**: Secondary description text for a menu item.
- **Menu.ItemIndicator**: Visual selection indicator (checkmark or dot) for a menu item.
- **SubMenu**: Root container that manages the expand/collapse state and provides animation context to children.
- **SubMenu.Background**: Absolute-fill layer that paints the sub-menu surface while it is open. Rendered automatically; replaceable via the `background` prop on `SubMenu`.
- **SubMenu.Trigger**: Pressable row that toggles the submenu open/closed. Styled like a regular menu item.
- **SubMenu.TriggerIndicator**: Animated chevron icon (default: chevron-right) that rotates when the submenu opens/closes. Place inside `SubMenu.Trigger`.
- **SubMenu.Content**: Absolutely positioned container that animates its height when the submenu opens/closes. Place `Menu.Item` elements inside.

## Usage

### Basic Usage

The Menu component uses compound parts to create a floating context menu.

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={220}>
      <Menu.Item>
        <Menu.ItemTitle>View Profile</Menu.ItemTitle>
      </Menu.Item>
      <Menu.Item>
        <Menu.ItemTitle>Settings</Menu.ItemTitle>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### With Item Descriptions

Add secondary description text to menu items alongside titles.

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={260}>
      <Menu.Item className="items-start">
        <View className="flex-1">
          <Menu.ItemTitle>New file</Menu.ItemTitle>
          <Menu.ItemDescription>Create a new file</Menu.ItemDescription>
        </View>
      </Menu.Item>
      <Menu.Item className="items-start">
        <View className="flex-1">
          <Menu.ItemTitle>Copy link</Menu.ItemTitle>
          <Menu.ItemDescription>Copy the file link</Menu.ItemDescription>
        </View>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### Single Selection

Use `Menu.Group` with `selectionMode="single"` to allow one selected item at a time.

```tsx
const [theme, setTheme] = useState<Set<MenuKey>>(() => new Set(['system']));

<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={180}>
      <Menu.Label>Appearance</Menu.Label>
      <Menu.Group
        selectionMode="single"
        selectedKeys={theme}
        onSelectionChange={setTheme}
      >
        <Menu.Item id="light">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>Light</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="dark">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>Dark</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="system">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>System</Menu.ItemTitle>
        </Menu.Item>
      </Menu.Group>
    </Menu.Content>
  </Menu.Portal>
</Menu>;
```

### Multiple Selection

Use `selectionMode="multiple"` to allow selecting multiple items simultaneously.

```tsx
const [textStyles, setTextStyles] = useState<Set<MenuKey>>(
  () => new Set(['bold', 'italic'])
);

<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={250}>
      <Menu.Label>Text Style</Menu.Label>
      <Menu.Group
        selectionMode="multiple"
        selectedKeys={textStyles}
        onSelectionChange={setTextStyles}
      >
        <Menu.Item id="bold">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>Bold</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="italic">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>Italic</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="underline">
          <Menu.ItemIndicator />
          <Menu.ItemTitle>Underline</Menu.ItemTitle>
        </Menu.Item>
      </Menu.Group>
    </Menu.Content>
  </Menu.Portal>
</Menu>;
```

### With SubMenu

Nest a `SubMenu` inside `Menu.Content` to reveal additional items on press.

```tsx
<Menu>
  <Menu.Trigger asChild>
    <Button variant="secondary">Editor Menu</Button>
  </Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={240}>
      <Menu.Item>
        <Menu.ItemTitle>New Space</Menu.ItemTitle>
      </Menu.Item>
      <SubMenu>
        <SubMenu.Trigger textValue="Focus">
          <SubMenu.TriggerIndicator />
          <Text className="flex-1 text-base font-medium text-foreground">
            Focus
          </Text>
        </SubMenu.Trigger>
        <SubMenu.Content>
          <Menu.Item>
            <Menu.ItemTitle>Zen Mode</Menu.ItemTitle>
          </Menu.Item>
          <Menu.Item>
            <Menu.ItemTitle>Reader Mode</Menu.ItemTitle>
          </Menu.Item>
          <Menu.Item>
            <Menu.ItemTitle>Lock Tab</Menu.ItemTitle>
          </Menu.Item>
        </SubMenu.Content>
      </SubMenu>
      <Menu.Item>
        <Menu.ItemTitle>Heading 1</Menu.ItemTitle>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### Danger Variant

Use `variant="danger"` on a menu item for destructive actions.

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={220}>
      <Menu.Item>
        <Menu.ItemTitle>Edit</Menu.ItemTitle>
      </Menu.Item>
      <Menu.Item variant="danger">
        <Menu.ItemTitle>Delete</Menu.ItemTitle>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### Placements

Control where the menu appears relative to the trigger.

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" placement="right" width={200}>
      <Menu.Item>
        <Menu.ItemTitle>Option A</Menu.ItemTitle>
      </Menu.Item>
      <Menu.Item>
        <Menu.ItemTitle>Option B</Menu.ItemTitle>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### BottomSheet Presentation

Use `presentation="bottom-sheet"` to display menu content as a bottom sheet modal.

```tsx
<Menu presentation="bottom-sheet">
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="bottom-sheet">
      <Menu.Item>
        <Menu.ItemTitle>Option A</Menu.ItemTitle>
      </Menu.Item>
      <Menu.Item>
        <Menu.ItemTitle>Option B</Menu.ItemTitle>
      </Menu.Item>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

### Dot Indicator

Use `variant="dot"` on `Menu.ItemIndicator` to show a filled circle instead of a checkmark.

```tsx
<Menu>
  <Menu.Trigger>...</Menu.Trigger>
  <Menu.Portal>
    <Menu.Overlay />
    <Menu.Content presentation="popover" width={180}>
      <Menu.Group
        selectionMode="single"
        selectedKeys={alignment}
        onSelectionChange={setAlignment}
      >
        <Menu.Item id="left">
          <Menu.ItemIndicator variant="dot" />
          <Menu.ItemTitle>Left</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="center">
          <Menu.ItemIndicator variant="dot" />
          <Menu.ItemTitle>Center</Menu.ItemTitle>
        </Menu.Item>
        <Menu.Item id="right">
          <Menu.ItemIndicator variant="dot" />
          <Menu.ItemTitle>Right</Menu.ItemTitle>
        </Menu.Item>
      </Menu.Group>
    </Menu.Content>
  </Menu.Portal>
</Menu>
```

## Example

```tsx
import type { MenuKey } from 'heroui-native';
import { Button, Menu, Separator } from 'heroui-native';
import { useState } from 'react';
import { Text, View } from 'react-native';

export default function MenuExample() {
  const [textStyles, setTextStyles] = useState<Set<MenuKey>>(
    () => new Set(['bold', 'italic'])
  );
  const [alignment, setAlignment] = useState<Set<MenuKey>>(
    () => new Set(['left'])
  );

  return (
    <Menu>
      <Menu.Trigger asChild>
        <Button variant="secondary">Styles</Button>
      </Menu.Trigger>
      <Menu.Portal>
        <Menu.Overlay />
        <Menu.Content presentation="popover" width={250}>
          <Menu.Label className="mb-1">Text Style</Menu.Label>
          <Menu.Group
            selectionMode="multiple"
            selectedKeys={textStyles}
            onSelectionChange={setTextStyles}
          >
            <Menu.Item id="bold">
              <Menu.ItemIndicator />
              <Menu.ItemTitle>Bold</Menu.ItemTitle>
              <Text className="text-sm text-muted">⌘ B</Text>
            </Menu.Item>
            <Menu.Item id="italic">
              <Menu.ItemIndicator />
              <Menu.ItemTitle>Italic</Menu.ItemTitle>
              <Text className="text-sm text-muted">⌘ I</Text>
            </Menu.Item>
            <Menu.Item id="underline">
              <Menu.ItemIndicator />
              <Menu.ItemTitle>Underline</Menu.ItemTitle>
              <Text className="text-sm text-muted">⌘ U</Text>
            </Menu.Item>
          </Menu.Group>
          <Separator className="mx-2 my-2 opacity-75" />
          <Menu.Label className="mb-1">Text Alignment</Menu.Label>
          <Menu.Group
            selectionMode="single"
            selectedKeys={alignment}
            onSelectionChange={setAlignment}
          >
            <Menu.Item id="left">
              <Menu.ItemIndicator variant="dot" />
              <Menu.ItemTitle>Left</Menu.ItemTitle>
            </Menu.Item>
            <Menu.Item id="center">
              <Menu.ItemIndicator variant="dot" />
              <Menu.ItemTitle>Center</Menu.ItemTitle>
            </Menu.Item>
            <Menu.Item id="right">
              <Menu.ItemIndicator variant="dot" />
              <Menu.ItemTitle>Right</Menu.ItemTitle>
            </Menu.Item>
          </Menu.Group>
        </Menu.Content>
      </Menu.Portal>
    </Menu>
  );
}
```

You can find more examples in the [GitHub repository](<https://github.com/heroui-inc/heroui-native/blob/main/example/src/app/(home)/components/menu.tsx>).

## API Reference

### Menu

| prop            | type                          | default     | description                                        |
| --------------- | ----------------------------- | ----------- | -------------------------------------------------- |
| `children`      | `React.ReactNode`             | -           | The content of the menu                            |
| `presentation`  | `'popover' \| 'bottom-sheet'` | `'popover'` | Presentation mode for the menu content             |
| `isOpen`        | `boolean`                     | -           | Controlled open state of the menu                  |
| `isDefaultOpen` | `boolean`                     | -           | Open state when initially rendered (uncontrolled)  |
| `isDisabled`    | `boolean`                     | -           | Whether the menu is disabled                       |
| `animation`     | `MenuRootAnimation`           | -           | Animation configuration for menu root              |
| `onOpenChange`  | `(open: boolean) => void`     | -           | Callback fired when the menu open state changes    |
| `...ViewProps`  | `ViewProps`                   | -           | All standard React Native View props are supported |

#### MenuRootAnimation

Animation configuration for menu root component. Can be:

- `"disable-all"`: Disable all animations including children
- `true` or `undefined`: Use default animations

### Menu.Trigger

| prop                | type              | default | description                                             |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children`          | `React.ReactNode` | -       | The trigger element content                             |
| `className`         | `string`          | -       | Additional CSS class for the trigger                    |
| `isDisabled`        | `boolean`         | `false` | Whether the trigger is disabled                         |
| `asChild`           | `boolean`         | -       | Render as child element using Slot pattern              |
| `...PressableProps` | `PressableProps`  | -       | All standard React Native Pressable props are supported |

### Menu.Portal

| prop                                         | type              | default | description                                                                                                                                                                                                      |
| -------------------------------------------- | ----------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children`                                   | `React.ReactNode` | -       | The portal content                                                                                                                                                                                               |
| `className`                                  | `string`          | -       | Additional CSS class for the portal container                                                                                                                                                                    |
| `disableFullWindowOverlay`                   | `boolean`         | `false` | Use a regular View instead of FullWindowOverlay on iOS                                                                                                                                                           |
| `unstable_accessibilityContainerViewIsModal` | `boolean`         | `false` | Controls whether VoiceOver treats the overlay window as a modal container. When `true`, VoiceOver is restricted to elements inside the overlay. iOS only. Unstable: may change with react-native-screens updates |
| `hostName`                                   | `string`          | -       | Optional name of the host element for the portal                                                                                                                                                                 |
| `forceMount`                                 | `boolean`         | -       | Force mount the portal regardless of open state                                                                                                                                                                  |

### Menu.Overlay

| prop                    | type                   | default | description                                                  |
| ----------------------- | ---------------------- | ------- | ------------------------------------------------------------ |
| `className`             | `string`               | -       | Additional CSS class for the overlay                         |
| `closeOnPress`          | `boolean`              | `true`  | Whether to close the menu when the overlay is pressed        |
| `animation`             | `MenuOverlayAnimation` | -       | Animation configuration for overlay                          |
| `isAnimatedStyleActive` | `boolean`              | `true`  | Whether animated styles (react-native-reanimated) are active |
| `forceMount`            | `boolean`              | -       | Force mount the overlay regardless of open state             |
| `...PressableProps`     | `PressableProps`       | -       | All standard React Native Pressable props are supported      |

#### MenuOverlayAnimation

Animation configuration for menu overlay component. Can be:

- `false` or `"disabled"`: Disable all animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration

| prop                     | type                    | default                 | description                                     |
| ------------------------ | ----------------------- | ----------------------- | ----------------------------------------------- |
| `state`                  | `'disabled' \| boolean` | -                       | Disable animations while customizing properties |
| `opacity.entering.value` | `EntryOrExitLayoutType` | `FadeIn.duration(200)`  | Custom entering animation for overlay           |
| `opacity.exiting.value`  | `EntryOrExitLayoutType` | `FadeOut.duration(150)` | Custom exiting animation for overlay            |

### Menu.Content (Popover)

Props when `presentation="popover"`.

| prop              | type                                             | default         | description                                        |
| ----------------- | ------------------------------------------------ | --------------- | -------------------------------------------------- |
| `children`        | `React.ReactNode`                                | -               | The menu content                                   |
| `presentation`    | `'popover'`                                      | -               | Presentation mode (must match Menu root)           |
| `placement`       | `'top' \| 'bottom' \| 'left' \| 'right'`         | `'bottom'`      | Where the menu appears relative to the trigger     |
| `align`           | `'start' \| 'center' \| 'end'`                   | `'center'`      | Alignment of the menu relative to the trigger      |
| `avoidCollisions` | `boolean`                                        | `true`          | Whether to reposition to avoid screen edges        |
| `offset`          | `number`                                         | `9`             | Distance from the trigger element in pixels        |
| `alignOffset`     | `number`                                         | `0`             | Offset along the alignment axis in pixels          |
| `width`           | `'content-fit' \| 'trigger' \| 'full' \| number` | `'content-fit'` | Content width sizing strategy                      |
| `className`       | `string`                                         | -               | Additional CSS class for the content container     |
| `animation`       | `MenuContentAnimation`                           | -               | Animation configuration for content                |
| `...ViewProps`    | `ViewProps`                                      | -               | All standard React Native View props are supported |

#### MenuContentAnimation

Animation configuration for menu popover content component. Can be:

- `false` or `"disabled"`: Disable all animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration

| prop             | type                    | default                         | description                                     |
| ---------------- | ----------------------- | ------------------------------- | ----------------------------------------------- |
| `state`          | `'disabled' \| boolean` | -                               | Disable animations while customizing properties |
| `entering.value` | `EntryOrExitLayoutType` | Scale + fade entering animation | Custom entering animation for content           |
| `exiting.value`  | `EntryOrExitLayoutType` | Scale + fade exiting animation  | Custom exiting animation for content            |

### Menu.Content (BottomSheet)

Props when `presentation="bottom-sheet"`. Extends `@gorhom/bottom-sheet` BottomSheet props.

| prop                        | type                                     | default | description                                          |
| --------------------------- | ---------------------------------------- | ------- | ---------------------------------------------------- |
| `children`                  | `React.ReactNode`                        | -       | The bottom sheet content                             |
| `presentation`              | `'bottom-sheet'`                         | -       | Presentation mode (must match Menu root)             |
| `className`                 | `string`                                 | -       | Additional CSS class for the bottom sheet            |
| `backgroundClassName`       | `string`                                 | -       | Additional CSS class for the background              |
| `handleIndicatorClassName`  | `string`                                 | -       | Additional CSS class for the handle indicator        |
| `contentContainerClassName` | `string`                                 | -       | Additional CSS class for the content container       |
| `contentContainerProps`     | `Omit<BottomSheetViewProps, 'children'>` | -       | Props for the content container                      |
| `animation`                 | `AnimationDisabled`                      | -       | Set to `false` or `"disabled"` to disable animations |
| `...BottomSheetProps`       | `Partial<BottomSheetProps>`              | -       | All `@gorhom/bottom-sheet` props are supported       |

### Menu.Close

Extends `CloseButtonProps`. Automatically closes the menu when pressed.

| prop             | type                   | default | description                          |
| ---------------- | ---------------------- | ------- | ------------------------------------ |
| `iconProps`      | `CloseButtonIconProps` | -       | Props for customizing the close icon |
| `...ButtonProps` | `ButtonRootProps`      | -       | All Button root props are supported  |

### Menu.Group

| prop                  | type                               | default  | description                                        |
| --------------------- | ---------------------------------- | -------- | -------------------------------------------------- |
| `children`            | `React.ReactNode`                  | -        | The group content (Menu.Item elements)             |
| `selectionMode`       | `'none' \| 'single' \| 'multiple'` | `'none'` | The type of selection allowed in the group         |
| `selectedKeys`        | `Iterable<MenuKey>`                | -        | Currently selected keys (controlled)               |
| `defaultSelectedKeys` | `Iterable<MenuKey>`                | -        | Initially selected keys (uncontrolled)             |
| `isDisabled`          | `boolean`                          | `false`  | Whether the entire group is disabled               |
| `disabledKeys`        | `Iterable<MenuKey>`                | -        | Keys of items that should be disabled              |
| `shouldCloseOnSelect` | `boolean`                          | -        | Whether selecting an item should close the menu    |
| `className`           | `string`                           | -        | Additional CSS class for the group container       |
| `onSelectionChange`   | `(keys: Set<MenuKey>) => void`     | -        | Callback fired when the selection changes          |
| `...ViewProps`        | `ViewProps`                        | -        | All standard React Native View props are supported |

### Menu.Label

| prop           | type              | default | description                                        |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children`     | `React.ReactNode` | -       | The label text content                             |
| `className`    | `string`          | -       | Additional CSS class for the label                 |
| `...TextProps` | `TextProps`       | -       | All standard React Native Text props are supported |

### Menu.Item

| prop                    | type                                                             | default     | description                                                  |
| ----------------------- | ---------------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
| `children`              | `React.ReactNode \| ((props: MenuItemRenderProps) => ReactNode)` | -           | Child elements or a render function                          |
| `id`                    | `MenuKey`                                                        | -           | Unique identifier, required when inside a Menu.Group         |
| `variant`               | `'default' \| 'danger'`                                          | `'default'` | Visual variant of the menu item                              |
| `isDisabled`            | `boolean`                                                        | `false`     | Whether the item is disabled                                 |
| `isSelected`            | `boolean`                                                        | -           | Controlled selected state for standalone items               |
| `shouldCloseOnSelect`   | `boolean`                                                        | `true`      | Whether pressing this item should close the menu             |
| `className`             | `string`                                                         | -           | Additional CSS class for the item                            |
| `animation`             | `MenuItemAnimation`                                              | -           | Animation configuration for press feedback                   |
| `isAnimatedStyleActive` | `boolean`                                                        | `true`      | Whether animated styles (react-native-reanimated) are active |
| `onSelectedChange`      | `(selected: boolean) => void`                                    | -           | Callback when standalone item's selected state changes       |
| `...PressableProps`     | `PressableProps`                                                 | -           | All standard React Native Pressable props are supported      |

#### MenuItemRenderProps

Props passed to the render function when `children` is a function.

| prop         | type                    | description                             |
| ------------ | ----------------------- | --------------------------------------- |
| `isSelected` | `boolean`               | Whether this item is currently selected |
| `isDisabled` | `boolean`               | Whether the item is disabled            |
| `isPressed`  | `SharedValue<boolean>`  | Whether the item is currently pressed   |
| `variant`    | `'default' \| 'danger'` | Visual variant of the item              |

#### MenuItemAnimation

Animation configuration for menu item press feedback. Can be:

- `false` or `"disabled"`: Disable all item animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration

| prop                           | type               | default                    | description                              |
| ------------------------------ | ------------------ | -------------------------- | ---------------------------------------- |
| `scale.value`                  | `number`           | `0.98`                     | Scale value when pressed                 |
| `scale.timingConfig`           | `WithTimingConfig` | `{ duration: 150 }`        | Spring animation configuration for scale |
| `backgroundColor.value`        | `string`           | `useThemeColor('default')` | Background color shown while pressed     |
| `backgroundColor.timingConfig` | `WithTimingConfig` | `{ duration: 150 }`        | Animation timing for background color    |

### Menu.ItemTitle

| prop           | type              | default | description                                        |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children`     | `React.ReactNode` | -       | The title text content                             |
| `className`    | `string`          | -       | Additional CSS class for the item title            |
| `...TextProps` | `TextProps`       | -       | All standard React Native Text props are supported |

### Menu.ItemDescription

| prop           | type              | default | description                                        |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children`     | `React.ReactNode` | -       | The description text content                       |
| `className`    | `string`          | -       | Additional CSS class for the item description      |
| `...TextProps` | `TextProps`       | -       | All standard React Native Text props are supported |

### Menu.ItemIndicator

| prop           | type                         | default       | description                                            |
| -------------- | ---------------------------- | ------------- | ------------------------------------------------------ |
| `children`     | `React.ReactNode`            | -             | Custom indicator content, defaults to checkmark or dot |
| `variant`      | `'checkmark' \| 'dot'`       | `'checkmark'` | Visual variant of the indicator                        |
| `iconProps`    | `MenuItemIndicatorIconProps` | -             | Icon configuration (checkmark variant)                 |
| `forceMount`   | `boolean`                    | `true`        | Force mount the indicator regardless of selected state |
| `className`    | `string`                     | -             | Additional CSS class for the item indicator            |
| `...ViewProps` | `ViewProps`                  | -             | All standard React Native View props are supported     |

#### MenuItemIndicatorIconProps

| prop    | type     | default | description                                    |
| ------- | -------- | ------- | ---------------------------------------------- |
| `size`  | `number` | `16`    | Size of the indicator icon (8 for dot variant) |
| `color` | `string` | `muted` | Color of the indicator icon                    |

### SubMenu

| prop            | type                      | default | description                                              |
| --------------- | ------------------------- | ------- | -------------------------------------------------------- |
| `children`      | `React.ReactNode`         | -       | The sub-menu content (trigger, content, and other items) |
| `isOpen`        | `boolean`                 | -       | Controlled open state of the sub-menu                    |
| `isDefaultOpen` | `boolean`                 | -       | Open state when initially rendered (uncontrolled)        |
| `isDisabled`    | `boolean`                 | `false` | Whether the sub-menu is disabled                         |
| `className`     | `string`                  | -       | Additional CSS class for the root container              |
| `background`    | `React.ReactNode`         | -       | Background layer behind the open sub-menu surface        |
| `animation`     | `SubMenuRootAnimation`    | -       | Animation configuration for the sub-menu                 |
| `onOpenChange`  | `(open: boolean) => void` | -       | Callback fired when the sub-menu open state changes      |
| `...ViewProps`  | `ViewProps`               | -       | All standard React Native View props are supported       |

##### SubMenuRootAnimation

Animation configuration for the SubMenu root component. Can be:

- `"disable-all"`: Disable all animations including children
- `false` or `"disabled"`: Disable only root animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration

| prop                            | type                    | default                                     | description                                     |
| ------------------------------- | ----------------------- | ------------------------------------------- | ----------------------------------------------- |
| `state`                         | `'disabled' \| boolean` | -                                           | Disable animations while customizing properties |
| `rootContent.marginHorizontal`  | `number`                | `-16`                                       | Margin horizontal when sub-menu is open         |
| `rootContent.marginVertical`    | `number`                | `-16`                                       | Margin vertical when sub-menu is open           |
| `rootContent.paddingHorizontal` | `number`                | `6`                                         | Padding horizontal when sub-menu is open        |
| `rootContent.paddingTop`        | `number`                | `12`                                        | Padding top when sub-menu is open               |
| `rootContent.springConfig`      | `WithSpringConfig`      | `{ damping: 100, stiffness: 950, mass: 3 }` | Spring configuration for expand/collapse        |
| `background.exiting`            | `EntryOrExitLayoutType` | `FadeOut.duration(200)`                     | Exit animation for the background layer         |

#### SubMenu.Background

Absolute-fill layer rendered behind the open sub-menu surface. It paints the sub-menu surface coat (`--color-overlay`) and, with no children, the layer chosen by the active library theme — a `GlassView` blur under the `glass` theme, nothing under the default theme.

The surface is mounted only while the sub-menu is open (and faded out on close) so the collapsed trigger row keeps the menu surface it sits on. That matters under themes with a translucent `--color-overlay`, where a permanent coat would tint the trigger row twice and make it read differently from its sibling `Menu.Item`s.

Replace it via the `background` prop on `SubMenu` — a custom node takes over the mount and exit transition as well, so wrap content in `SubMenu.Background` to keep the absolute-fill, surface coat, and clipping:

```tsx
<SubMenu
  background={
    <SubMenu.Background>
      <LinearGradient
        colors={['#ffffff22', '#ffffff05']}
        style={StyleSheet.absoluteFill}
      />
    </SubMenu.Background>
  }
>
  ...
</SubMenu>
```

Passing `background={null}` removes the layer entirely, leaving the open sub-menu transparent over the menu content.

| prop           | type              | default | description                                        |
| -------------- | ----------------- | ------- | -------------------------------------------------- |
| `children`     | `React.ReactNode` | -       | Custom content replacing the theme default layer   |
| `className`    | `string`          | -       | Additional CSS class for the background container  |
| `...ViewProps` | `ViewProps`       | -       | All standard React Native View props are supported |

#### SubMenu.Trigger

| prop                | type              | default | description                                             |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children`          | `React.ReactNode` | -       | The trigger content (title, icons, indicator, etc.)     |
| `textValue`         | `string`          | -       | Accessible text value announced by screen readers       |
| `className`         | `string`          | -       | Additional CSS class for the trigger                    |
| `isDisabled`        | `boolean`         | `false` | Whether the trigger is disabled                         |
| `asChild`           | `boolean`         | -       | Render as child element using Slot pattern              |
| `...PressableProps` | `PressableProps`  | -       | All standard React Native Pressable props are supported |

#### SubMenu.TriggerIndicator

Animated indicator icon that rotates when the submenu opens/closes. Defaults to a chevron-right icon.

| prop                    | type                               | default | description                                                  |
| ----------------------- | ---------------------------------- | ------- | ------------------------------------------------------------ |
| `children`              | `React.ReactNode`                  | -       | Custom indicator content (replaces default chevron)          |
| `className`             | `string`                           | -       | Additional CSS class for the indicator                       |
| `iconProps`             | `SubMenuTriggerIndicatorIconProps` | -       | Icon configuration for the default chevron                   |
| `animation`             | `SubMenuTriggerIndicatorAnimation` | -       | Animation configuration for indicator rotation               |
| `isAnimatedStyleActive` | `boolean`                          | `true`  | Whether animated styles (react-native-reanimated) are active |
| `...ViewProps`          | `ViewProps`                        | -       | All standard React Native View props are supported           |

##### SubMenuTriggerIndicatorIconProps

| prop    | type     | default | description                 |
| ------- | -------- | ------- | --------------------------- |
| `size`  | `number` | `16`    | Size of the indicator icon  |
| `color` | `string` | `muted` | Color of the indicator icon |

##### SubMenuTriggerIndicatorAnimation

Animation configuration for the trigger indicator rotation. Can be:

- `false` or `"disabled"`: Disable all animations
- `true` or `undefined`: Use default animations
- `object`: Custom animation configuration

| prop                    | type                    | default                                      | description                                      |
| ----------------------- | ----------------------- | -------------------------------------------- | ------------------------------------------------ |
| `state`                 | `'disabled' \| boolean` | -                                            | Disable animations while customizing properties  |
| `rotation.value`        | `[number, number]`      | `[0, 90]`                                    | Rotation values [collapsed, expanded] in degrees |
| `rotation.springConfig` | `WithSpringConfig`      | `{ damping: 140, stiffness: 1000, mass: 4 }` | Spring configuration for rotation                |

#### SubMenu.Content

| prop                | type              | default | description                                             |
| ------------------- | ----------------- | ------- | ------------------------------------------------------- |
| `children`          | `React.ReactNode` | -       | The submenu items (Menu.Item, Menu.Group, etc.)         |
| `className`         | `string`          | -       | Additional CSS class for the content container          |
| `...PressableProps` | `PressableProps`  | -       | All standard React Native Pressable props are supported |

## Hooks

### useMenu

Hook to access the menu root context. Must be used within a `Menu` component.

```tsx
import { useMenu } from 'heroui-native';

const { isOpen, onOpenChange, presentation, isDisabled } = useMenu();
```

#### Returns

| property       | type                          | description                             |
| -------------- | ----------------------------- | --------------------------------------- |
| `isOpen`       | `boolean`                     | Whether the menu is currently open      |
| `onOpenChange` | `(open: boolean) => void`     | Callback to change the open state       |
| `presentation` | `'popover' \| 'bottom-sheet'` | Current presentation mode               |
| `isDisabled`   | `boolean \| undefined`        | Whether the menu is disabled            |
| `nativeID`     | `string`                      | Unique identifier for the menu instance |

### useMenuItem

Hook to access the menu item context. Must be used within a `Menu.Item` component.

```tsx
import { useMenuItem } from 'heroui-native';

const { id, isSelected, isDisabled, variant } = useMenuItem();
```

#### Returns

| property     | type                    | description                            |
| ------------ | ----------------------- | -------------------------------------- |
| `id`         | `MenuKey \| undefined`  | Item identifier                        |
| `isSelected` | `boolean`               | Whether the item is currently selected |
| `isDisabled` | `boolean`               | Whether the item is disabled           |
| `variant`    | `'default' \| 'danger'` | Visual variant of the item             |

### useMenuAnimation

Hook to access the menu animation context. Must be used within a `Menu` component.

```tsx
import { useMenuAnimation } from 'heroui-native';

const { progress, isDragging } = useMenuAnimation();
```

#### Returns

| property     | type                   | description                                               |
| ------------ | ---------------------- | --------------------------------------------------------- |
| `progress`   | `SharedValue<number>`  | Animation progress shared value (0=idle, 1=open, 2=close) |
| `isDragging` | `SharedValue<boolean>` | Whether the bottom sheet is currently being dragged       |

### useSubMenu

Hook to access the sub-menu context. Must be used within a `SubMenu` component.

```tsx
import { useSubMenu } from 'heroui-native';

const { isOpen, onOpenChange, isDisabled } = useSubMenu();
```

#### Returns

| property       | type                      | description                                 |
| -------------- | ------------------------- | ------------------------------------------- |
| `isOpen`       | `boolean`                 | Whether the sub-menu is currently open      |
| `onOpenChange` | `(open: boolean) => void` | Callback to change the open state           |
| `isDisabled`   | `boolean`                 | Whether the sub-menu is disabled            |
| `nativeID`     | `string`                  | Unique identifier for the sub-menu instance |

## Special Notes

### Element Inspector (iOS)

Menu uses FullWindowOverlay on iOS. To enable the React Native element inspector during development, set `disableFullWindowOverlay={true}` on `Menu.Portal`. Tradeoff: the menu will not appear above native modals when disabled.

### Native Modal (iOS)

When a `Menu` is opened inside a screen presented as a native modal (`presentation: 'modal' | 'formSheet' | 'pageSheet'`), the menu content may render shifted upward. In the new architecture (Fabric), `react-native-screens` marks `RNSModalScreen` as a Fabric root, so the trigger's position is reported relative to the modal's origin while `FullWindowOverlay` (where the menu is mounted) is anchored to the iOS application window. Compensate by adding `safeAreaInsets.top` to `offset`:

```tsx
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const insets = useSafeAreaInsets();

<Menu.Content presentation="popover" offset={insets.top}>
  ...
</Menu.Content>;
```

See `example/src/app/(home)/components/menu-in-modal-screen.tsx` for a complete example.
