AppBar
v1.0.20Updated 19 Oct 2026Odoo/Xero-style module-menu top bar — app launcher, brand, a current-module pill with switcher, a Radix Menubar section-dropdown bar, and a right cluster (+New, ⌘K search, notifications, company switcher, avatar). Dark surface.
Preview
Live · 5 stories▸Why this is recommendedheaderappbartopbarmenubar+6
AppBar — module menu.
- ✓Top of a module-based ERP/accounting workspace
- ✓Odoo/Xero-style products with section menus
- ✓Apps needing a module switcher + dropdown menu bar
- App launcher + brand + current-module pill with switcher
- Horizontal section dropdown bar on Radix Menubar (arrow-key nav) with active underline
- Right cluster: +New (split), ⌘K search, TH/EN toggle, notifications, company switcher, avatar menu
- Dark bg-sidebar surface, both themes; responsive collapse with hidden-scrollbar overflow
- Data-driven, SSR-safe, keyboard-accessible, className + data-slot passthrough
- i18n: labels prop overrides every built-in UI string (app-launcher aria, Switch module heading, language-group aria, account-menu aria, search text); merged over DEFAULT_APP_BAR_LABELS
- ✕Primary vertical navigation (use Sidebar)
- ✕In-page section headers (use PageHead)
- ✕Minimal marketing headers (use AppBarCommand)
Install
Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.
Usage
Tick variants in the left menu — each adds a tab with that variant’s real story source, the same code the preview above renders.
Props
brandLogo chip + wordmark
—moduleCurrent-module pill (+ modules switcher)
—modulesFlat module-switcher list shown in the pill dropdown
—moduleGroupsGrouped module switcher — bands of modules under labelled headings, for when a flat `modules` list has grown past readable. AppBarModuleGroup = { id, label: ReactNode, modules: AppBarModule[] }. Takes precedence over `modules`; rows keep their icon, truncation, aria-current and active check, and the generic "Switch module" caption drops away since each band names itself. MCP feedback fb_f295b2f1.
—menusHorizontal section dropdown bar
—newAction+New button (plain or split menu)
—companyCurrent company (+ companies switcher)
—userAvatar dropdown menu
—stickyPosition sticky top-0 z-40 (default true)
—labelsOverride any built-in UI string (i18n). Keys: allApps, switchModule, language, accountMenu, searchPlaceholder, newAction, switchCompany, notifications, notificationsUnread. English defaults ship verbatim (DEFAULT_APP_BAR_LABELS). notificationsUnread takes a {count} token filled with the locale-formatted unread number; searchPlaceholder loses to the searchPlaceholder prop and newAction loses to newAction.label. MCP feedback fb_aae65135.
—languagesLanguages the bar offers. Renders nothing when omitted or empty.
—activeLanguageThe chosen code. Defaults to the first entry.
—onLanguageChangeCalled once with the chosen code.
—languageVariantHow the language control is drawn. "auto" (default) is a segmented group up to LANGUAGE_SEGMENTED_MAX (3) entries and a dropdown beyond it; "segmented" and "menu" pin the form regardless of count. The segmented form was the only form, which suits TH / EN and breaks at scale: it is hidden md:flex with no overflow handling, so past a handful of languages the extra buttons push the rest of a 52px bar out of the row. The dropdown shows the active label on one trigger and every language in a radio group behind it. Both forms carry data-slot="app-bar-language", with data-variant telling them apart. MCP feedback fb_4bdd6c1e.
—actionsExtra right-side slot, rendered before the user avatar. The row it lands in declares `data-surface="sidebar"` and the class `group/app-bar-actions`, and provides that surface to every build69 control inside it — so a LanguageSwitcher or ThemeToggle dropped here colours itself for the dark bar with no classes passed in, and a host’s own markup can style against `group-data-[surface=sidebar]/app-bar-actions:`. Pass `surface="default"` on a control to opt out. MCP feedback fb_4bdd6c1e.
—