Menubar
Horizontal bar of menus, each opening a dropdown of items.
FileEdit
New Document
Open…
Save
Web preview — components render natively on iOS & Android
import { Menubar, MenubarMenu, MenubarItem } from "@/components/ui/menubar";
export function MyScreen() {
return (
<Menubar>
<MenubarMenu trigger="File">
<MenubarItem onPress={() => {}}>New File</MenubarItem>
<MenubarItem onPress={() => {}}>Open…</MenubarItem>
<MenubarItem onPress={() => {}}>Save</MenubarItem>
</MenubarMenu>
<MenubarMenu trigger="Edit">
<MenubarItem onPress={() => {}}>Undo</MenubarItem>
<MenubarItem onPress={() => {}}>Redo</MenubarItem>
</MenubarMenu>
</Menubar>
);
}Installation
npx @aniui/cli add menubarUsage
import { Menubar, MenubarMenu, MenubarItem } from "@/components/ui/menubar";
export function MyScreen() {
return (
<Menubar>
<MenubarMenu trigger="File">
<MenubarItem onPress={() => {}}>New File</MenubarItem>
<MenubarItem onPress={() => {}}>Save</MenubarItem>
</MenubarMenu>
<MenubarMenu trigger="Edit">
<MenubarItem onPress={() => {}}>Undo</MenubarItem>
</MenubarMenu>
</Menubar>
);
}Props
Menubar
PropTypeDefault
childrenReact.ReactNode—classNamestring—Also accepts all View props from React Native.
MenubarMenu
PropTypeDefault
triggerReact.ReactNode—childrenReact.ReactNode—classNamestring—MenubarItem
PropTypeDefault
onPress() => void—childrenReact.ReactNode—classNamestring—Also accepts all Pressable props from React Native.
Accessibility
MenubarusesaccessibilityRole="menubar".- Triggers and items use
accessibilityRole="menuitem"; the open panel usesaccessibilityRole="menu".
Source
components/ui/menubar.tsx
import React, { createContext, useContext, useRef, useState } from "react";
import { View, Text, Pressable, Modal } from "react-native";
import { cn } from "@/lib/utils";
const MenubarCloseContext = createContext<(() => void) | null>(null);
export interface MenubarProps extends React.ComponentPropsWithoutRef<typeof View> {
className?: string;
children?: React.ReactNode;
}
export function Menubar({ className, ...props }: MenubarProps) {
return (
<View
className={cn("h-12 flex-row items-center gap-1 rounded-md border border-border bg-card px-1", className)}
accessibilityRole="menubar"
{...props}
/>
);
}
export interface MenubarMenuProps {
trigger: React.ReactNode;
className?: string;
children?: React.ReactNode;
}
export function MenubarMenu({ trigger, className, children }: MenubarMenuProps) {
const [open, setOpen] = useState(false);
const [anchor, setAnchor] = useState({ x: 0, y: 0 });
const ref = useRef<View>(null);
const openMenu = () => {
// Open immediately so the menu never depends on a measure callback firing;
// measureInWindow (not measure) then refines the anchor inside the Modal.
setOpen(true);
ref.current?.measureInWindow((x, y, _w, h) => {
setAnchor({ x, y: y + h + 4 });
});
};
return (
<>
<Pressable
ref={ref}
onPress={openMenu}
accessibilityRole="menuitem"
accessible
className="min-h-12 min-w-12 justify-center rounded-sm px-3"
>
{typeof trigger === "string" ? <Text className="text-sm font-medium text-foreground">{trigger}</Text> : trigger}
</Pressable>
<Modal visible={open} transparent animationType="fade" onRequestClose={() => setOpen(false)}>
<Pressable style={{ flex: 1 }} onPress={() => setOpen(false)} accessible={false}>
<View
className={cn("min-w-40 rounded-md border border-border bg-card p-1", className)}
style={{ position: "absolute", left: anchor.x, top: anchor.y }}
accessibilityRole="menu"
>
<MenubarCloseContext.Provider value={() => setOpen(false)}>{children}</MenubarCloseContext.Provider>
</View>
</Pressable>
</Modal>
</>
);
}
export interface MenubarItemProps extends React.ComponentPropsWithoutRef<typeof Pressable> {
className?: string;
children?: React.ReactNode;
}
export function MenubarItem({ className, children, onPress, ...props }: MenubarItemProps) {
const close = useContext(MenubarCloseContext);
return (
<Pressable
accessibilityRole="menuitem"
accessible
onPress={(e) => {
onPress?.(e);
close?.();
}}
className={cn("min-h-12 min-w-12 justify-center rounded-sm px-2", className)}
{...props}
>
{typeof children === "string" ? <Text className="text-sm text-foreground">{children}</Text> : children}
</Pressable>
);
}

