macbetter

Menus and pickers

Menu Bar

Every command in your app, in menus along the top of the screen.

"use client"

import { MenuBar, MenuBarContent, MenuBarTrigger } from "macbetter/menu-bar"
import {
  Menu,
  MenuCheckboxItem,
  MenuItem,
  MenuRadioGroup,
  MenuRadioItem,
  MenuSeparator,
  MenuSub,
  MenuSubContent,
  MenuSubTrigger,
} from "macbetter/menu"

export default function Example() {
  return (
    <MenuBar aria-label="Notes">
      <Menu>
        <MenuBarTrigger app>Notes</MenuBarTrigger>
        <MenuBarContent>
          <MenuItem value="about">About Notes</MenuItem>
          <MenuSeparator />
          <MenuItem value="settings" shortcut="mod+,">
            Settings…
          </MenuItem>
          <MenuSeparator />
          <MenuItem value="hide" shortcut="mod+h">
            Hide Notes
          </MenuItem>
          <MenuItem value="quit" shortcut="mod+q">
            Quit Notes
          </MenuItem>
        </MenuBarContent>
      </Menu>
      <Menu>
        <MenuBarTrigger>File</MenuBarTrigger>
        <MenuBarContent>
          <MenuItem value="new-note" shortcut="mod+n">
            New Note
          </MenuItem>
          <MenuItem value="new-folder" shortcut="mod+shift+n">
            New Folder
          </MenuItem>
          <MenuSub>
            <MenuSubTrigger>Open Recent</MenuSubTrigger>
            <MenuSubContent>
              <MenuItem value="recent-trip">Weekend trip</MenuItem>
              <MenuItem value="recent-groceries">Groceries</MenuItem>
              <MenuItem value="recent-ideas">Gift ideas</MenuItem>
            </MenuSubContent>
          </MenuSub>
          <MenuSeparator />
          <MenuItem value="close" shortcut="mod+w">
            Close
          </MenuItem>
          <MenuItem value="print" shortcut="mod+p">
            Print…
          </MenuItem>
        </MenuBarContent>
      </Menu>
      <Menu>
        <MenuBarTrigger>Edit</MenuBarTrigger>
        <MenuBarContent>
          <MenuItem value="undo" shortcut="mod+z">
            Undo Typing
          </MenuItem>
          <MenuItem value="redo" shortcut="mod+shift+z" disabled>
            Redo
          </MenuItem>
          <MenuSeparator />
          <MenuItem value="cut" shortcut="mod+x">
            Cut
          </MenuItem>
          <MenuItem value="copy" shortcut="mod+c">
            Copy
          </MenuItem>
          <MenuItem value="paste" shortcut="mod+v">
            Paste
          </MenuItem>
          <MenuItem value="select-all" shortcut="mod+a">
            Select All
          </MenuItem>
        </MenuBarContent>
      </Menu>
      <Menu>
        <MenuBarTrigger>View</MenuBarTrigger>
        <MenuBarContent>
          <MenuRadioGroup name="layout" defaultValue="list">
            <MenuRadioItem value="list">as List</MenuRadioItem>
            <MenuRadioItem value="gallery">as Gallery</MenuRadioItem>
          </MenuRadioGroup>
          <MenuSeparator />
          <MenuCheckboxItem value="folders" defaultChecked>
            Show Folders
          </MenuCheckboxItem>
          <MenuCheckboxItem value="note-count">Show Note Count</MenuCheckboxItem>
        </MenuBarContent>
      </Menu>
      <Menu>
        <MenuBarTrigger>Window</MenuBarTrigger>
        <MenuBarContent>
          <MenuItem value="minimize" shortcut="mod+m">
            Minimize
          </MenuItem>
          <MenuItem value="zoom">Zoom</MenuItem>
        </MenuBarContent>
      </Menu>
      <Menu>
        <MenuBarTrigger>Help</MenuBarTrigger>
        <MenuBarContent>
          <MenuItem value="help">Notes Help</MenuItem>
        </MenuBarContent>
      </Menu>
    </MenuBar>
  )
}

When to use it

The menu bar is where people look for any command on the Mac, so every action your app offers should be reachable from it. Use it for a full desktop app; a single page or a phone layout doesn't need one.

  • Start with the app menu, titled with the app's name, then File, Edit, View, any app-specific menus, Window and Help, in that order.
  • Keep the menus and their items stable. Disable an item that doesn't apply instead of hiding it.
  • Give every frequently used command a keyboard shortcut and follow the standard ones (⌘N, ⌘S, ⌘Z).

Usage

import { MenuBar, MenuBarContent, MenuBarTrigger } from "macbetter/menu-bar"
import { Menu, MenuItem } from "macbetter/menu"

Put one Menu per title inside MenuBar, with a MenuBarTrigger and a MenuBarContent. Mark the app menu's trigger app to set it in bold. The items are the Menu parts.

Platform behavior

  • macOS: a 24-point translucent bar with 13-point titles. The open title gets a rounded fill, and its menu hangs straight from the bar without scaling. With one menu open, moving the pointer across the bar opens each menu in turn.
  • iPadOS: the menu bar people pull down from the top of the screen, with taller titles, capsule highlights and iPad-sized menus.
  • iOS: there's no menu bar. Put the commands in toolbars and pull-down buttons.

Accessibility

The bar is one tab stop with role="menubar"; name it with aria-label. Left and Right move between titles, Down or Enter opens a menu, Left and Right in an open menu move to the next one, and Escape closes it and returns focus to its title.

API

PropTypeDefaultDescription
MenuBarorientation, loop, disabled, modal—The bar. Takes the ui-sdk Menubar's props.
MenuBarTriggerapp?: boolean—A title. `app` sets the application menu's title in bold.
MenuBarContentsideOffset3A menu that hangs from the bar.
data-openbar and title—On the bar while any menu is open, and on the open title.
--mb-menu-bar-heightlength24px · 44pxMac · iPad.
--mb-menu-bar-radiuslength4px · capsuleThe open title's fill.