Flex
A low-level flexbox layout primitive that exposes the full flex API — four directions, three wrap modes, independent row and column gap, align-items, justify-content, align-content, inline mode, polymorphic render, and LTR/RTL. Ships with FlexItem for per-child grow, shrink, basis, order, and alignSelf control.
Playground
Installation
pnpm add @tessinaui/uiUsage
import { Flex, FlexItem } from "@tessinaui/ui";{/* Row layout */}
<Flex direction="row" gap="md" align="center">
<Avatar src="/me.png" />
<div className="flex flex-col">
<p className="font-medium">Jane</p>
<p className="text-muted-foreground">jane@example.com</p>
</div>
</Flex>
{/* Column layout */}
<Flex direction="column" gap="sm">
<h2>Title</h2>
<p>Body</p>
<button>Action</button>
</Flex>
{/* Wrapping with independent gaps */}
<Flex direction="row" wrap="wrap" columnGap="xl" rowGap="sm">
{tags.map((t) => <Chip key={t}>{t}</Chip>)}
</Flex>
{/* Sidebar + main with FlexItem grow */}
<Flex direction="row" gap="md">
<aside className="w-48">Sidebar</aside>
<FlexItem grow>
<main>Main content fills the remaining space</main>
</FlexItem>
</Flex>
{/* Three columns with fractional basis */}
<Flex direction="row" gap="md">
<FlexItem basis="1/4">Left</FlexItem>
<FlexItem basis="2/4">Center</FlexItem>
<FlexItem basis="1/4">Right</FlexItem>
</Flex>
{/* Reorder with order prop */}
<Flex direction="row" gap="sm">
<FlexItem order="last">rendered last</FlexItem>
<div>rendered first</div>
<FlexItem order="first">rendered even earlier</FlexItem>
</Flex>
{/* Polymorphic */}
<Flex direction="row" gap="sm" render={<nav aria-label="Primary" />}>
<a href="/">Home</a>
<a href="/about">About</a>
</Flex>
{/* RTL */}
<Flex direction="row" dir="rtl" gap="sm">
<span>أول</span>
<span>ثاني</span>
</Flex>Showcase
Direction
Unlike Stack, Flex exposes all four flex-direction values directly.
| Value | CSS mapping |
|---|---|
"row" (default) | flex-row |
"column" | flex-col |
"row-reverse" | flex-row-reverse |
"column-reverse" | flex-col-reverse |
Wrap
| Value | CSS mapping |
|---|---|
"nowrap" (default) | flex-nowrap |
"wrap" | flex-wrap |
"wrap-reverse" | flex-wrap-reverse |
Gap
Seven presets that map to Tailwind's spacing scale.
| Value | Tailwind | px |
|---|---|---|
"none" | gap-0 | 0 |
"xs" | gap-1 | 4 |
"sm" | gap-2 | 8 |
"md" | gap-4 | 16 |
"lg" | gap-6 | 24 |
"xl" | gap-8 | 32 |
"2xl" | gap-12 | 48 |
For independent axis control use rowGap and columnGap — they accept the same seven values and override gap on their respective axis.
<Flex wrap="wrap" columnGap="xl" rowGap="sm">…</Flex>Align (align-items)
Cross-axis alignment of children.
| Value | CSS mapping |
|---|---|
"start" | items-start |
"center" | items-center |
"end" | items-end |
"stretch" (default) | items-stretch |
"baseline" | items-baseline |
Justify (justify-content)
Main-axis distribution.
| Value | CSS mapping |
|---|---|
"start" (default) | justify-start |
"center" | justify-center |
"end" | justify-end |
"between" | justify-between |
"around" | justify-around |
"evenly" | justify-evenly |
Content (align-content)
Applies only when wrap is enabled and there are multiple rows on the cross axis.
| Value | CSS mapping |
|---|---|
"start" | content-start |
"center" | content-center |
"end" | content-end |
"between" | content-between |
"around" | content-around |
"evenly" | content-evenly |
"stretch" | content-stretch |
"baseline" | content-baseline |
Inline
inline={true} swaps flex for inline-flex so the container flows alongside surrounding text or other inline-level elements.
Polymorphic render
Preserve Flex styling while mounting semantic HTML.
<Flex direction="row" gap="md" render={<nav aria-label="Primary" />}>
<a href="/">Home</a>
<a href="/about">About</a>
</Flex>
<Flex render={<section />} direction="column" gap="lg">
<h2>Settings</h2>
<p>Adjust your preferences below.</p>
</Flex>FlexItem
A helper for setting flex-child properties (flex-grow, flex-shrink, flex-basis, order, align-self) without reaching for Tailwind classes directly. FlexItem is optional — you can always apply grow, shrink-0, etc. inline on any child.
<Flex direction="row" gap="md">
<aside className="w-48">Sidebar</aside>
<FlexItem grow>
<main>Main (grows to fill)</main>
</FlexItem>
</Flex>grow
| Value | CSS |
|---|---|
true / 1 | grow |
false / 0 | grow-0 |
2, 3, 4, 5 | flex-grow: n |
shrink
| Value | CSS |
|---|---|
true / 1 | shrink |
false / 0 | shrink-0 |
2, 3, 4, 5 | flex-shrink: n |
basis
Presets cover fractional layouts without arbitrary values.
"auto" · "full" · "0" · "1/2" · "1/3" · "2/3" · "1/4" · "2/4" · "3/4" · "1/5" · "2/5" · "3/5" · "4/5" · "1/6" · "5/6" · "1/12" through "11/12"
order
| Value | CSS |
|---|---|
"none" | order-none |
"first" | order-first |
"last" | order-last |
1 – 12 | order-n |
alignSelf
"auto" · "start" · "center" · "end" · "stretch" · "baseline" → self-*
RTL
dir="rtl" is forwarded to the DOM node and flips the main axis of row directions. Column directions are unaffected by text direction.
Accessibility
- Flex is a structural primitive — it applies no ARIA roles.
- Use
renderto mount semantic HTML (<nav>,<ul>,<section>,<header>) when the grouping has meaning. - Reordering children with
orderorrow-reverse/column-reverseseparates visual order from DOM order. Keep DOM order logical — screen readers and keyboard navigation follow source order, not visual order. inlinedoes not remove any semantics — the element remains a<div>(or whateverrenderprovides).
When to use Flex vs. Stack
Both are flex wrappers. Pick based on how much of the flex API you actually need.
| Use Stack when… | Use Flex when… |
|---|---|
| You want a single-axis layout with sensible defaults | You need the full flexbox API |
| Direction should flip via a single prop | You want explicit row-reverse / column-reverse |
| Gap presets are enough | You need independent rowGap and columnGap |
| Children size themselves naturally | You need grow / shrink / basis / order on children |
For many apps Stack is the right pick. Reach for Flex when you're building a layout that can't be expressed through Stack's opinionated API.
API Reference
Flex Props
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "row" | "column" | "row-reverse" | "column-reverse" | "row" | flex-direction |
wrap | "nowrap" | "wrap" | "wrap-reverse" | "nowrap" | flex-wrap |
gap | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | — | Shorthand for both row and column gap |
rowGap | Same as gap | — | Vertical gap (overrides gap on that axis) |
columnGap | Same as gap | — | Horizontal gap (overrides gap on that axis) |
align | "start" | "center" | "end" | "stretch" | "baseline" | "stretch" | align-items |
justify | "start" | "center" | "end" | "between" | "around" | "evenly" | "start" | justify-content |
content | "start" | "center" | "end" | "between" | "around" | "evenly" | "stretch" | "baseline" | — | align-content — only relevant with wrap |
inline | boolean | false | Uses inline-flex instead of flex |
render | ReactElement | — | Polymorphic target — clone this element and apply Flex styles |
dir | "ltr" | "rtl" | — | Text direction forwarded to the DOM node |
className | string | — | Extra classes on the root element |
FlexItem Props
| Prop | Type | Default | Description |
|---|---|---|---|
grow | boolean | 0 | 1 | 2 | 3 | 4 | 5 | — | flex-grow |
shrink | boolean | 0 | 1 | 2 | 3 | 4 | 5 | — | flex-shrink |
basis | Fraction preset (see table above) | — | flex-basis |
order | "none" | "first" | "last" | 1..12 | — | order |
alignSelf | "auto" | "start" | "center" | "end" | "stretch" | "baseline" | — | align-self |
render | ReactElement | — | Polymorphic target |
dir | "ltr" | "rtl" | — | Text direction forwarded to the DOM node |
className | string | — | Extra classes on the root element |
Notes
- No intrinsic padding. Flex only controls layout — add padding, borders, background via
className. - No SSR caveats. Flex is a pure wrapper with no hooks; safe to render server-side.
contentis a prop, not an HTML attribute. React's nativecontentHTML attribute (meta-tag-only) is omitted from Flex's props so the CVA variant takes precedence.- Arbitrary values. If a fraction you need isn't in the
basispreset list, drop toclassName="basis-[...]"— FlexItem's class output is merged after its props.
Stack
A flex-based layout primitive for arranging items in a row or column. Configurable direction, gap, alignment, justification, wrapping, reversal, dividers, inline display, polymorphic rendering, and LTR/RTL support. Ships with HStack and VStack convenience wrappers.
Grid
A CSS-grid layout primitive with static and responsive column counts, gap presets, flow control, and per-cell placement via GridItem. Polymorphic render, RTL, and no hard-coded tokens.