Patterns
Page header
The band across the top of every app page — the app-side cousin of SectionHead. It answers "what is this, and what can you do with it?" One component, two jobs: it heads a collection (eyebrow · title · count + a primary action) and it is the identity hero of a record (eyebrow · title · status · a metadata row + record actions).
Collection header
The top of a list view: what you're looking at, how much of it there is, and the one thing you came here to do — create.
Record identity hero
The top of a detail view: who or what this record is, its live status, and the facts you check first — with the record's actions on the right.
Slots
Only the title is required — use the slots your page needs and skip the rest.
- eyebrow
- A gold uppercase kicker — the entity type or section.
- title
- The name or collection title. Required. Renders the page h1 (override with titleAs).
- count
- A muted, tabular number beside the title — the size of a collection.
- status
- A slot beside the title for a
<Badge>— a record's live state. - meta
- A muted row of facts below, auto-separated by middots. Pass spans.
- actions
- Right-aligned Buttons — the primary action (lists) or record actions (detail).
Materiality
Typographic, not a surface — a header is neither a card nor a control, so it gets no border or fill. The engraved heading belongs to the proposed system; here the title is simply the display face: bold slab type, flat on the page. The count is mono and tabular; the meta row is muted with middot separators.
- frameless
- No frame or fill. Set
dividerfor a single hairline below — for a header that pins above scrolling content. - size
size="lg"(default) is the page h1 scale; md downsizes the title for a nested panel. The semantic level is separate — set titleAs to keep the heading outline correct.- count
- Mono (
--font-data), tabular, muted — it reads as a measure, not a heading.
Props
- title / eyebrow / description
- The required title and two optional text slots above and below it.
- count / status
- A collection count, or a record status node — beside the title.
- meta?: ReactNode
- The muted fact row below the title.
- actions?: ReactNode
- Right-aligned actions.
- size / titleAs / divider
- size 'lg' | 'md', titleAs the heading element (default h1), divider for a bottom hairline.
Usage
import { PageHeader, Button } from '@halo-compliance/ui'
import { Plus } from 'lucide-react'
<PageHeader
eyebrow="Compliance"
title="Officers"
count={142}
description="Loan officers across every branch."
actions={
<Button variant="primary" icon={<Plus />}>New officer</Button>
}
/>import { PageHeader, Badge, Button } from '@halo-compliance/ui'
import { SquarePen } from 'lucide-react'
<PageHeader
eyebrow="Loan officer"
title="Tom Becker"
status={<Badge tone="affirm" dot>Active</Badge>}
meta={
<>
<span>Created by Dana Whitfield</span>
<span>NMLS 1234567</span>
</>
}
actions={<Button variant="secondary" icon={<SquarePen />}>Edit</Button>}
/>When to use
- The top of every list and detail view. It is the orientation band of a Collection and the identity region of a Record.
- One per surface. It carries the page's h1; nested panels use a downsized header (size md) or plain headings.
- Doc pages use SectionHead instead. PageHeader is the app analog — count, status, meta and actions are app concerns.
Anti-patterns
- A toolbar in the header. Search and filters belong in the collection toolbar below, not in the actions slot — keep it to the primary action.
- Framing it. A header is not a surface; wrapping it in a Card reads as a panel and competes with the content.
- A wall of actions. One primary action, the rest behind a ⋯ menu — the header is for orientation, not a control panel.
Related
- /text-groups — the doc-page sibling; same three-part top composition.
- /collection — the list view this heads.
- /record — the detail view whose Identity region this is.
- /badge — the status node in the hero.