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";
2
3<Flex />

Usage

Flex maps the flexbox properties onto props. Set the direction first: the alignment props read against whichever axis it picks.

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 row
5 </Button>
6 <Button size="small" variant="outline">
7 is the
8 </Button>
9 <Button size="small" variant="outline">
10 default
11 </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 <Flex
4 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<Flex
2 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:

SlotElement
flexThe 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 rowReverse and columnReverse change only the visual order. Don't rely on them to convey sequence.
  • Use the render prop to swap in a semantic element (<nav>, <ul>, <section>) when the group has meaning beyond layout.