Brik Design System
Build Standards

Composition Layers

Five conceptual layers — Section, Layout, Container, Block, Component — and the decision rules for assembling them.

A page in BDS is composed in five layers. Each has a single responsibility, a single vocabulary, and only knows about the layer below it. This model is pedagogical — it explains how to think about a page — and is intentionally non-binding on the BEM canon (ADR-008).

The five layers

LayerResponsibilityVocabularyExamples
SectionPage role with surrounding structure (vertical rhythm, container, background surface)Page-level semanticHero, Content, CTA
LayoutPure composition primitive — arranges children. No styling beyond structure.CompositionStack, Cluster, Grid, Split, Row
ContainerStyled holder that composes blocks into a self-contained unit. Carries border / padding / elevation / radius.Bounded unitCard, List, Form, Accordion, Tabs
BlockComposed content unit — fixed slot shape filled with atoms.Slot + atomsContentBlock, MediaBlock, ListItem, FormField, Stat
ComponentSingle primitive atom.One primitiveButton, Input, Image, Badge, Icon

Where each layer lives

LayerDirectoryNotes
Sectioncontent-system/blueprints/{react,astro}/Blueprint families per ADR-008 play the Section role
Layoutcomponents/ui/Stack, Cluster, Grid, Split, Row
Containercomponents/ui/Card, Accordion, List
Blockcomponents/ui/Field, Card preset="summary"
Componentcomponents/ui/Atomic primitives

Block vs container — decision rule

If the thing is described primarily by how its children are styled and bounded (border, elevation, padding, max-width) → it's a container. If it's described by what slots it offers and which atoms fill them (heading, body, kicker, action) → it's a block.

Card passes "styled and bounded" → container. ContentBlock passes "slots and atoms" → block.

Card is a styled container

A Card encodes only its container styling (border, radius, padding, elevation). Orientation comes from the layout primitive inside it, not a Card variant.

// ✅ Stacked card — Stack layout inside Card
<Card>
  <Stack>
    <MediaBlock />
    <ContentBlock />
  </Stack>
</Card>

// ✅ Horizontal card — Split layout inside Card
<Card>
  <Split>
    <MediaBlock />
    <ContentBlock />
  </Split>
</Card>

// ❌ Don't bake orientation into Card
<Card variant="horizontal">...</Card>
<Card layout="stacked">...</Card>

This keeps CardImageLeft, CardStacked, CardHorizontal from existing — they're all "Card + a layout child."

Stat is a block

Stat (value + label, two slots, no border styling) is a block, not a container. The bordered "stat tile" look is a Card containing a Stat.

// Bordered stat tile
<Card>
  <Stat value="75%" label="of website credibility comes from design" />
</Card>

// Card with content + metric
<Card>
  <ContentBlock title="First impressions" body="..." />
  <Stat value="0.05s" label="to make a first impression" />
</Card>

If you find yourself reaching for a StatCard, you're conflating block and container — write it as Card + Stat instead.

Container reference

ContainerPurposeWhen
DataSectionTitled block of read-mode data on a pageOverview / profile tabs, client-detail pages
SheetSectionTitled block inside a sheet body (uppercase label heading)Any grouping inside <Sheet>
Card (and variants)Bordered, self-contained content unitGrids of comparable items, dashboards, marketing
Board (BoardColumn, BoardCard)Kanban-style containerTask boards
Dialog / Modal / SheetOverlay containersFocused interactions

Don't reach for a Card when a DataSection is right. Cards are self-contained units in a grid; DataSection is one region of a larger page.

On this page