An accessible React menubar component that provides keyboard navigation, submenus, and customizable styling while maintaining semantic HTML structure and screen reader compatibility.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Essential components for creating the basic menubar structure and managing overall state, keyboard navigation, and menu visibility.
Root menubar container component that manages the overall menubar state and provides horizontal navigation between menu triggers.
/**
* Root menubar container with keyboard navigation and state management
* @param props - Menubar configuration props
* @returns JSX element representing the menubar
*/
function Menubar(props: MenubarProps): React.ReactElement;
interface MenubarProps extends React.ComponentPropsWithoutRef<'div'> {
/** Controlled value for which menu is currently open */
value?: string;
/** Default value for which menu is open on initial render */
defaultValue?: string;
/** Callback fired when the open menu changes */
onValueChange?: (value: string) => void;
/** Whether navigation should loop from last to first item (default: true) */
loop?: boolean;
/** Text direction for the menubar (inherits from DirectionProvider if not specified) */
dir?: 'ltr' | 'rtl';
}Usage Examples:
'use client';
import * as Menubar from "@radix-ui/react-menubar";
// Basic menubar
function BasicMenubar() {
return (
<Menubar.Root>
<Menubar.Menu>
<Menubar.Trigger>File</Menubar.Trigger>
{/* ... menu content */}
</Menubar.Menu>
<Menubar.Menu>
<Menubar.Trigger>Edit</Menubar.Trigger>
{/* ... menu content */}
</Menubar.Menu>
</Menubar.Root>
);
}
// Controlled menubar
function ControlledMenubar() {
const [activeMenu, setActiveMenu] = React.useState("");
return (
<Menubar.Root value={activeMenu} onValueChange={setActiveMenu}>
<Menubar.Menu value="file">
<Menubar.Trigger>File</Menubar.Trigger>
{/* ... menu content */}
</Menubar.Menu>
<Menubar.Menu value="edit">
<Menubar.Trigger>Edit</Menubar.Trigger>
{/* ... menu content */}
</Menubar.Menu>
</Menubar.Root>
);
}Individual menu within the menubar that contains triggers and content. Each menu represents a distinct dropdown section.
/**
* Individual menu container within the menubar
* @param props - Menu configuration props
* @returns JSX element representing the menu
*/
function MenubarMenu(props: MenubarMenuProps): React.ReactElement;
interface MenubarMenuProps {
/** Unique identifier for this menu (auto-generated if not provided) */
value?: string;
/** Child components (typically Trigger and Portal/Content) */
children?: React.ReactNode;
}Usage Examples:
// Basic menu with auto-generated value
<Menubar.Menu>
<Menubar.Trigger>File</Menubar.Trigger>
<Menubar.Portal>
<Menubar.Content>
<Menubar.Item>New</Menubar.Item>
</Menubar.Content>
</Menubar.Portal>
</Menubar.Menu>
// Menu with explicit value for controlled behavior
<Menubar.Menu value="file-menu">
<Menubar.Trigger>File</Menubar.Trigger>
{/* ... content */}
</Menubar.Menu>Button that triggers the opening of a menu, with comprehensive keyboard and mouse interaction handling.
/**
* Button that triggers menu opening with keyboard and mouse support
* @param props - Trigger button props
* @returns JSX element representing the trigger button
*/
function MenubarTrigger(props: MenubarTriggerProps): React.ReactElement;
interface MenubarTriggerProps extends React.ComponentPropsWithoutRef<'button'> {
/** All standard button props are supported */
}Usage Examples:
// Basic trigger
<Menubar.Trigger>File</Menubar.Trigger>
// Trigger with custom styling and event handlers
<Menubar.Trigger
className="menu-trigger"
onFocus={() => console.log("Trigger focused")}
>
Edit
</Menubar.Trigger>
// Disabled trigger
<Menubar.Trigger disabled>
Help
</Menubar.Trigger>Portal component for rendering menu content outside the normal DOM tree, typically used for proper positioning and z-index management.
/**
* Portal for rendering menu content outside normal DOM hierarchy
* @param props - Portal configuration props
* @returns Portal-rendered content
*/
function MenubarPortal(props: MenubarPortalProps): React.ReactElement;
interface MenubarPortalProps {
/** Target container for portal rendering (defaults to document.body) */
container?: HTMLElement;
/** Child components to render in the portal */
children?: React.ReactNode;
}Usage Examples:
// Basic portal usage
<Menubar.Portal>
<Menubar.Content>
<Menubar.Item>Menu Item</Menubar.Item>
</Menubar.Content>
</Menubar.Portal>
// Portal with custom container
<Menubar.Portal container={document.getElementById('modal-root')}>
<Menubar.Content>
<Menubar.Item>Menu Item</Menubar.Item>
</Menubar.Content>
</Menubar.Portal>Container for menu items with focus management, keyboard navigation, and positioning features.
/**
* Container for menu items with focus and keyboard management
* @param props - Content container props
* @returns JSX element representing the menu content
*/
function MenubarContent(props: MenubarContentProps): React.ReactElement;
interface MenubarContentProps extends React.ComponentPropsWithoutRef<'div'> {
/** Alignment relative to trigger (default: 'start') */
align?: 'start' | 'center' | 'end';
/** Side preference for positioning */
side?: 'top' | 'right' | 'bottom' | 'left';
/** Distance from trigger in pixels */
sideOffset?: number;
/** Alignment offset in pixels */
alignOffset?: number;
/** Whether content should avoid collisions with the boundary */
avoidCollisions?: boolean;
/** Element or area to constrain positioning within */
collisionBoundary?: Element | null | Array<Element | null>;
/** Padding from collision boundary in pixels */
collisionPadding?: number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>;
/** Whether content should stick to trigger when boundary is reached */
sticky?: 'partial' | 'always';
/** Callback fired when content is closed via auto-focus */
onCloseAutoFocus?: (event: Event) => void;
/** Callback fired when focus moves outside the content */
onFocusOutside?: (event: FocusOutsideEvent) => void;
/** Callback fired when interaction occurs outside the content */
onInteractOutside?: (event: InteractOutsideEvent) => void;
/** Callback fired when escape key is pressed */
onEscapeKeyDown?: (event: KeyboardEvent) => void;
/** Callback fired when pointer moves down outside the content */
onPointerDownOutside?: (event: PointerDownOutsideEvent) => void;
}Usage Examples:
// Basic content
<Menubar.Content>
<Menubar.Item>New File</Menubar.Item>
<Menubar.Item>Open</Menubar.Item>
<Menubar.Separator />
<Menubar.Item>Exit</Menubar.Item>
</Menubar.Content>
// Content with custom positioning
<Menubar.Content
align="center"
side="bottom"
sideOffset={5}
onCloseAutoFocus={(event) => {
// Custom focus handling
event.preventDefault();
}}
>
<Menubar.Item>Centered Menu Item</Menubar.Item>
</Menubar.Content>Key Implementation Details:
data-radix-menubar-content="" attribute--radix-menubar-content-transform-origin: Transform origin for animations--radix-menubar-content-available-width: Available width for content--radix-menubar-content-available-height: Available height for content--radix-menubar-trigger-width: Width of the triggering element--radix-menubar-trigger-height: Height of the triggering element// Element reference types
type MenubarElement = React.ComponentRef<'div'>;
type MenubarTriggerElement = React.ComponentRef<'button'>;
type MenubarContentElement = HTMLDivElement;
// Event types
interface FocusOutsideEvent {
target: HTMLElement;
preventDefault(): void;
}
interface InteractOutsideEvent {
target: HTMLElement;
preventDefault(): void;
}
interface PointerDownOutsideEvent {
target: HTMLElement;
preventDefault(): void;
}
// Direction type
type Direction = 'ltr' | 'rtl';
// Portal container type
type PortalContainer = HTMLElement | null;Install with Tessl CLI
npx tessl i tessl/npm-radix-ui--react-menubar