RadCN
Navigationreadycomponentready

Menubar

A dependency-free application menubar with trigger-owned menus, portal content, submenus, checked items, radio groups, and keyboard navigation.

Importimport { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarPortal, MenubarTrigger } from 'radcn/menubar'
Preview

Live package example

Render the upstream four-menu browser-style demo with exact menu copy, shortcuts, checked state, submenus, and sideOffset parity.

Menubar Demo

Render the upstream four-menu browser-style demo with exact menu copy, shortcuts, checked state, submenus, and sideOffset parity.

Preview
import {
  Menubar,
  MenubarCheckboxItem,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarPortal,
  MenubarRadioGroup,
  MenubarRadioItem,
  MenubarSeparator,
  MenubarShortcut,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from 'radcn/menubar'

export function MenubarDemo() {
  return (
    <Menubar id="menubar-demo">
      <MenubarMenu value="file">
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarPortal>
          <MenubarContent sideOffset={8}>
            <MenubarItem textValue="New Tab">New Tab <MenubarShortcut>⌘T</MenubarShortcut></MenubarItem>
            <MenubarItem textValue="New Window">New Window <MenubarShortcut>⌘N</MenubarShortcut></MenubarItem>
            <MenubarItem disabled textValue="New Incognito Window">New Incognito Window</MenubarItem>
            <MenubarSeparator />
            <MenubarSub>
              <MenubarSubTrigger textValue="Share">Share</MenubarSubTrigger>
              <MenubarSubContent>
                <MenubarItem textValue="Email link">Email link</MenubarItem>
                <MenubarItem textValue="Messages">Messages</MenubarItem>
                <MenubarItem textValue="Notes">Notes</MenubarItem>
              </MenubarSubContent>
            </MenubarSub>
            <MenubarSeparator />
            <MenubarItem textValue="Print...">Print... <MenubarShortcut>⌘P</MenubarShortcut></MenubarItem>
          </MenubarContent>
        </MenubarPortal>
      </MenubarMenu>
      <MenubarMenu value="edit">
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarPortal>
          <MenubarContent sideOffset={8}>
            <MenubarItem textValue="Undo">Undo <MenubarShortcut>⌘Z</MenubarShortcut></MenubarItem>
            <MenubarItem textValue="Redo">Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut></MenubarItem>
            <MenubarSeparator />
            <MenubarSub>
              <MenubarSubTrigger textValue="Find">Find</MenubarSubTrigger>
              <MenubarSubContent>
                <MenubarItem textValue="Search the web">Search the web</MenubarItem>
                <MenubarSeparator />
                <MenubarItem textValue="Find...">Find...</MenubarItem>
                <MenubarItem textValue="Find Next">Find Next</MenubarItem>
                <MenubarItem textValue="Find Previous">Find Previous</MenubarItem>
              </MenubarSubContent>
            </MenubarSub>
            <MenubarSeparator />
            <MenubarItem textValue="Cut">Cut</MenubarItem>
            <MenubarItem textValue="Copy">Copy</MenubarItem>
            <MenubarItem textValue="Paste">Paste</MenubarItem>
          </MenubarContent>
        </MenubarPortal>
      </MenubarMenu>
      <MenubarMenu value="view">
        <MenubarTrigger>View</MenubarTrigger>
        <MenubarPortal>
          <MenubarContent sideOffset={8}>
            <MenubarCheckboxItem textValue="Always Show Bookmarks Bar">Always Show Bookmarks Bar</MenubarCheckboxItem>
            <MenubarCheckboxItem checked textValue="Always Show Full URLs">Always Show Full URLs</MenubarCheckboxItem>
            <MenubarSeparator />
            <MenubarItem inset textValue="Reload">Reload <MenubarShortcut>⌘R</MenubarShortcut></MenubarItem>
            <MenubarItem disabled inset textValue="Force Reload">Force Reload <MenubarShortcut>⇧⌘R</MenubarShortcut></MenubarItem>
            <MenubarSeparator />
            <MenubarItem inset textValue="Toggle Fullscreen">Toggle Fullscreen</MenubarItem>
            <MenubarSeparator />
            <MenubarItem inset textValue="Hide Sidebar">Hide Sidebar</MenubarItem>
          </MenubarContent>
        </MenubarPortal>
      </MenubarMenu>
      <MenubarMenu value="profiles">
        <MenubarTrigger>Profiles</MenubarTrigger>
        <MenubarPortal>
          <MenubarContent sideOffset={8}>
            <MenubarRadioGroup value="benoit">
              <MenubarRadioItem value="andy" textValue="Andy">Andy</MenubarRadioItem>
              <MenubarRadioItem value="benoit" textValue="Benoit">Benoit</MenubarRadioItem>
              <MenubarRadioItem value="Luis" textValue="Luis">Luis</MenubarRadioItem>
            </MenubarRadioGroup>
            <MenubarSeparator />
            <MenubarItem inset textValue="Edit...">Edit...</MenubarItem>
            <MenubarSeparator />
            <MenubarItem inset textValue="Add Profile...">Add Profile...</MenubarItem>
          </MenubarContent>
        </MenubarPortal>
      </MenubarMenu>
    </Menubar>
  )
}

Installation

Intended future install command. RadCN is private and not published to npm yet, so this snippet documents the target user-facing API rather than something external consumers can run today.

pnpm add radcn # intended future package
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarPortal, MenubarTrigger } from 'radcn/menubar'

Theming

RadCN tokens read the resolved theme from the document. Store the user's preference separately, then resolve system preferences to a concrete light or dark theme before setting package tokens.

<html data-radcn-theme-mode="system" data-radcn-theme="dark">
  ...
</html>

Accessibility

  • Menubar renders role="menubar" with aria-orientation and trigger role="menuitem" semantics.
  • Triggers expose aria-haspopup, aria-controls, and aria-expanded when enhanced in the browser.
  • Menu content renders role="menu"; checkbox and radio items expose menuitemcheckbox and menuitemradio states.
  • Keyboard movement, typeahead, Escape close, submenu focus, disabled skip, and hover switching are browser-enhanced without React state.

Customization

  • Root, menu, trigger, portal, content, items, separators, submenus, checkbox items, radio groups, radio items, indicators, and shortcuts expose public data-radcn hooks.
  • The named demo passes sideOffset={8} to match upstream MenubarContent placement without changing the package default.
  • Shortcut glyphs, check marks, radio dots, and submenu carets are app-owned presentation over package hooks.
  • className, Tailwind utilities, and cn map to class, style, CSS variables, package classes, and data-radcn-menubar hooks.

Remix 3 Notes

  • use client and Radix Menubar primitives map to server-rendered Menubar markup plus scoped enhanceMenubar browser behavior.
  • lucide CheckIcon, ChevronRightIcon, and CircleIcon map to RadCN-owned text indicators and app-owned presentation, not a package dependency.
  • data-slot maps to public data-radcn-menubar* hooks and shared data-radcn-menu-* hooks.
  • Radix Portal maps to explicit MenubarPortal content moved into data-radcn-portal-root by the browser enhancer.
  • Vendor source remains read-only evidence and is not imported by RadCN.