Record
Every record is one thing, and the page treats it that way. Three regions, stacked top to bottom. Identity — the name, the facts you check first (status · owner · version · dates), and the actions for this one thing; Data — everything it holds, in fields and sections; and Feed — the record's whole story, rendered by the Feed component: audit events and conversation woven into one stream, the way GitHub mixes system events and comments. Metadata lives in Identity (no properties rail) and audit lives in the Feed (no separate log) — so there's nothing on a side rail to break. That's why one simple vertical stack works at any width, split pane included.
BetaRecord is Beta — the composition is settled (PageHeader · Sections · Feed · ActionBar); the prop surface may still move.
Three regions, one stack — that's the whole layout. Identity sits at the top with the metadata, so there's no side rail to break when the pane gets narrow. Data and Feed scroll inside the well while the page stays put — the same scroll deal as a collection. Try Split pane: the record keeps its full height and hands a third of the well to a contextual Card on the right — the spot where a feature like AI chat docks right beside the work. (Support chat is a different thing — it floats in the bottom-right corner.) The stack just keeps working at two-thirds width, because a stack has nothing horizontal to collapse. On desktop the panel pushes; on mobile it'd slide in as a drawer. Audit and conversation share one Feed instead of two tabs — system events read as lines, replies as cards. And everything in the frame is the real thing — Record composing PageHeader, Feed, and ActionBar, live; edit a field and watch the staged dot light up.
API
Record owns the geometry and the scroll contract; the regions stay the canonical components. Four props on the root, plus one compound section.
- identity
- The pinned Identity region — typically a <PageHeader size="md" divider> with eyebrow, title, status Badge, meta facts, and header actions. Required: a record always announces what it is.
- children
- The body — Record.Section blocks (Data) and the Feed, stacked in order. The one scroll container: the page stays put while the body scrolls.
- actions?
- The pinned intent bar — an <ActionBar sticky={false}>. Staged-until-intent means the intents stay reachable from anywhere in the record. Omit for read-only records.
- context? · contextLabel?
- Contextual-pane content — the feature docking beside the record (AI chat, reference). When present the record yields the right third of the well to a secondary Card. contextLabel names the pane (its header and accessible name) and is required with context.
- <Record.Section title caption?>
- A titled Data section inside the body. Sections separate with hairlines; the body, not the section, owns the scroll.
Usage
import {
ActionBar, Badge, Button, Feed, PageHeader, Record,
} from '@halo-compliance/ui'
import { Check, FileDown } from 'lucide-react'
<Record
identity={
<PageHeader size="md" divider titleAs="h2"
eyebrow="Rulebook review"
title={review.title}
status={<Badge tone="caution" dot>In review</Badge>}
meta={<><span>{review.openedBy}</span><span>{review.channel}</span></>}
actions={<Button variant="secondary" icon={<FileDown />}>Export</Button>}
/>
}
actions={
<ActionBar sticky={false} dirty={form.state.isDirty} intents={[
{ id: 'discard', label: 'Discard', tone: 'ghost',
disabled: !form.state.isDirty, onPress: form.reset },
{ id: 'save', label: 'Save', tone: 'primary', icon: <Check />,
disabled: !form.state.isDirty, onPress: form.handleSubmit },
]} />
}
context={paneOpen ? <ReviewAssistant review={review} /> : undefined}
contextLabel="AI assistant" // ?pane=split — keep the pane in the URL
>
<Record.Section title="Submission">
{/* fields — read mode IS write mode; edits stage into the form */}
</Record.Section>
<Record.Section title="Feed">
<Feed>{/* events + comments, one stream */}</Feed>
</Record.Section>
</Record>Related
- /page-header — the Identity region.
- /feed — the history stream the body embeds.
- /action-bar — the pinned intent bar and the staged-until-intent doctrine.