build69
build69  /  Components  /  Navigation  /  Topbar

Topbar

v1.0.24Updated 20 Oct 2026

Persistent app-level top bar with breadcrumb / page title slot, action buttons, and user menu.

Preview

Live · 14 stories
DefaultOpen ↗
▸Why this is recommendedheadertopbarnavbarshell+1

The default, out-of-the-box Topbar.

Recommended for+14
  • ✓Top of every AppShell-wrapped page
  • ✓A top bar for an app that has no notifications yet (omit the notification props and no bell is drawn)
Tags+6
headertopbarnavbarshelldefault
Features+4
  • Workspace switcher (brand block) — a caret only when a workspaceMenu / onCreateWorkspace is given
  • Primary nav with count badges
  • Search field + ⌘K command palette — rendered only when a search prop is wired
  • Create menu, 22-app launcher, help button
  • Notification bell + popover (All / Mentions / Unread) — rendered only when notifications are wired; showNotifications={false} hides it outright
  • User pill with status dot; menu rows appear per handler (onSelect / onThemeChange / onSignOut), and with none the pill is plain identity
  • No dead controls: an action with no way to take effect is not rendered (fb_b8731787)
  • i18n: labels prop overrides every built-in UI string (workspace switcher, search palette, create menu, app launcher, notifications, user menu, aria-labels); merged over DEFAULT_TOPBAR_LABELS
  • Client-side routing: pass `linkComponent` (next/link, React Router Link) and every row that has an href renders through the host app link component instead of a plain anchor, which would reload the whole document (fb_bf7dc63a); TopbarNavItem gains an event-carrying onClick
Not recommended for−2
  • ✕In-page section headers (use PageHead)

Install

Ask your agent, or call the MCP tool directly. The resolved bundle is written into your project.

get_registry_item({ name: "Topbar" })

Usage

import { Topbar } from '@/components/navigation/topbar';

// An app with no notifications API: pass nothing for them and no bell is drawn.
<Topbar
  brand={{ mark: 'b', name: 'build69', workspace: 'Mali & Daughters' }}
  nav={nav}
  activeNavKey="home"
  searchResults={results}
  onSelectSearchResult={(value) => router.push(hrefFor(value))}
  user={{ name, role, initials, onSignOut }}
/>

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

Left block: { mark, name, workspace, workspaceMenu?, onSelectWorkspace?, onCreateWorkspace? }. Without a workspaceMenu and without onCreateWorkspace it renders as plain identity — no caret promising a switcher

TopbarBrand—
nav

Primary nav items { key, label, icon, count?, active?, href? }. Omitted renders no nav (never sample links) — pass DEMO_TOPBAR_NAV for the sample set

ReadonlyArray<TopbarNavItem>—
activeNavKey

Key of the active nav item (falls back to item.active)

string—
searchPlaceholder

Text in the search field; null hides the search outright

string | null—
searchResults

Palette results { value, group, title, meta?, icon?, onSelect? }. Passing it (even []) is what tells the Topbar the app HAS search — with no search prop at all the field, palette and ⌘K shortcut are not rendered

ReadonlyArray<TopbarSearchResult>—
onSearch

Query changed in the palette; also wires the search field

(value: string) => void—
onSelectSearchResult

A result was picked (per-result onSelect wins). Without either, picking a result only closes the palette

(value: string) => void—
createMenu

Create dropdown items { label, value, icon?, description?, shortcut?, group? }; pair with onCreate

ReadonlyArray<TopbarCreateItem>—
onCreate

A create item was chosen

(value: string) => void—
appLauncher

App-grid items { product, label?, group?, onSelect? }; omitted renders no launcher trigger

ReadonlyArray<TopbarAppLink>—
notifications

Unread count on the bell. Passing it (0 included) is one of the signals that the app has notifications

number—
notificationItems

Popover list; [] shows the caught-up empty state. Passing it wires the bell

ReadonlyArray<TopbarNotification>—
showNotifications

Explicit bell control (fb_b8731787). Omit for the default — the bell renders only when a notification prop/handler is supplied. false hides it even with data; true renders it with none

boolean—
onMarkAllNotificationsRead

Popover "Mark all read" — the link renders only when this is wired

() => void—
onViewAllNotifications

Popover footer "View all" (hidden when omitted)

() => void—
onNotificationSettings

Popover footer "Settings" (hidden when omitted)

() => void—
user

{ name, role?, initials, status?, menu?, onSelect?, theme?, onThemeChange?, onSignOut? }. The menu rows follow the handlers: onSelect gives My profile / Preferences / Help & docs, onThemeChange the Theme submenu, onSignOut the Sign out row; with none the pill is identity only

TopbarUser—
onHelp

Help & docs icon button (hidden when omitted)

() => void—
onMobileMenu

Hamburger shown below md (hidden when omitted)

() => void—
labels

Override any built-in UI string — workspace switcher, search palette, create menu, app launcher, notifications, user menu, aria-labels (i18n). Merged over DEFAULT_TOPBAR_LABELS; {count} template for the unread-bell aria-label

Partial<TopbarLabels>—
linkComponent

The host app link component for every nav row that has an href (next/link, React Router Link). Defaults to a plain anchor, which in a routed app reloads the whole document. TopbarNavItem.onClick now receives the click EVENT so a host can preventDefault and route itself. Rows carry data-slot="topbar-nav-link". MCP feedback fb_bf7dc63a.

TopbarLinkComponent—

Related