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.

First
Second
Third

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.

PropTypeDefault
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 | 164
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