Stack
Vertical spacing primitive.
Usage
<Stack gap=4> is display: flex; flex-direction: column; gap: 1rem, with the gap bound
to the spacing scale. align defaults to stretch, which is what you want for stacked form fields.
Why the API is narrow
There is no margin, padding, width or colour prop. That is deliberate.
Margin belongs to the parent. A component that sets its own outer margin
cannot be reused in a layout that spaces things differently — you end up overriding it, which
is worse than never having had it. And an each-generated list gets
even rhythm from one gap rather than a margin on every item plus a :last-child exception.
The gap is a token key, not a length. gap=4, not gap="17px". Constraining it is the whole point: it keeps vertical
rhythm consistent across the app instead of letting every screen invent its own spacing.
This library shipped the other version of this component before 1.0. Box took seventeen style props with
duplicate aliases — p/padding, m/margin, w/width — and concatenated inline style strings.
It had reinvented CSS with a worse syntax, and it was dropped rather than ported. The moment you
want something Stack does not express, reach for CSS: that is not a gap in the component, it is
the boundary working.
Keeping the markup semantic
Use as to render the element the content actually is — ul for a list, fieldset for grouped inputs, nav for navigation — instead of wrapping a div around it. List styling
is reset, so as="ul" stays semantic without looking like a bulleted list.
- List item one
- List item two
Props
Plus every native attribute of the element you render, via prop spreading. Reach for Flex when the direction is not vertical.
| Prop | Type | Default |
|---|---|---|
gap Vertical space between children, as a spacing token key — not an arbitrary length. That constraint is the point: it keeps rhythm consistent and stops this becoming a place to invent one-off spacing. | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16 | 4 |
align Cross-axis alignment. `stretch` (the default) lets children fill the width, which is what you want for stacked form fields. | 'start' | 'center' | 'end' | 'stretch' | 'stretch' |
as Element to render. Use it to keep the markup semantic — `ul` for a list, `fieldset` for grouped inputs — instead of wrapping a div around one. | 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'ul' | 'ol' | 'li' | 'nav' | 'form' | 'fieldset' | 'div' |
class Extra classes merged onto the element. | string | — |
children | Snippet | — |