Layout Primitives
Box, Stack, and Inline — composable layout components that wrap flexbox and remove the need for utility-class repetition on common layout patterns.
Preview
Stack (vertical, gap-4)
First item
Second item
Third item
Inline (row, gap-2, wrapping)
Design
Systems
Components
Tokens
Motion
Accessibility
Stack row, justify-between
Title
Cancel
Save
Components
| Component | Description | Key props |
|---|---|---|
| Box | Polymorphic wrapper — renders as any HTML element via the as prop. | as, className |
| Stack | Flex column (default) or row with gap, align, and justify control. | direction, gap, align, justify, wrap, as |
| Inline | Shorthand for Stack direction=row wrap=true align=center. | gap, align, justify |
Gap scale
| Prop value | CSS gap | Use case |
|---|---|---|
| gap="1" | 4px | Icon + label tight coupling |
| gap="2" | 8px | Inline tags, chip groups |
| gap="3" | 12px | Form label + input |
| gap="4" | 16px | Default — card items, list rows |
| gap="6" | 24px | Section-level separation |
| gap="8" | 32px | Major layout regions |
Implementation
Stack.tsx
tsx
// Box — polymorphic wrapper, any HTML element
<Box as="section" className="p-6">
content
</Box>
// Stack — vertical flex column
<Stack gap="4">
<Card />
<Card />
<Card />
</Stack>
// Stack — horizontal row
<Stack direction="row" justify="between" align="center">
<Logo />
<NavLinks />
</Stack>
// Inline — row, wrapping, centered items (default)
<Inline gap="2">
<Tag>Design</Tag>
<Tag>Systems</Tag>
<Tag>Components</Tag>
</Inline>
// Props
// Box: as?, className?, + all native element props
// Stack: direction? ("col"|"row"), gap? (0–12),
// align?, justify?, wrap?, as?, className?
// Inline: same as Stack (direction fixed to "row")Guidelines
- →Use Stack instead of writing flex flex-col gap-4 inline — it communicates intent and enforces the spacing scale.
- →Box with as='section' or as='ul' keeps semantics correct without adding a wrapper div.
- →Inline defaults to wrap so it doesn't overflow on small screens — only set wrap={false} when truncation is intentional.
- →These primitives have no visual opinion — all surface styling (borders, backgrounds) comes from Tailwind utilities on the child elements.