Flex
A layout primitive that arranges children in a row or column, with props for alignment, spacing, and wrapping.
Overview
Flex is the workhorse layout primitive: a div with display: flex and props for direction, align, justify, wrap, and gap, so you rarely write flexbox CSS by hand. By default it lays children out in a row (direction="row", align="stretch", justify="start", wrap="noWrap"). Reach for it whenever you're stacking or spacing things along one axis — toolbars, form rows, sidebars. For two-dimensional layouts use Grid, and for a page-width wrapper use Container.
Anatomy
Import and assemble the component:
1import { Flex } from "@raystack/apsara";23<Flex />
Usage
Nesting
Nest Flex containers to compose a layout: here an outer row — the default direction — holds two columns, each spaced with gap.
1<Flex gap={9}>2 <Flex gap={5} direction="column">3 <Button>Primary button</Button>4 <Button>Primary button</Button>5 <Button>Primary button</Button>6 </Flex>7 <Flex gap={5} direction="column">8 <Button>Primary button</Button>9 <Button>Primary button</Button>10 <Button>Primary button</Button>11 </Flex>12</Flex>
Direction
row is the default. column stacks children instead. The reverse variants flip the visual order without touching the DOM order, so keyboard and screen-reader order stay put.
1<Flex direction="column" gap={5}>2 <Flex direction="row" gap={3}>3 <Button size="small" variant="outline">4 row5 </Button>6 <Button size="small" variant="outline">7 is the8 </Button>9 <Button size="small" variant="outline">10 default11 </Button>12 </Flex>13 <Flex direction="column" gap={3} style={{ width: "fit-content" }}>14 <Button size="small" variant="outline">15 column
Justify
justify distributes children along the main axis. between pushes the first and last to the edges, which is the usual way to build a toolbar with actions on both sides.
1<Flex direction="column" gap={4} style={{ width: "100%" }}>2 {["start", "center", "end", "between"].map((j) => (3 <Flex4 key={j}5 justify={j}6 gap={3}7 style={{8 width: "100%",9 padding: 8,10 border: "1px dashed var(--rs-color-border-base-primary)",11 borderRadius: 4,12 }}13 >14 <Badge>{j}</Badge>15 <Badge>b</Badge>
Align
align positions children on the cross axis. center is what pulls a row of mixed heights — an icon, a label, a button — onto one optical line. baseline aligns their text instead.
1<Flex2 gap={4}3 align="center"4 style={{5 height: 90,6 padding: 8,7 border: "1px dashed var(--rs-color-border-base-primary)",8 borderRadius: 4,9 }}10>11 <Badge>align</Badge>12 <Text size="large">center</Text>13 <Button size="small">pulls a mixed-height row onto one line</Button>14</Flex>
Wrap
nowrap is the default, so children shrink rather than move to a new line. Set wrap when the item count is unbounded, like a row of tags.
1<Flex wrap="wrap" gap={3} style={{ maxWidth: 300 }}>2 {["alpha", "bravo", "charlie", "delta", "echo", "foxtrot"].map((t) => (3 <Badge key={t}>{t}</Badge>4 ))}5</Flex>
API Reference
Renders a flex container for layout.
Prop
Type
Slots
Every rendered part carries a stable data-slot attribute for styling and testing:
| Slot | Element |
|---|---|
flex | The flex container (or the element supplied via render) |
Accessibility
- Renders a plain
<div>and adds no roles or ARIA attributes — purely visual layout with no semantic meaning. - Screen readers read children in DOM order, so
rowReverseandcolumnReversechange only the visual order. Don't rely on them to convey sequence. - Use the
renderprop to swap in a semantic element (<nav>,<ul>,<section>) when the group has meaning beyond layout.