apps/docs/content/docs/en/native/components/(collections)/menu.mdx
<NativeVideoPlayerView target="auto" srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/menu-docs-light.mp4" srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/menu-docs-dark.mp4" />
import { Menu, SubMenu } from 'heroui-native';
<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>
background prop on SubMenu.SubMenu.Trigger.Menu.Item elements inside.The Menu component uses compound parts to create a floating context menu.
<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>
Add secondary description text to menu items alongside titles.
<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>
Use Menu.Group with selectionMode="single" to allow one selected item at a time.
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>;
Use selectionMode="multiple" to allow selecting multiple items simultaneously.
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>;
Nest a SubMenu inside Menu.Content to reveal additional items on press.
<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>
Use variant="danger" on a menu item for destructive actions.
<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>
Control where the menu appears relative to the trigger.
<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>
Use presentation="bottom-sheet" to display menu content as a bottom sheet modal.
<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>
Use variant="dot" on Menu.ItemIndicator to show a filled circle instead of a checkmark.
<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>
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.
| 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 |
Animation configuration for menu root component. Can be:
"disable-all": Disable all animations including childrentrue or undefined: Use default animations| 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 |
| 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 |
| 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 |
Animation configuration for menu overlay component. Can be:
false or "disabled": Disable all animationstrue or undefined: Use default animationsobject: 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 |
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 |
Animation configuration for menu popover content component. Can be:
false or "disabled": Disable all animationstrue or undefined: Use default animationsobject: 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 |
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 |
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 |
| 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 |
| 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 |
| 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 |
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 |
Animation configuration for menu item press feedback. Can be:
false or "disabled": Disable all item animationstrue or undefined: Use default animationsobject: 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 |
| 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 |
| 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 |
| 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 |
| prop | type | default | description |
|---|---|---|---|
size | number | 16 | Size of the indicator icon (8 for dot variant) |
color | string | muted | Color of the indicator icon |
| 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 |
Animation configuration for the SubMenu root component. Can be:
"disable-all": Disable all animations including childrenfalse or "disabled": Disable only root animationstrue or undefined: Use default animationsobject: 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 |
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.Items.
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:
<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 |
| 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 |
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 |
| prop | type | default | description |
|---|---|---|---|
size | number | 14 | Size of the indicator icon |
color | string | muted | Color of the indicator icon |
Animation configuration for the trigger indicator rotation. Can be:
false or "disabled": Disable all animationstrue or undefined: Use default animationsobject: 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 |
| 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 |
Hook to access the menu root context. Must be used within a Menu component.
import { useMenu } from 'heroui-native';
const { isOpen, onOpenChange, presentation, isDisabled } = useMenu();
| 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 |
Hook to access the menu item context. Must be used within a Menu.Item component.
import { useMenuItem } from 'heroui-native';
const { id, isSelected, isDisabled, variant } = useMenuItem();
| 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 |
Hook to access the menu animation context. Must be used within a Menu component.
import { useMenuAnimation } from 'heroui-native';
const { progress, isDragging } = useMenuAnimation();
| 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 |
Hook to access the sub-menu context. Must be used within a SubMenu component.
import { useSubMenu } from 'heroui-native';
const { isOpen, onOpenChange, isDisabled } = useSubMenu();
| 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 |
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.
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:
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const insets = useSafeAreaInsets();
<Menu.Content presentation="popover" offset={insets.top}>
...
</Menu.Content>;