ReferenceAppBar
The Reference shell's app bar, ready to go. The chrome that never changes ( LanguageSelector) is baked into the End slot, the brand variant is a simple prop, and the parts that depend on your app ( middle, account) come in as composition. One preset, one shell — and the same shape will repeat for <AppAppBar> and <PromotionAppBar> once their middles ship.
This pattern pairs with ReferenceMiddle: one wraps the Reference shell's middle, the other wraps its whole app bar. Want full control? Drop down to the <AppBar> primitive and put the canonical pieces together yourself.
Live demo
Running in bounded mode so the bar stays inside the demo box. Give the search trigger a try — the CommandPalette opens right over the page — and the language selector and sign-in button work too.
API shape — the three-category rule
Every slot in the Reference app bar falls into one of three buckets, and the preset's API follows straight from that.
- Invariant content
Baked. Not a prop. LanguageSelector is invariant chrome on every shell — the preset just mounts it. The one per-deployment config it needs (
cookieDomain) is forwarded. NavHistory (back / forward / recents) is baked into the Brand slot too, gated on onNavigate.- Enumerated content
Variant prop. Brand resolves between
'mark'and'lockup'; mode resolves between'edge'and'bounded'. Finite, known sets — you just pick from the list.- Contextual content
Composition. Middle takes the search index and a navigate function; account takes the auth state and signInHref. Both vary by consumer and reactively respond to runtime state — they’re
ReactNodeprops, not parametric options.
Props
- brand
'mark' | 'lockup'Default
'mark'. Mark for in-app surfaces; lockup for acquisition / marketing.- brandHref
stringDefault
'/'. Brand anchor target.- brandLabel
stringDefault
'Halo — Home'. Accessible label on the brand anchor.- mode
'edge' | 'bounded'Default
'edge'. Forwarded to<AppBar>.- onNavigate
(pathname: string) => voidRouter navigate for the baked
NavHistory(back / forward / recents in the Brand slot). Pass it to wire history; omit it for a Reference shell without. The app also records visits via recordNav.- navHistoryIcons
Record<string, ReactNode>Optional icon-key → glyph map forwarded to NavHistory, for recents rows whose recorded visit carried an icon key.
- middle
ReactNodeRequired. Typically
<ReferenceMiddle items={…} onNavigate={…} />.- account
ReactNodeRequired. Typically
<AccountSlot state={…} signInHref={…} />.- cookieDomain
stringForwarded to the baked LanguageSelector. Pass
'.halocompliance.com'in production for cross-subdomain.- onSlotError
(error: Error, info: ErrorInfo) => voidFires when any of the AppBar’s per-slot boundaries catch (Brand / Middle / End). Same shape as the AppBar’s own prop.
- onChromeError
(error: Error, info: ErrorInfo) => voidFires when one of the baked chrome patterns (BrandSlot, LanguageSelector) catches inside its own ErrorBoundary. Chrome degrades silently to the user; this is the only developer signal.
Usage
import {
ReferenceAppBar,
ReferenceMiddle,
AccountSlot,
} from '@halo-compliance/ui'
<ReferenceAppBar
onNavigate={navigate}
middle={<ReferenceMiddle items={SEARCH_INDEX} onNavigate={navigate} />}
account={<AccountSlot state="signed-out" signInHref={portalUrl} />}
/><ReferenceAppBar
brand="lockup"
brandHref="/"
brandLabel="Halo Compliance Design System — Home"
mode="edge"
onNavigate={navigate}
cookieDomain=".halocompliance.com"
middle={
<ReferenceMiddle
items={SEARCH_INDEX}
placeholder="Search docs"
onNavigate={navigate}
onError={reportChromeError}
/>
}
account={
<AccountSlot
state="signed-out"
signInHref={portalUrl}
onError={reportChromeError}
/>
}
onSlotError={reportChromeError}
onChromeError={reportChromeError}
/>When to reach for it
- Use the preset when you're building a Reference shell — docs, knowledge base, design system. Match it and the bar stays consistent across every surface.
- Drop down to
<AppBar>when you need full control: a different middle (a Reference shell variant), a custom End-slot composition (a third invariant element), or a custom mode treatment.
Anti-patterns
- Don’t expose what’s invariant. Language is on every shell on every surface — exposing it as a prop invites accidental removal. Bake it. Same rule applies if a future “audit log indicator” or similar becomes invariant.
- Don’t turn composition slots into prop bags. The temptation is to flatten
middle=<ReferenceMiddle items={…} />intomiddleItems={…}. Don’t — middle has half a dozen optional knobs (onError, shortcutMatcher, shortcutHint, placeholder, …) that would all have to flatten too. Composition keeps the API stable as the inner pattern grows. - Don’t reach for the preset when you need a different shell. An App-shell AppBar (⌘K + tenant + alerts) is a different preset, not a customized Reference one.
<AppAppBar>ships when<AppMiddle>lands.
Related
- /app-bar — the AppBar Component this preset composes. Drop down to it for hand-composed shells.
- /app-bar#middle — the middle slot and its shell-conditional content. ReferenceMiddle is the canonical Reference fill.
- /app-bar#language — LanguageSelector, baked into this preset’s End slot.
- /shell — how the bar mounts inside SiteLayout.