Stack
Lays its children out in one column or one row, with a gap from the spacing scale. Use it for forms, toolbars, lists and anything that flows in one direction.
Installation
Set up Camaleo once (Installation), then import it. It has no state, so it renders on the server.
import { Stack } from "@camaleo/react";Anatomy
One flex element with data-slot="stack". Stacks nest: this page header is a row whose two children are stacks of their own.
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above.
gap={1} · Label and value: one idea
Invoice
#2026-118Due
11/20/2026gap={3} · Items in a list
gap={6} · Separate groups
Billing
#2026-118
Shipping
Belo Horizonte
Gap shows what belongs together
gap counts steps of --cml-space, so the rhythm follows the skin. Small gaps join a label to its value; large gaps separate groups.
Projects
12 active
Page header row
justify="space-between" puts the title on one side and the actions on the other. With wrap, the actions drop below the title on a phone.
Topics
- Design systems
- Accessibility
- React
- Performance
- Typography
- Dark mode
Tags that wrap
A row of tags should wrap, not scroll sideways or squeeze. It is also a ul, so screen readers say how many topics there are.
Account manager · Atlas
Row or column
Switch it on. The same three children turn from a row into a column; only direction changes, so the reading order stays the same.
Tab order 1
Tab order 2
Tab order 3
Tab follows what you see: left to right.
Visual order equals Tab order
Turn on row-reverse and press Tab: focus starts on the right. To put the main action at the end, place it last in the DOM and use justify="flex-end".
Workspace
Members
8 of 10 seats
Storage
34 GB of 100 GB
Plan
Team, monthly
Rows with dividers
Stack has no divider prop. Put a Separator between children and the gap spaces it evenly above and below.
On call this week
- Beatriz Santos
Backend
- João Pereira
Infrastructure
- Carla Mendes
Frontend
A list that stacks
as="ul" keeps list semantics while Stack handles the spacing. Remove the bullets and the indent with listStyle and padding.
Responsive without breakpoints
There are no breakpoint props. Give each child a minimum width with flex and turn on wrap: three fields in a row become one column on a phone.
In context
These are whole pieces of UI you can copy, in the skin you picked.
Order summary
Subtotal
$412.00
Shipping
$18.90
Coupon WELCOME10
−$41.20
Product designer · São Paulo
Create your workspace
Free for 14 days. No card needed.
Guidelines
Invoice #2026-118
Due 11/20/2026 · $1,240.00
Payment by bank transfer or card.
The title and its due date read as one thing, and the action stands apart.
Invoice #2026-118
Due 11/20/2026 · $1,240.00
Payment by bank transfer or card.
Every line is equally far from the next, so nothing says what belongs together.
Cancel comes first and Publish last, pushed to the end with justify="flex-end". Tab follows the eye.
It looks identical, but Tab now starts on the right and moves left, and screen readers read Publish before Cancel.
Props
as="ul").-reverse values only flip the picture: reading and Tab order still follow the DOM.--cml-space (0.25rem by default): gap={4} = 1rem.align-items).justify-content).as takes the same tags as Box. Every other prop goes to the element. Your style is merged after the custom properties, so it can override any of them.
Styling hooks
Each prop becomes a custom property on the element. Leave a prop out and your stylesheet can set its property instead, for example at a breakpoint.
Attributes
Tokens it reads
This component only
/* the actions bar becomes a row from 40rem up */
@media (min-width: 40rem) {
.actions[data-slot="stack"] {
--cml-stack-direction: row;
--cml-stack-justify: flex-end;
}
}Accessibility
- Visual order must match DOM order. column-reverse and row-reverse only move the picture: Tab and screen readers still follow the DOM, so reorder the JSX instead.
- Wrapping keeps the DOM order too: items flow left to right, then on to the next line, which is the order people read.
- Space is not meaning. If items form a list, render as="ul"; if a group needs a name, give it a heading.
- Use as for landmarks and forms (as="form", as="nav") so the semantics come with the layout.