Stack
When to use
Section titled “When to use”- A form’s fields, or a card’s lines, down the page
- A row of buttons, or tags that wrap onto new lines
The space between children belongs to the Stack, not to margins on the children. A CSS reset can’t collapse it, and two margins never add up.
Choosing between laying out:
| Component | Use it for | For example |
|---|---|---|
| Stack | Children in one line, down or across, with a gap between them | A form’s fields, a row of buttons, tags |
| Grid | Children in equal columns, wrapping into rows | Cards, a gallery, a dashboard’s tiles |
| Table | Records compared across the same columns | Invoices, users, order lines |
| Toolbar | A row of controls reached with the arrow keys, as one Tab stop | A text editor’s formatting controls |
Project settingsA column of lines, a small step apart.
- React
- TypeScript
- CSS
- Accessibility
- Design tokens
Saved
import { Badge, Button, Chip, Stack } from '@arun-dev/ui';
export default function StackBasics() { return ( // A column — the default — with sections a medium gap apart. <Stack gap="md" style={{ inlineSize: 'min(100%, 28rem)' }}> <Stack gap="3xs"> <strong>Project settings</strong> <span className="text-color-secondary">A column of lines, a small step apart.</span> </Stack>
{/* A row that wraps: chips move to a new line when they run out of room. */} <Stack direction="row" gap="2xs" wrap render={<ul role="list" aria-label="Tags" />}> {['React', 'TypeScript', 'CSS', 'Accessibility', 'Design tokens'].map((tag) => ( <Chip key={tag} render={<li />}> {tag} </Chip> ))} </Stack>
{/* A row with its ends pushed apart, lined up down the middle. */} <Stack direction="row" justify="between" align="center"> <Badge tone="success">Saved</Badge> <Stack direction="row" gap="2xs"> <Button>Cancel</Button> <Button variant="primary">Publish</Button> </Stack> </Stack> </Stack> );}Stack is a flex container. gap takes a step on the spacing scale — 0, 3xs up to
3xl — the --space-* token of the same name.
| Prop | Type | Default | Description |
|---|---|---|---|
direction | 'column' | 'row' | 'column' | Down the page, or across it. |
gap | '0' | '3xs' | '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'sm' | Space between the children: the --space-* token of the same name. |
align | 'start' | 'center' | 'end' | 'baseline' | 'stretch' | 'stretch' | How children line up across the stack: across a column, or down a row. |
justify | 'start' | 'center' | 'end' | 'between' | 'start' | How children are spread along the stack. between pushes the ends apart. |
wrap | boolean | false | Lets children move onto a new line when they run out of room. |
className | string | Concatenated with the component's own classes, never replacing them. | |
render | ReactElement | Element or component to render instead of the default. Props, className, event handlers and ref are merged onto it. | |
ref | Ref<HTMLElement> | Ref to the rendered element. Merged with any ref on the render element. | |
…rest | HTMLAttributes | Anything else is spread onto the rendered element, so id, aria-*, data-* and event handlers all reach the DOM. |
- It renders a
<div>. Userenderfor the element the content needs:render={<ul role="list" />}for a list,render={<form />}for a form. A Stack drops a list’s markers itself;role="list"keeps it announced as a list in Safari. - For a layout that changes at a width, such as a column on phones and a row on wide screens,
add your own class with a media query. Or use a Grid with
minItemSize, which needs no breakpoints. - Without React, the
stackandspace-*utility classes give a column with a gap.