build69
build69  /  Components  /  Navigation  /  AppBar

AppBar

v1.0.20Updated 19 Oct 2026

Odoo/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
Module menuOpen ↗
▸Why this is recommendedheaderappbartopbarmenubar+6

AppBar — module menu.

Recommended for+14
  • ✓Top of a module-based ERP/accounting workspace
  • ✓Odoo/Xero-style products with section menus
  • ✓Apps needing a module switcher + dropdown menu bar
Tags+6
headerappbartopbarmenubarshellnavigationodooxeromodulemenu
Features+4
  • 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
Not recommended for−2
  • ✕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.

get_registry_item({ name: "AppBar" })

Usage

import { AppBar } from '@build69/ui';

<AppBar brand={brand} module={module} modules={modules} menus={menus} user={user} />

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

PropTypeRequired
brand

Logo chip + wordmark

AppBarBrand—
module

Current-module pill (+ modules switcher)

AppBarModule—
modules

Flat module-switcher list shown in the pill dropdown

AppBarModule[]—
moduleGroups

Grouped 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.

AppBarModuleGroup[]—
menus

Horizontal section dropdown bar

AppBarMenu[]—
newAction

+New button (plain or split menu)

AppBarNewAction—
company

Current company (+ companies switcher)

AppBarCompany—
user

Avatar dropdown menu

AppBarUser—
sticky

Position sticky top-0 z-40 (default true)

boolean—
labels

Override 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.

Partial<AppBarLabels>—
languages

Languages the bar offers. Renders nothing when omitted or empty.

{ code: string; label: string }[]—
activeLanguage

The chosen code. Defaults to the first entry.

string—
onLanguageChange

Called once with the chosen code.

(code: string) => void—
languageVariant

How 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.

"auto" | "segmented" | "menu"—
actions

Extra 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.

ReactNode—

Related