Stack
Compose flexbox properties into two one-dimensional layout primitives — Stack for vertical and horizontal arrangements, with responsive direction switching.
<Stack> composes flexbox properties into two layout primitives: direction="horizontal" (the
default, wraps .hstack) for row arrangements and direction="vertical" (wraps .vstack) for
column arrangements. The concept originates from the open source
Pylon project.
For simple one-dimensional arrangements — a toolbar, a form's field list — <Stack> needs no
grid around it. Reach for <Flex> instead for more control than
Stack's fixed alignment defaults give — wrapping, main-axis justification, or no default alignment
at all. Reach for <Grid> for responsive column spans, start
lines, and two-dimensional row-and-column layouts.
A Tailwind build of @chassis-ui/css has the classes of gap only with its safelist loaded: see
Tailwind.
Vertical
direction="vertical" arranges children in a column. Items stretch to full width by default;
gap controls the spacing between them.
import { Stack } from '@chassis-ui/react'
export const Example = () => {
return (
<Stack direction="vertical" gap="md">
<div className="p-xs">First item</div>
<div className="p-xs">Second item</div>
<div className="p-xs">Third item</div>
</Stack>
)
}Horizontal
The default direction="horizontal" arranges children in a row, aligned to the start of the
cross axis. Items take only their natural width; gap controls the spacing between them.
import { Stack } from '@chassis-ui/react'
export const Example = () => {
return (
<Stack gap="md">
<div className="p-xs">First item</div>
<div className="p-xs">Second item</div>
<div className="p-xs">Third item</div>
</Stack>
)
}.ms-auto acts as a spacer, pushing following items to the far end:
import { Stack } from '@chassis-ui/react'
export const Example = () => {
return (
<Stack gap="md">
<div className="p-xs">First item</div>
<div className="p-xs ms-auto">Second item</div>
<div className="p-xs">Third item</div>
</Stack>
)
}Responsive direction
direction takes an object in place of a value to switch the direction at one or more
breakpoints: base is the direction from the narrowest width ('horizontal' when omitted), and
a key named after a breakpoint (sm/md/lg/xl/2xl) is the direction from that breakpoint
up, as in direction={{ base: 'vertical', md: 'horizontal' }}. The breakpoints are
container queries rather than viewport
media queries. gap takes the same object, gap={{ base: 'sm', md: 'lg' }}, but its gap-*
classes in @chassis-ui/css follow the viewport, so a direction and a gap on one Stack can
switch at different widths.
Responsive direction switching requires a .contains-inline ancestor to establish the container
query context — <Stack> doesn't apply this itself, since the containment has to live on a
parent of the element whose own layout is switching. Resize the browser to preview the
transition between column and row layouts below:
import { Stack } from '@chassis-ui/react'
export const Example = () => {
return (
<div className="contains-inline">
<Stack direction={{ base: 'vertical', sm: 'horizontal' }} gap={{ base: 'sm', sm: 'md' }}>
<button type="button" className="button primary">
Primary action
</button>
<button type="button" className="button primary outline">
Cancel
</button>
</Stack>
</div>
)
}API
Stack
| Prop | Type | Default |
|---|---|---|
asChild? | boolean | — |
Render the single child element in place of this component's own element, with this
component's classes, props and ref merged onto it: <Button asChild><Link href="/login">Log
in</Link></Button>. The alternative to component for React Server Components — an element
can be passed from the server to this package's client components, a component reference
(component={Link}) can't. | ||
className? | string | — |
| A string of all className you want applied to the component. | ||
component? | ElementType | — |
| Component used for the root node. Either a string to use a HTML element or a component. | ||
direction? | Responsive<"horizontal" | "vertical"> | — |
Lays children out in a row (horizontal, the default, maps to .hstack) or a column
(vertical, maps to .vstack). An object switches the direction from a breakpoint up:
{ base: 'vertical', md: 'horizontal' }. The breakpoints are container queries, so they
require a .contains-inline ancestor (not applied by Stack itself — see the docs) to
establish the container context they evaluate against. | ||
gap? | { Responsive<Spacing | 0> } | — |
Spacing between children, mapped to the gap-* utility classes. Takes an object per
breakpoint, as direction does: { base: 'sm', md: 'lg' }. | ||
ref? | any | — |