Skip to content

Menubar

Group app commands in familiar menus such as File, Edit and View.

import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use a menubar for the command surface of a document-style app: an editor, a design tool, an IDE in the browser, where people expect menus they can scrub across. For one menu behind a button, use a Dropdown Menu. For site navigation between pages, use a Navigation Menu.

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarSeparator,
  MenubarShortcut,
  MenubarTrigger,
} from '@youj/react'

export function EditorMenubar() {
  return (
    <Menubar>
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New document <MenubarShortcut>⌘N</MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem>Print…</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Undo</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}

Each MenubarMenu is a menu whose trigger sits in the bar. Its content takes everything a Dropdown Menu does, under Menubar names: MenubarItem (with variant="danger" and inset), MenubarCheckboxItem, MenubarRadioGroup and MenubarRadioItem, MenubarLabel, MenubarGroup, MenubarSeparator, MenubarShortcut, and submenus with MenubarSub, MenubarSubTrigger and MenubarSubContent. The API matches shadcn/ui's Menubar, so its examples paste in.

Reference

Propscontainer, presentation (2)

Props

Menubar adds no props of its own. They pass through to MenubarPrimitive.Props.

Base UI's Menubar takes orientation ('horizontal' by default, which sets the arrow keys), loopFocus (default true), modal and disabled.

MenubarContent props
PropType
containerHTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null>

Where the portal renders. Default: document.body.

–
presentationOverlayPresentation
'auto''sheet''popover'

auto (the default) is a popover under a pointer and a bottom sheet on touch; force either one.

–

It defaults to align="start" with the first row under the trigger's label, sideOffset={6}, and takes Dropdown Menu's side, align, alignOffset, collisionPadding and container.

MotionOpen-menu mark, mark appears and leaves, menu opens… · reduced motion

Motion

Motion tokens
MomentTokens
Open-menu markglides to the trigger whose menu opened
spring.smooth

0.36s, bounce 0

0.36s, bounce 0
Mark appears and leaveswhen the first menu opens and the last one closes
duration.fastease.standard

140ms · cubic-bezier(0.2, 0, 0, 1)

140mscubic-bezier(0.2, 0, 0, 1)
Menu opensyj-pop from the trigger, as Dropdown Menu
duration.fastease.enter

140ms · cubic-bezier(0.16, 1, 0.3, 1)

140mscubic-bezier(0.16, 1, 0.3, 1)
Row highlightone highlight glides between rows, as Dropdown Menu
spring.smooth

0.36s, bounce 0

0.36s, bounce 0

Reduced motion

The mark jumps to the open trigger, menus appear without the pop, and the row highlight jumps.

Reduced motion

The mark moves straight to the open trigger, menus open in place and rows highlight without gliding. Which menu is open reads exactly the same.

AccessibilityKeyboard, ARIA, focus

Accessibility

  • The bar is a menubar and each trigger a menuitem with aria-haspopup and aria-expanded. It's a single tab stop; ← and → move between triggers and wrap, mirrored in right-to-left layouts.
  • ↓, Enter or Space opens a menu and focuses its first row; inside, the arrow keys, typeahead, Home and End work as in any menu. Escape closes it and returns focus to its trigger.
  • The gliding mark is decorative (aria-hidden). In forced-colors mode the open trigger gets an outline instead.