The "show one record" page: a record header (media, h1, status, key facts, actions, previous/next pager), a main column for tabs, activity and related lists, and a side column of details. It responds to its own width — below 42rem (672px) of layout width the side column moves under the header, its sections fold and the key facts become a scrolling strip. It measures itself, not the viewport.
Laura Callahan
CustomerHead of Operations · Northwind Traders
Activity
Calls, emails and notes from everyone on the account.
- Meltem Aydın logged a call · 14 minAgreed on the 3-year option if onboarding hours are included.
- Laura Callahan replied to “Renewal — revised quote”
- Can Demir moved Northwind renewal to Proposal
- Meltem Aydın added a noteBoard meets on December 3 — wants a signed draft before then.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { RecordLayout, RecordHeader, RecordPager, RecordMain, RecordSection, RecordAside, RecordAsideSection } from "@vamos-ui/react";
<RecordLayout>
<RecordHeader
back={{ href: "/crm/contacts", label: "Contacts" }}
media={<Avatar name="Laura Callahan" size="xl" />}
title="Laura Callahan"
subtitle="Head of Operations · Northwind Traders"
status={<Badge tone="success">Customer</Badge>}
facts={[{ label: "Owner", value: "Meltem Aydın" }, { label: "Lifetime value", value: "$48,500" }]}
actions={<Button variant="primary">Log call</Button>}
pager={<RecordPager index={3} total={128} prevHref="/crm/contacts/41" nextHref="/crm/contacts/43" />}
/>
<RecordMain>
<RecordSection title="Activity"><ActivityTimeline items={activity} /></RecordSection>
</RecordMain>
<RecordAside>
<RecordAsideSection title="Details"><DescriptionList items={details} /></RecordAsideSection>
</RecordAside>
</RecordLayout>Examples
Resizable side column
resizable adds a window-splitter handle on the side column's edge: drag it, or focus it and use ←/→ (Shift ×4), Home/End; double-click or Enter resets.
Side column: 340px
Laura Callahan
CustomerHead of Operations · Northwind Traders
Activity
Calls, emails and notes from everyone on the account.
- Meltem Aydın logged a call · 14 minAgreed on the 3-year option if onboarding hours are included.
- Laura Callahan replied to “Renewal — revised quote”
- Can Demir moved Northwind renewal to Proposal
- Meltem Aydın added a noteBoard meets on December 3 — wants a signed draft before then.
Previous / next
RecordPager shows "1 of 4" and registers j (next) and k (previous) — ignored while typing. With prevHref/nextHref the buttons are links and the shortcuts navigate through VamosProvider.
Selin Öztürk
ActiveProduct designer · Design
Narrow container
Below 672px of layout width the aside sits under the header, every section folds and the facts scroll sideways.
Laura Callahan
CustomerHead of Operations · Northwind Traders
Activity
Calls, emails and notes from everyone on the account.
- Meltem Aydın logged a call · 14 minAgreed on the 3-year option if onboarding hours are included.
- Laura Callahan replied to “Renewal — revised quote”
- Can Demir moved Northwind renewal to Proposal
- Meltem Aydın added a noteBoard meets on December 3 — wants a signed draft before then.
States
state="loading" renders a skeleton page; not-found and forbidden render a full-page empty state with the page's h1. readOnly hides header actions.
API
RecordLayout
| Prop | Type | Default |
|---|---|---|
asidePositionLogical side of the side column (flips in RTL). | "end" | "start" | "end" |
asideWidth · defaultAsideWidth · onAsideWidthChangeSide column width in px, controlled or not. | number | 320 |
resizableWindow-splitter handle on the side column. | boolean | false |
minAsideWidth · maxAsideWidthResize limits. | number | 260 · 520 |
stateBuilt-in page states. | "ready" | "loading" | "not-found" | "forbidden" | "ready" |
notFound · forbiddenReplace the default state pages. | ReactNode | — |
readOnlyHides RecordHeader actions. | boolean | false |
labelsOverrides for the record namespace. | RecordLayoutLabels | — |
RecordHeader
| Prop | Type | Default |
|---|---|---|
titleThe page's <h1>. | ReactNode | — |
subtitle · status · mediaRole and company, a status badge, an avatar or logo. | ReactNode | — |
factsKey facts as a <dl>; a scrolling strip at phone width. | { label: ReactNode; value: ReactNode }[] | — |
actionsHeader buttons (hidden when readOnly). | ReactNode | — |
back"← Contacts" link. | { href: string; label: string } | — |
pagerA RecordPager at the top end. | ReactNode | — |
saving"Saving…" status next to the title. | boolean | — |
sizeTitle 20 / 28 px × --display-scale. | "sm" | "md" | "md" |
loadingSkeleton title and subtitle. | boolean | — |
RecordPager
| Prop | Type | Default |
|---|---|---|
index · total1-based position and list length: "3 of 128". | number | — |
prevHref · nextHrefLinks; j/k navigate through VamosProvider. | string | — |
onPrevious · onNextCallbacks instead of links. | () => void | — |
shortcutsRegister j / k (aria-keyshortcuts). | boolean | true |
RecordMain · RecordSection
| Prop | Type | Default |
|---|---|---|
tabsRecordMain: route tabs above the content. | ReactNode | — |
title · description · actionRecordSection: a titled card (<section aria-labelledby>). | ReactNode | — |
paddingRecordSection body padding. | "md" | "none" | "md" |
RecordAside · RecordAsideSection
| Prop | Type | Default |
|---|---|---|
aria-labelRecordAside: name of the complementary landmark. | string | "Details" |
title · actionRecordAsideSection header. | ReactNode | — |
collapsibleFold on wide layouts too (narrow layouts always fold). | boolean | false |
defaultOpen · open · onOpenChangeOpen state. | boolean | true |
headingLevelHeading level of the title. | 2 | 3 | 2 |
SidePaneHandle
| Prop | Type | Default |
|---|---|---|
value · onValueChangePane width in px. Shared by Record detail and Editor layouts for custom side columns. | number | — |
min · max · defaultValueLimits and the reset width. | number | — |
edgeWhich edge of the pane the handle sits on. | "start" | "end" | "start" |
stepArrow-key step (Shift ×4). | number | 16 |