Layout
One shell, two page shapes, and the widths, rails and gutters that frame every screen.
One shell#
Every Oration app sits in the same frame: a cool-neutral sidebar rail beside the white content plane, and a 48px app header on top of every workspace page.
The shell at each sidebar state
Drawn at real size and scaled to fit. The sidebar collapses to an icon rail on request and becomes a sheet below 768px.
| Part | Size | Notes |
|---|---|---|
| Sidebar rail | 16rem | Cool Rail (bg-sidebar), 28px items in Body dense, 16px icons with a 10px gap. Read from SIDEBAR_WIDTH in the Sidebar component. |
| Icon rail | 3rem | The collapsed sidebar. Items show only their icons. |
| Sheet below 768px | 18rem | The sidebar opens over the plane from the header's toggle, on the dialog scrim. |
| App header | 48px | Sticky, White Plane with a hairline bottom, 12px side padding. Holds the sidebar toggle, a 16px divider, breadcrumbs and page actions 6px apart. |
The header is the one constant. Document pages scroll under it; full-bleed tools sit beneath it and scroll inside. Pages without a visible title pass heading to the header so it renders the page's h1 as screen-reader text. See Sidebar and Breadcrumb.
Two page shapes#
Inside the shell, a page is either a document that scrolls or a tool that fills the viewport. Decide which before drawing anything.
Document pages#
Home, settings, overviews and record pages. A centered column up to 72rem that scrolls with the window.
| Measure | Value | Classes |
|---|---|---|
| Column width | 72rem (1152px) | mx-auto w-full max-w-6xl |
| Narrow forms | 48rem (768px) | max-w-3xl |
| Side gutters | 24px, 16px below 640px | px-4 sm:px-6 |
| Top and bottom padding | 32px | py-8 |
| Between sections | 32px | gap-8 or mt-8 |
| Page description | up to 42rem | max-w-[42rem] |
// A document page: Home, settings, overviews, record tabs<AppHeader crumbs={[{ label: "Payments" }, { label: "Payment runs" }]} /><div className="mx-auto w-full max-w-6xl px-4 py-8 sm:px-6"> <PageTitle title="Payment runs" description="Schedule, approve and reconcile supplier payments." /> <div className="mt-8 flex flex-col gap-8"> <section>…</section> <section>…</section> </div></div>// A narrow form keeps the gutters and caps the column at 48rem<div className="mx-auto w-full max-w-3xl px-4 py-8 sm:px-6">…</div>PageBody in Page title is max-w-6xl px-6 py-8, so it keeps 24px gutters on a phone. DESIGN.md asks for 16px below 640px, which is what Home and the hand-built document pages use. Write px-4 sm:px-6 until PageBody changes.
Full-bleed tools#
Grids, boards, canvases and editors. A full-height column where one region scrolls and the chrome around it stays put.
| Part | Value | Notes |
|---|---|---|
| Column | 100svh | flex h-svh min-h-0 flex-col. The window never scrolls. |
| App header | 48px | The same sticky header as every page. |
| Toolbar rows | 28px controls | View tabs, search, filters, sort and display in one or two rows. See Toolbar. |
| Content | flex-1 | One region that scrolls internally: min-h-0 flex-1 overflow-auto. Grid headers stick to its top. |
| Footer | 36px | Sticky, with counts and totals in 12px tabular figures. |
// A full-bleed tool: grids, boards, canvases, editors<div className="flex h-svh min-h-0 flex-col"> <AppHeader heading="Invoices" crumbs={[{ label: "Invoices" }]} /> <Toolbar>…28px controls…</Toolbar> <div className="min-h-0 flex-1 overflow-auto"> <DataGrid … /> </div> <footer className="sticky bottom-0 flex h-9 items-center border-t border-border px-3 text-xs text-muted-foreground tabular-nums"> 212 invoices, $1,284,920.18 </footer></div>- A page has one scrolling region. Nested scroll areas inside a scrolling page are a sign the page picked the wrong shape.
- Don't center a tool in a 72rem column, and don't stretch a document page edge to edge.
min-h-0on every flex child between the column and the scrolling region, or the region grows instead of scrolling.
Home#
A document page with a two-column grid from 1024px: the approvals column plus a 20rem right rail.
Columns sit 32px apart and rail cards 16px apart. Below 1024px the rail moves above the approvals and sits two-up from 768px. The rail comes first in the source, so it is also first for keyboard and screen-reader users at every width.
// apps/web/src/app/(app)/page.tsx<div className="mx-auto w-full max-w-6xl px-4 py-8 sm:px-6"> <HomeGreeting /> <div className="mt-8 grid gap-8 lg:grid-cols-[minmax(0,1fr)_20rem] lg:gap-y-4"> <aside className="grid content-start gap-4 md:grid-cols-2 lg:col-start-2 lg:row-start-1 lg:grid-cols-1"> …rail cards… </aside> <div className="min-w-0 lg:col-start-1 lg:row-span-2 lg:row-start-1"> <ApprovalsQueue /> </div> </div></div>Record pages#
A record page adds a 21rem attribute rail on the right from 1024px, and its tab bar sticks under the header.
| Part | Value | Notes |
|---|---|---|
| Attribute rail | 21rem | w-[21rem] border-l border-border, scrolling on its own. A hairline edge, not a shadow: the rail is part of the plane. |
| Tab bar | line tabs | Sticks under the header, scrolls horizontally and fades its clipped edge over 2rem. |
| Below 1024px | sheet | The rail moves into a right sheet opened from a details button in the header. |
All measurements#
Every fixed width and height in the frame, in one place.
| Element | Size | Tailwind |
|---|---|---|
| Sidebar | 16rem | --sidebar-width |
| Icon rail | 3rem | --sidebar-width-icon |
| Sidebar sheet below 768px | 18rem | --sidebar-width on mobile |
| App header | 48px | h-12 |
| Document column | 72rem | max-w-6xl |
| Narrow form column | 48rem | max-w-3xl |
| Reading text and descriptions | 42rem | max-w-[42rem] |
| Gutters | 24px (16px below 640px) | px-4 sm:px-6 |
| Page top and bottom | 32px | py-8 |
| Between sections and Home's columns | 32px | gap-8 |
| Home rail | 20rem | lg:grid-cols-[minmax(0,1fr)_20rem] |
| Between rail cards | 16px | gap-4 |
| Record attribute rail | 21rem | w-[21rem] |
| Toolbar controls | 28px | h-7 |
| Tool footer | 36px | h-9 |
Templates#
Each template is one of the two shapes with its parts filled in. Start a new screen from the closest one.
| Template | Shape | What it adds |
|---|---|---|
| Document page | Document | Title, description and sections in the 72rem column. |
| Home | Document | The greeting, the approvals column and the 20rem rail. |
| Settings page | Document | Settings navigation, sections of label-left rows and the save bar. |
| Record page | Document | A sticky line tab bar and the 21rem attribute rail. |
| List page | Tool | Toolbar, data grid and the sticky footer. |
| Workspace | Tool | Queue, conversation and context panes that collapse to one below 768px. |
| Canvas | Tool | A node canvas on the dotted grid with a palette and an inspector. |
| Auth | Outside the shell | Centered and split layouts for sign in and sign up, with no sidebar or header. |