Skip to content

Menubar Primitive

A menu that stays visible on the screen, often seen in desktop apps, offering easy access to a standard set of commands.

Installation

Install the component via your command line.

Terminal window
npx expo install @rn-primitives/menubar

Usage

import * as React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import Animated, { FadeIn } from 'react-native-reanimated';
import * as MenubarPrimitive from '@rn-primitives/menubar';
function Example() {
const [value, setValue] = React.useState<string | undefined>();
const [isSubOpen, setIsSubOpen] = React.useState(false);
const [isChecked, setIsChecked] = React.useState(false);
const [radio, setRadio] = React.useState('michael');
// TODO: handle closing menus when pressing/clicking outside of this Example component. Ex: when navigating to another screen
function closeSubs() {
setIsSubOpen(false);
}
function onValueChange(val: string | undefined) {
if (typeof val === 'string') {
setValue(val);
return;
}
closeSubs();
setValue(undefined);
}
return (
<>
{!!value && (
<MenubarPrimitive.Overlay
style={StyleSheet.absoluteFillObject}
/>
)}
<MenubarPrimitive.Root value={value} onValueChange={onValueChange}>
<MenubarPrimitive.Menu value='file'>
<MenubarPrimitive.Trigger onPress={closeSubs}>
<Text>File</Text>
</MenubarPrimitive.Trigger>
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content>
<MenubarPrimitive.Item>
<Text>New Tab</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>New Window</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item disabled>
<Text>New Incognito Window</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Sub open={isSubOpen} onOpenChange={setIsSubOpen}>
<MenubarPrimitive.SubTrigger>
<Text>Share</Text>
</MenubarPrimitive.SubTrigger>
<MenubarPrimitive.SubContent>
<Animated.View entering={FadeIn.duration(200)}>
<MenubarPrimitive.Item>
<Text>Email link</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>Messages</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>Notes</Text>
</MenubarPrimitive.Item>
</Animated.View>
</MenubarPrimitive.SubContent>
</MenubarPrimitive.Sub>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Print...</Text>
</MenubarPrimitive.Item>
</MenubarPrimitive.Content>
</MenubarPrimitive.Portal>
</MenubarPrimitive.Menu>
<MenubarPrimitive.Menu value='edit'>
<MenubarPrimitive.Trigger onPress={closeSubs}>
<Text>Edit</Text>
</MenubarPrimitive.Trigger>
<MenubarPrimitive.Content className='native:w-48'>
<MenubarPrimitive.Item>
<Text>Undo</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>Redo</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Cut</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>Copy</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item>
<Text>Paste</Text>
</MenubarPrimitive.Item>
</MenubarPrimitive.Content>
</MenubarPrimitive.Menu>
<MenubarPrimitive.Menu value='view'>
<MenubarPrimitive.Trigger onPress={closeSubs}>
<Text>View</Text>
</MenubarPrimitive.Trigger>
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content>
<MenubarPrimitive.CheckboxItem
checked={isChecked}
onCheckedChange={setIsChecked}
closeOnPress={false}
>
<Text>Always Show Bookmarks Bar</Text>
</MenubarPrimitive.CheckboxItem>
<MenubarPrimitive.Item>
<Text>Reload</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Item disabled>
<Text>Force Reload</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Toggle Fullscreen</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Hide Sidebar</Text>
</MenubarPrimitive.Item>
</MenubarPrimitive.Content>
</MenubarPrimitive.Portal>
</MenubarPrimitive.Menu>
<MenubarPrimitive.Menu value='profile'>
<MenubarPrimitive.Trigger onPress={closeSubs}>
<Text>Profiles</Text>
</MenubarPrimitive.Trigger>
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content>
<MenubarPrimitive.RadioGroup value={radio} onValueChange={setRadio}>
<MenubarPrimitive.RadioItem closeOnPress={false} value='andy'>
<Text>Andy</Text>
</MenubarPrimitive.RadioItem>
<MenubarPrimitive.RadioItem closeOnPress={false} value='michael'>
<Text>Michael</Text>
</MenubarPrimitive.RadioItem>
<MenubarPrimitive.RadioItem closeOnPress={false} value='creed'>
<Text>Creed</Text>
</MenubarPrimitive.RadioItem>
</MenubarRadioGroup>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Edit...</Text>
</MenubarPrimitive.Item>
<MenubarPrimitive.Separator />
<MenubarPrimitive.Item>
<Text>Add Profile...</Text>
</MenubarPrimitive.Item>
</MenubarPrimitive.Content>
</MenubarPrimitive.Portal>
</MenubarPrimitive.Menu>
</MenubarPrimitive.Root>
</>
);
}

Props

Root

Extends View props

PropTypeNote
value*boolean
onValueChange*(value: boolean) => void
asChildboolean(optional)

Extends View props

PropTypeNote
value*string
asChildboolean(optional)

Trigger

Extends Pressable props

PropTypeNote
asChildboolean(optional)

Portal

PropTypeNote
children*React.ReactNode
forceMounttrue | undefined(optional)
hostNamestringWeb Only (optional)
containerHTMLElement | null | undefinedWeb Only (optional)

Overlay

Extends Pressable props

PropTypeNote
asChildboolean(optional)
forceMounttrue | undefined;(optional)

Content

Extends View props

PropTypeNote
asChildboolean(optional)
forceMounttrue | undefined(optional)
alignOffsetnumber(optional)
insetsInsets(optional)
avoidCollisionsboolean(optional)
align’start’ | ‘center’ | ‘end’(optional)
side’top’ | ‘bottom’(optional)
sideOffsetnumber(optional)
disablePositioningStylebooleanNative Only (optional)
loopbooleanWeb Only (optional)
onCloseAutoFocus(event: Event) => voidWeb Only (optional)
onEscapeKeyDown(event: KeyboardEvent) => voidWeb Only (optional)
onPointerDownOutside(event: PointerDownOutsideEvent) => voidWeb Only (optional)
onFocusOutside(event: FocusOutsideEvent) => voidWeb Only (optional)
onInteractOutsidePointerDownOutsideEvent | FocusOutsideEventWeb Only (optional)
collisionBoundaryElement | null | Array<Element | null>Web Only (optional)
sticky’partial’ | ‘always’Web Only (optional)
hideWhenDetachedbooleanWeb Only (optional)

Group

Extends Text props

PropTypeNote
asChildboolean(optional)

Label

Extends Text props

PropTypeNote
asChildboolean(optional)

Item

Extends Pressable props

PropTypeNote
asChildboolean(optional)
textValueboolean(optional)
closeOnPressboolean(optional)

CheckboxItem

Extends Pressable props

PropTypeNote
checked*boolean
onCheckedChange*(value: boolean) => void
textValue*string
asChildboolean(optional)
closeOnPressbooleanNative Only_(optional)_

RadioGroup

Extends View props

PropTypeNote
value*boolean
onValueChange*(value: boolean) => void
asChildboolean(optional)

RadioItem

Extends Pressable props

PropTypeNote
value*boolean
onCheckedChange*(value: boolean) => void
asChildboolean(optional)
closeOnPressbooleanNative Only_(optional)_

ItemIndicator

Extends View props

PropTypeNote
asChildboolean(optional)
forceMounttrue /undefined

Separator

Extends View props

PropTypeNote
asChildboolean(optional)
decorativeboolean(optional)

Sub

Extends View props

PropTypeNote
asChildboolean(optional)
defaultOpenboolean(optional)
openboolean(optional)
onOpenChange(value: boolean) => void(optional)

SubTrigger

Extends Pressable props

PropTypeNote
textValuestring(optional)
asChildboolean(optional)

SubContent

Extends Pressable props

PropTypeNote
asChildboolean(optional)
forceMounttrue /undefined

useRootContext

Must be used within a Root component. It provides the following values from the dropdown menu: open, and onOpenChange.

useMenuContext

Must be used within a Menu component. It provides the following values from the dropdown menu: open, and onOpenChange.

useSubContext

Must be used within a Sub component. It provides the following values from the dropdown menu: open, and onOpenChange.