{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "menu-bar",
  "title": "Menu Bar",
  "author": "Ballmac <https://ui.ballmac.com>",
  "description": "A translucent macOS menu bar on Radix Menubar: a bold app menu, menus with key equivalents, submenus and checkmarks, a status area with icon buttons and a hydration-safe live clock.",
  "dependencies": [
    "radix-ui",
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ballmac/components/menu-bar.tsx",
      "content": "// Ballmac UI: Menu Bar. https://ui.ballmac.com/components/menu-bar\n\"use client\"\n\nimport * as React from \"react\"\nimport { CheckIcon, ChevronRightIcon } from \"lucide-react\"\nimport { Menubar as MenubarPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype MenuBarProps = React.ComponentProps<typeof MenubarPrimitive.Root>\n\n/**\n * A macOS menu bar built on Radix Menubar: arrow keys move between menus and items, typeahead,\n * Escape closes. Put MenuBarMenu children first and a MenuBarStatus area last. The status area is\n * rendered beside the ARIA menubar (not inside it), since a menubar may only contain menu items.\n */\nfunction MenuBar({ className, children, style, ...props }: MenuBarProps) {\n  const all = React.Children.toArray(children)\n  const isStatus = (c: React.ReactNode) => React.isValidElement(c) && c.type === MenuBarStatus\n  return (\n    <div\n      data-slot=\"menu-bar\"\n      style={style}\n      className={cn(\n        \"flex h-7 w-full min-w-0 items-center px-2 text-[13px] text-foreground select-none\",\n        \"border-b border-white/20 bg-background/55 shadow-[0_0.5px_0_0_rgb(0_0_0/0.08)] backdrop-blur-2xl backdrop-saturate-150 dark:border-white/[0.06] dark:bg-background/45\",\n        className\n      )}\n    >\n      <MenubarPrimitive.Root data-slot=\"menu-bar-menus\" className=\"flex min-w-0 items-center gap-0.5\" {...props}>\n        {all.filter((c) => !isStatus(c))}\n      </MenubarPrimitive.Root>\n      {all.filter(isStatus)}\n    </div>\n  )\n}\n\nfunction MenuBarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n  return <MenubarPrimitive.Menu data-slot=\"menu-bar-menu\" {...props} />\n}\n\nfunction MenuBarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n  return <MenubarPrimitive.Group data-slot=\"menu-bar-group\" {...props} />\n}\n\nfunction MenuBarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n  return <MenubarPrimitive.Sub data-slot=\"menu-bar-sub\" {...props} />\n}\n\ntype MenuBarTriggerProps = React.ComponentProps<typeof MenubarPrimitive.Trigger> & {\n  /** \"app\" sets the trigger in bold, like the application menu next to the logo. */\n  variant?: \"default\" | \"app\"\n}\n\nfunction MenuBarTrigger({ variant = \"default\", className, ...props }: MenuBarTriggerProps) {\n  return (\n    <MenubarPrimitive.Trigger\n      data-slot=\"menu-bar-trigger\"\n      className={cn(\n        \"flex h-[22px] shrink-0 items-center gap-1.5 rounded-[5px] px-2 outline-none transition-colors duration-75\",\n        \"hover:bg-foreground/[0.08] focus-visible:bg-foreground/[0.1] data-[state=open]:bg-foreground/[0.12] [&_svg]:size-3.5 [&_svg]:shrink-0\",\n        variant === \"app\" ? \"font-bold\" : \"font-normal\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst menuSurface =\n  \"z-50 min-w-[14rem] overflow-hidden rounded-[10px] border border-foreground/10 bg-popover/80 p-[5px] text-[13px] text-popover-foreground shadow-[0_0_0_0.5px_rgb(0_0_0/0.12),0_12px_32px_-8px_rgb(0_0_0/0.35)] backdrop-blur-2xl backdrop-saturate-150 outline-none dark:bg-popover/75 dark:shadow-[0_0_0_0.5px_rgb(0_0_0/0.8),0_12px_32px_-8px_rgb(0_0_0/0.7)] data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:duration-150 motion-reduce:animate-none\"\n\ntype MenuBarContentProps = React.ComponentProps<typeof MenubarPrimitive.Content> & {\n  /** Render into a portal on document.body (default). Set false to keep the menu inside its container, e.g. in a mockup. */\n  portal?: boolean\n}\n\nfunction MenuBarContent({ portal = true, className, align = \"start\", alignOffset = -4, sideOffset = 4, ...props }: MenuBarContentProps) {\n  const content = (\n    <MenubarPrimitive.Content\n      data-slot=\"menu-bar-content\"\n      align={align}\n      alignOffset={alignOffset}\n      sideOffset={sideOffset}\n      className={cn(menuSurface, \"origin-(--radix-menubar-content-transform-origin)\", className)}\n      {...props}\n    />\n  )\n  return portal ? <MenubarPrimitive.Portal>{content}</MenubarPrimitive.Portal> : content\n}\n\nconst itemClasses =\n  \"relative flex h-[22px] cursor-default items-center gap-2 rounded-[5px] px-2 outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:text-foreground/35 data-[highlighted]:bg-ring data-[highlighted]:text-white [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5\"\n\ntype MenuBarItemProps = React.ComponentProps<typeof MenubarPrimitive.Item> & {\n  /** Indent the label to line up with checkbox items. */\n  inset?: boolean\n  /** Red text for destructive actions. */\n  variant?: \"default\" | \"destructive\"\n}\n\nfunction MenuBarItem({ inset, variant = \"default\", className, ...props }: MenuBarItemProps) {\n  return (\n    <MenubarPrimitive.Item\n      data-slot=\"menu-bar-item\"\n      data-variant={variant}\n      className={cn(itemClasses, inset && \"ps-6\", variant === \"destructive\" && \"text-destructive\", \"group/menu-item\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction MenuBarCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {\n  return (\n    <MenubarPrimitive.CheckboxItem data-slot=\"menu-bar-checkbox-item\" className={cn(itemClasses, \"group/menu-item ps-6\", className)} {...props}>\n      <span className=\"absolute start-1.5 flex size-3.5 items-center justify-center\">\n        <MenubarPrimitive.ItemIndicator>\n          <CheckIcon className=\"size-3\" strokeWidth={2.5} aria-hidden=\"true\" />\n        </MenubarPrimitive.ItemIndicator>\n      </span>\n      {children}\n    </MenubarPrimitive.CheckboxItem>\n  )\n}\n\nfunction MenuBarLabel({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Label>) {\n  return (\n    <MenubarPrimitive.Label\n      data-slot=\"menu-bar-label\"\n      className={cn(\"px-2 pt-1.5 pb-0.5 text-[11px] font-semibold text-muted-foreground\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction MenuBarSeparator({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Separator>) {\n  return <MenubarPrimitive.Separator data-slot=\"menu-bar-separator\" className={cn(\"mx-2 my-[5px] h-px bg-foreground/10\", className)} {...props} />\n}\n\ntype MenuBarShortcutProps = React.ComponentProps<\"span\">\n\n/** Right-aligned key equivalent, e.g. \"⇧⌘N\". Plain text, so it is part of the item's accessible name. */\nfunction MenuBarShortcut({ className, ...props }: MenuBarShortcutProps) {\n  return (\n    <span\n      data-slot=\"menu-bar-shortcut\"\n      className={cn(\"ms-auto ps-6 font-sans text-[12px] tracking-[0.12em] text-muted-foreground group-data-[highlighted]/menu-item:text-white/90\", className)}\n      {...props}\n    />\n  )\n}\n\nfunction MenuBarSubTrigger({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger>) {\n  return (\n    <MenubarPrimitive.SubTrigger\n      data-slot=\"menu-bar-sub-trigger\"\n      className={cn(itemClasses, \"data-[state=open]:bg-foreground/10 data-[state=open]:data-[highlighted]:bg-ring\", className)}\n      {...props}\n    >\n      {children}\n      <ChevronRightIcon className=\"ms-auto size-3.5 opacity-60\" aria-hidden=\"true\" />\n    </MenubarPrimitive.SubTrigger>\n  )\n}\n\ntype MenuBarSubContentProps = React.ComponentProps<typeof MenubarPrimitive.SubContent> & {\n  /** Render into a portal on document.body (default). */\n  portal?: boolean\n}\n\nfunction MenuBarSubContent({ portal = true, className, sideOffset = 2, ...props }: MenuBarSubContentProps) {\n  const content = (\n    <MenubarPrimitive.SubContent\n      data-slot=\"menu-bar-sub-content\"\n      sideOffset={sideOffset}\n      className={cn(menuSurface, \"min-w-[10rem] origin-(--radix-menubar-content-transform-origin)\", className)}\n      {...props}\n    />\n  )\n  return portal ? <MenubarPrimitive.Portal>{content}</MenubarPrimitive.Portal> : content\n}\n\ntype MenuBarStatusProps = React.ComponentProps<\"div\">\n\n/** The right side of the bar: status icons and the clock. */\nfunction MenuBarStatus({ className, ...props }: MenuBarStatusProps) {\n  return <div data-slot=\"menu-bar-status\" className={cn(\"ms-auto flex shrink-0 items-center gap-0.5\", className)} {...props} />\n}\n\ntype MenuBarStatusItemProps = React.ComponentProps<\"button\">\n\n/** An icon button in the status area. Give it an aria-label. */\nfunction MenuBarStatusItem({ className, type = \"button\", ...props }: MenuBarStatusItemProps) {\n  return (\n    <button\n      type={type}\n      data-slot=\"menu-bar-status-item\"\n      className={cn(\n        \"flex h-[22px] min-w-[26px] shrink-0 items-center justify-center gap-1 rounded-[5px] px-1.5 outline-none transition-colors duration-75 hover:bg-foreground/[0.08] focus-visible:ring-2 focus-visible:ring-ring/60 [&_svg]:size-[15px] [&_svg]:shrink-0\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\ntype MenuBarClockProps = Omit<React.ComponentProps<\"time\">, \"children\"> & {\n  /** BCP 47 locale for formatting. Fixed by default so server and browser agree. */\n  locale?: string\n  /** Intl options. Default: short weekday, month, day, and hour:minute. */\n  format?: Intl.DateTimeFormatOptions\n  /** Show a fixed time instead of the live clock (useful for mockups and screenshots). */\n  value?: Date\n}\n\nconst defaultClockFormat: Intl.DateTimeFormatOptions = { weekday: \"short\", month: \"short\", day: \"numeric\", hour: \"numeric\", minute: \"2-digit\" }\n\n/**\n * A live clock that ticks each minute. It renders nothing time-specific on the server and fills in after\n * mount, so it never causes a hydration mismatch.\n */\nfunction MenuBarClock({ locale = \"en-US\", format = defaultClockFormat, value, className, ...props }: MenuBarClockProps) {\n  const fixed = value?.getTime()\n  const [now, setNow] = React.useState<Date | null>(value ?? null)\n\n  React.useEffect(() => {\n    if (fixed !== undefined) {\n      setNow(new Date(fixed))\n      return\n    }\n    setNow(new Date())\n    let interval: number | undefined\n    const timeout = window.setTimeout(() => {\n      setNow(new Date())\n      interval = window.setInterval(() => setNow(new Date()), 60_000)\n    }, 60_000 - (Date.now() % 60_000))\n    return () => {\n      window.clearTimeout(timeout)\n      window.clearInterval(interval)\n    }\n  }, [fixed])\n\n  const text = now ? new Intl.DateTimeFormat(locale, format).format(now).replace(/,/g, \"\") : \"\"\n  return (\n    <time\n      data-slot=\"menu-bar-clock\"\n      dateTime={now?.toISOString()}\n      className={cn(\"inline-flex h-[22px] min-w-[4.5rem] shrink-0 items-center justify-end px-1.5 tabular-nums\", className)}\n      {...props}\n    >\n      {text}\n    </time>\n  )\n}\n\nexport {\n  MenuBar,\n  MenuBarCheckboxItem,\n  MenuBarClock,\n  MenuBarContent,\n  MenuBarGroup,\n  MenuBarItem,\n  MenuBarLabel,\n  MenuBarMenu,\n  MenuBarSeparator,\n  MenuBarShortcut,\n  MenuBarStatus,\n  MenuBarStatusItem,\n  MenuBarSub,\n  MenuBarSubContent,\n  MenuBarSubTrigger,\n  MenuBarTrigger,\n  type MenuBarClockProps,\n  type MenuBarContentProps,\n  type MenuBarItemProps,\n  type MenuBarProps,\n  type MenuBarShortcutProps,\n  type MenuBarStatusItemProps,\n  type MenuBarStatusProps,\n  type MenuBarSubContentProps,\n  type MenuBarTriggerProps,\n}\n",
      "type": "registry:ui",
      "target": "@components/ballmac/menu-bar.tsx"
    }
  ],
  "meta": {
    "schema": 1,
    "tier": "free",
    "tags": [
      "menubar",
      "menu",
      "macos",
      "navigation",
      "keyboard shortcuts",
      "clock",
      "status bar"
    ],
    "version": "1.0.0",
    "updated": "2026-09-29",
    "ai": {
      "summary": "<MenuBar> holds <MenuBarMenu value><MenuBarTrigger/><MenuBarContent>items</MenuBarContent></MenuBarMenu> (Radix Menubar parts with Mac styling) followed by <MenuBarStatus> with <MenuBarStatusItem aria-label> icon buttons and <MenuBarClock />. Use variant=\"app\" on the app-name trigger and <MenuBarShortcut> for key equivalents.",
      "whenToUse": [
        "A Mac desktop mockup or product hero where the app's menus should really open",
        "A web app that wants desktop-style menus with keyboard navigation (File, Edit, View)",
        "Status bars that pair a few icon buttons with a clock"
      ],
      "whenNotToUse": [
        "Site navigation for a marketing page (use a header with links)",
        "A single action menu on a button (use a dropdown menu)"
      ],
      "composesWith": [
        "mac-window",
        "dock",
        "dynamic-island"
      ],
      "a11y": [
        {
          "keys": "Tab",
          "action": "Focuses the menu bar (one stop), then the status buttons"
        },
        {
          "keys": "ArrowLeft / ArrowRight",
          "action": "Moves between menus, also while one is open"
        },
        {
          "keys": "Enter / Space / ArrowDown",
          "action": "Opens the focused menu"
        },
        {
          "keys": "ArrowUp / ArrowDown, typeahead",
          "action": "Moves between items"
        },
        {
          "keys": "Escape",
          "action": "Closes the menu and returns focus to its trigger"
        }
      ],
      "customization": [
        "MenuBarTrigger variant: default | app (bold)",
        "MenuBarContent / MenuBarSubContent portal: false keeps menus inside a mockup container",
        "MenuBarItem inset and variant=\"destructive\"; highlighted items use the --ring color like the macOS accent",
        "MenuBarClock: locale (default en-US), format (Intl options), value for a fixed time"
      ]
    },
    "examples": [
      "menu-bar-demo"
    ],
    "url": "https://ui.ballmac.com/components/menu-bar"
  },
  "categories": [
    "macos"
  ],
  "type": "registry:ui"
}