Skip to content

Top bar / app bar

In review
Live · web

Primary app header: drive it live (toggle search, push the inbox count, condense the bar)

NockerlDashboard

Inbox shows 3 unread · search is collapsed · bar is full. Tab through every action; the cyan boundary line closes the bar. The island is live.

Variants

Chat
Session settings

Condensed: the same bar after scroll (height collapses; freezes under reduced motion)

NockerlDashboard
3 selected
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,
// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
import { NockerlIconButton, NockerlAvatar } from '@dizyx/nockerl-react';
export function AppHeader() {
const [searchOpen, setSearchOpen] = useState(false);
return (
<TopBar
brand={{ mark: 'nockerl', product: 'Nockerl' }} // mark + optional product label
title="Chat" // page title (centered on Android)
align="center" // 'lead' | 'center'
actions={
<>
<NockerlIconButton icon="search" label="Search" pressed={searchOpen} onClick={() => setSearchOpen((v) => !v)} />
<ClusterStatus online={3} total={4} onClick={openCluster} />
<InboxButton count={3} onClick={openInbox} /> {/* count → "99+" → unseen dot */}
<NockerlAvatar src={user.photo} name={user.name} presence="streaming" onClick={openSettings} />
</>
}
/>
);
}
// A sub-screen header: a leading back button + title instead of the brand.
<TopBar leading={<NockerlIconButton icon="back" label="Back" onClick={goBack} />} title="Session settings" />
PropTypeDefaultDescription
brand{ mark: BrandMark; product?: string }Leading identity: the three-peaks mark and an optional product label. Omit when leading is set (a sub-screen).
leadingReactNodeReplaces the brand on a sub-screen, typically a back IconButton. Mutually exclusive with brand.
titlestringPage title. Bound to the title.medium type role.
align'lead' | 'center''lead'Title placement. center is the Android idiom, absolutely centered to the bar so the action cluster never shifts it.
breadcrumbCrumb[]Wayfinding trail ({ label, href }[]) shown in place of the title; the last crumb is aria-current="page".
actionsReactNodeTrailing account cluster, right-aligned and evenly gapped: search · ClusterStatus · InboxButton · Avatar.
condensedbooleanfalseScrolled state: the bar shrinks its height. Animates (height); freezes under prefers-reduced-motion.
selection{ count: number; actions: ReactNode }Contextual mode. Replaces the chrome with a cyan-tinted "N selected" bar + bulk actions and a clear button.
InboxButton.countnumber0Inbox badge count (agent-orange keycap); clamps to 99+, falls back to an unseen dot at 0.