Centrim Design System — a token-first, accessible React component system.
Layout
Structural helpers with no visual opinion beyond spacing and optional surfaces. Compose them to build pages; resize your browser to see the responsive behaviour.
Container
Centers content and caps its width with responsive gutters. The outermost wrapper for page content.
import { Container } from "@/design-system";
Max-width variants
Stack
Vertical flex layout for stacking related content with a consistent, token-based gap.
import { Stack } from "@/design-system";
Gap scale
Alignment
Inline
Horizontal flex layout that wraps by default — toolbars, filter rows, form actions.
import { Inline } from "@/design-system";
Wrapping toolbar
Resize the window to see items wrap onto a new line.
Grid
Responsive CSS grid with breakpoint-specific column counts, for card and dashboard layouts.
import { Grid } from "@/design-system";
1 → 2 → 4 columns
One column on mobile, two from sm, four from lg.
Cluster
Groups small items — tags, badges, chips — that wrap together with a consistent gap.
import { Cluster } from "@/design-system";
Tag list
Split
Two-region layout that stacks on small screens and splits into a row from lg up.
import { Split } from "@/design-system";
2:1 split
Section
Vertical rhythm wrapper for page sections, with an optional title and description slot.
import { Section } from "@/design-system";
With header
Quarterly revenue
Recognised revenue across all regions, updated nightly.
Center
Centers content horizontally within an intrinsic max width, with an option to also center vertically.
import { Center } from "@/design-system";
Horizontally centered
PageLayout
Full page shell with header, sidebar, main and footer slots, filling at least the viewport height.
import { PageLayout } from "@/design-system";
Header, sidebar, main, footer
ScrollArea
Radix ScrollArea with token-styled scrollbars for content that must be capped to a fixed height.
import { ScrollArea } from "@/design-system";
Vertical, max height small
Horizontal
ResizablePanelGroup / ResizablePanel / ResizableHandle
Draggable, keyboard-accessible split panels built on react-resizable-panels, for editors and inspector layouts.
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@/design-system";
Horizontal split
PageHeader
Top-of-page identity block: breadcrumb, eyebrow, title, description, supporting metadata and actions. Deliberately light — no surface, no shadow.
import { PageHeader } from "@/design-system";
When to use
- Once per page, as the first thing inside the page shell.
- When the page needs a primary action, a trail back up the hierarchy, or record metadata.
When not to use
- For a section inside a page — use ContentHeader.
- As a hero: it carries hierarchy, not marketing weight.
Breadcrumb, title, description, metadata, actions
Composition: PageHeader → Breadcrumb + Button. Resize to see the actions drop below the title.
Section
Page title
One or two lines of supporting description that explain what this page contains.
ContentHeader
Lighter header for a section inside a page — same anatomy as PageHeader at a smaller type scale.
import { ContentHeader } from "@/design-system";
When to use
- Above a table, list, card group or form section inside a page.
- When a section needs its own local action.
When not to use
- At the top of a page — that is PageHeader's job.
With a section action
Section title
Supporting copy for this section only.
ActionBar
Toolbar above a view: search and filters lead, secondary/overflow/primary actions trail. Owns no controls of its own.
import { ActionBar } from "@/design-system";
When to use
- Above a table, list or board that needs search, filters and a primary action.
- When actions apply to the whole view rather than to a selection.
When not to use
- For actions on selected rows — use BulkActionBar.
- For filter chips and clear-all behaviour — use FilterBar.
Search, filters, overflow, primary action
DashboardGrid / DashboardGridItem
Layout-only tile grid with responsive reflow and variable spans. Carries no dashboard content of its own.
import { DashboardGrid, DashboardGridItem } from "@/design-system";
When to use
- Any tile-based overview where tiles differ in importance and width.
- When one tile should span the full row and others sit beside each other.
When not to use
- For arbitrary content grids with equal cells — plain Grid is enough.
- As a dashboard: it is a primitive, not a screen.
4 columns with variable spans
DetailLayout
Primary content with a secondary information column, for record, profile, settings and object-detail views.
import { DetailLayout } from "@/design-system";
When to use
- Record pages where metadata, related items or activity supports the main content.
- When the secondary column should follow the content on mobile.
When not to use
- For navigation beside content — use SidebarLayout.
- For two equally important panels — use SplitPanel.
Content + supporting details
Primary content
The main record body.
SplitPanel
Two content panels side by side at a fixed ratio, stacking below lg.
import { SplitPanel } from "@/design-system";
When to use
- Comparison views, editor + preview, form + summary.
- When both panels are equally important.
When not to use
- When the user should drag the divider — use ResizablePanelGroup.
- For a content/metadata relationship — use DetailLayout.
2:1 with a divider
SettingsLayout
Settings navigation beside the active settings panel. Adds no navigation of its own.
import { SettingsLayout } from "@/design-system";
When to use
- Multi-section settings, preferences and account areas.
- Whenever sections are navigated rather than scrolled.
When not to use
- For a single settings form — FormPageLayout is enough.
Navigation + panel
Section settings
Generic placeholder panel for the selected section.
FormPageLayout
Page shell for a single form: header, form sections, action footer — with an optional guidance aside.
import { FormPageLayout } from "@/design-system";
When to use
- Create/edit pages and multi-section forms.
- When the commit action belongs at the end of the page rather than inline.
When not to use
- For a short form inside a dialog or card — compose FormField directly.
- It arranges only: fields come from FormSection/FormField, actions from Button.
Header → sections → footer
TablePageLayout
Page shell for a collection view: header, toolbar, table, pagination — with one slot for empty/no-results/error/loading states.
import { TablePageLayout } from "@/design-system";
When to use
- Any list or table page that needs search, filters and paging.
- When empty and error states should occupy the same region as the table.
When not to use
- It recreates nothing: pass the existing DataTable, FilterBar, Pagination and state components.
Populated collection view
MasterDetailLayout
Master list beside a detail panel on desktop; a list → detail navigation flow below lg.
import { MasterDetailLayout } from "@/design-system";
When to use
- Inboxes, queues and browse-then-inspect workflows.
- When users move between records without losing their place in the list.
When not to use
- When a record deserves its own page — use DetailLayout.
- For navigation rather than records — use SidebarLayout.
Two panes (desktop) / list → detail (mobile)
Select a record, then narrow the window to see the mobile navigation pattern.