# Menubar

A desktop-style row of menus (File, Edit, View) in Candor's theme (Base UI). Arrow keys move between the menus and along each menu's items, Right and Left open and close submenus, Escape closes the open menu and returns focus to its trigger. An item that can't be used stays in the menu, marked and explained, instead of vanishing.

- Registry name: `menubar` (`@candor/menubar`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/menubar

## Install

```bash
npx candor-ui add menubar
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/menubar`.
It brings in: layer, motion, tokens, utils.
npm packages: @base-ui/react@^1.9.0, lucide-react@^1.67.0.

## Example

```tsx
"use client"

import * as React from "react"
import {
  Menubar,
  MenubarCheckboxItem,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarRadioGroup,
  MenubarRadioItem,
  MenubarSeparator,
  MenubarShortcut,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from "@/components/candor/ui/menubar"

export default function Example() {
  const [grid, setGrid] = React.useState(true)
  const [density, setDensity] = React.useState("comfortable")
  return (
    <Menubar>
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New report <MenubarShortcut>⌘N</MenubarShortcut>
          </MenubarItem>
          <MenubarSub>
            <MenubarSubTrigger>Export</MenubarSubTrigger>
            <MenubarSubContent>
              <MenubarItem>CSV</MenubarItem>
              <MenubarItem>PDF</MenubarItem>
              <MenubarItem locked="Needs the data add-on.">Parquet</MenubarItem>
            </MenubarSubContent>
          </MenubarSub>
          <MenubarSeparator />
          <MenubarItem variant="destructive">Delete report</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>View</MenubarTrigger>
        <MenubarContent>
          <MenubarCheckboxItem checked={grid} onCheckedChange={setGrid}>
            Show gridlines
          </MenubarCheckboxItem>
          <MenubarSeparator />
          <MenubarRadioGroup value={density} onValueChange={setDensity}>
            <MenubarRadioItem value="compact">Compact</MenubarRadioItem>
            <MenubarRadioItem value="comfortable">Comfortable</MenubarRadioItem>
          </MenubarRadioGroup>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}
```

## <Menubar>

Props:

- `className?: string | undefined`

Also takes the props of `Omit<MenubarPrimitive.Props, "className">`.

## <MenubarCheckboxItem>

A `Menubar` item that turns a setting on or off and shows a tick while it is on.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.
- `onSelect?: OnSelect | undefined`: Called when the person chooses the item; `event.preventDefault()` keeps the menu open.
- `closeOnClick?: boolean | undefined` (default `true`): Closes the menu once the person ticks the item, as Candor's menus did on Radix. Defaults to true.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarContent>

The popup of a `Menubar`, holding its items.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.

Also takes the props of `Omit<T, "className" | "style">`, `Pick<MenuPrimitive.Positioner.Props, "side" | "sideOffset" | "align" | "alignOffset" | "collisionPadding">`.

## <MenubarGroup>

A set of related items in a `Menubar`, read as one group by screen readers.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarItem>

One action in a `Menubar`; it runs when chosen and closes the menu.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.
- `inset?: boolean | undefined`: Indents the item to line up with items that have an icon.
- `variant?: "default" | "destructive" | undefined` (default `"default"`): destructive colours the item for actions that remove or can't be undone.
- `onSelect?: OnSelect | undefined`: Called when the person chooses the item; `event.preventDefault()` keeps the menu open.
- `locked?: string | null | undefined`: Why the item can't be used right now. When set, it stays in the menu and in the arrow-key order, marked `aria-disabled`, choosing it does nothing and keeps the menu open, and the reason is printed beside it and read to screen readers. `null` or left out: unlocked.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarLabel>

A non-interactive heading over a group of items in a `Menubar`.

Props:

- `inset?: boolean | undefined`: Indents the label to line up with items that have an icon.

Also takes the props of `React.ComponentProps<"div">`.

## <MenubarMenu>

One menu of a `Menubar`, with its `MenubarTrigger` and `MenubarContent`.

No props.

Also takes the props of `MenuPrimitive.Root.Props`.

## <MenubarPortal>

Renders a `Menubar`'s popup at the end of the page so nothing clips it; the parts do this themselves, so reach for it only to place a popup yourself.

No props.

Also takes the props of `Omit<MenuPrimitive.Portal.Props, "container">`.

## <MenubarRadioGroup>

A set of `MenubarRadioItem`s of which one is chosen.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarRadioItem>

One choice in a `MenubarRadioGroup`, ticked while it is the chosen one.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.
- `onSelect?: OnSelect | undefined`: Called when the person chooses the item; `event.preventDefault()` keeps the menu open.
- `closeOnClick?: boolean | undefined` (default `true`): Closes the menu once the person ticks the item, as Candor's menus did on Radix. Defaults to true.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarSeparator>

A line between two groups of items in a `Menubar`.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarShortcut>

The keys shown at the end of an item that run the same action from elsewhere.

No props.

Also takes the props of `React.ComponentProps<"span">`.

## <MenubarSub>

A nested menu inside a `Menubar`; its `MenubarSubTrigger` opens its `MenubarSubContent`.

No props.

Also takes the props of `MenuPrimitive.SubmenuRoot.Props`.

## <MenubarSubContent>

The popup of a nested menu in a `Menubar`.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.

Also takes the props of `Omit<T, "className" | "style">`, `Pick<MenuPrimitive.Positioner.Props, "side" | "sideOffset" | "align" | "alignOffset" | "collisionPadding">`.

## <MenubarSubTrigger>

The item in a `Menubar` that opens a nested menu, marked with an arrow.

Props:

- `className?: string | undefined`: Classes for the part, merged with Candor's.
- `style?: React.CSSProperties | undefined`: Inline styles for the part, merged over its motion chain.
- `inset?: boolean | undefined`: Indents the trigger to line up with items that have an icon.

Also takes the props of `Omit<T, "className" | "style">`.

## <MenubarTrigger>

The name in a `Menubar` that opens one of its menus.

Props:

- `className?: string | undefined`

Also takes the props of `Omit<MenuPrimitive.Trigger.Props, "className">`.

## Motion

- **open** (overlay, scale): A menu fades in over the overlay family's duration (200 ms in, 120 ms out by default) and scales up from 0.95 from where it is anchored (the menu's trigger, or for a submenu the item that opened it).
- **sub-open** (overlay, scale): A submenu fades in and scales up a little from the item that opened it when the person opens it with the pointer or an arrow key, and fades out when it closes. Under reduced motion it is a short fade.

Set with `--cd-motion-menubar-<moment>-*` in your brand file; the families are in the design reference.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
