Spacer
A decorative gap-filler. Three axis modes, eight sizes, optional grow-to-fill behaviour, and polymorphic render. Accessibility-hidden by default — screen readers skip it.
Playground
Installation
pnpm add @tessinaui/uiUsage
import { Spacer } from "@tessinaui/ui";{/* Fixed horizontal gap between inline elements */}
<div className="flex items-center">
<span>Hello</span>
<Spacer axis="horizontal" size="md" />
<span>World</span>
</div>
{/* Fixed vertical gap between blocks */}
<div className="flex flex-col">
<h2>Title</h2>
<Spacer axis="vertical" size="lg" />
<p>Body</p>
</div>
{/* Push apart — grow fills remaining space */}
<header className="flex items-center">
<Logo />
<Spacer grow />
<UserMenu />
</header>
{/* Navbar with grouped left/right clusters */}
<nav className="flex items-center gap-2">
<Logo />
<NavLink>Home</NavLink>
<NavLink>Docs</NavLink>
<Spacer grow />
<Button variant="ghost">Sign in</Button>
<Button>Sign up</Button>
</nav>Showcase
Axis
| Value | CSS applied |
|---|---|
"horizontal" | width-only (w-*) — Spacer becomes inline-block |
"vertical" | height-only (h-*) — Spacer stays block |
"both" (default) | size-* — Spacer is square on both axes |
In a horizontal flex container use axis="horizontal"; in a column stack use axis="vertical"; inside grids, axis="both" keeps the Spacer square.
Size
| Value | Tailwind | px |
|---|---|---|
"none" | — | 0 |
"xs" | w-1 / h-1 / size-1 | 4 |
"sm" | w-2 / h-2 / size-2 | 8 |
"md" (default) | w-4 / h-4 / size-4 | 16 |
"lg" | w-6 / h-6 / size-6 | 24 |
"xl" | w-8 / h-8 / size-8 | 32 |
"2xl" | w-12 / h-12 / size-12 | 48 |
"3xl" | w-16 / h-16 / size-16 | 64 |
Grow
<Spacer grow />When grow is true, the Spacer adds flex-grow: 1. In a flex parent this makes the Spacer fill all remaining space — the canonical "push apart" pattern for toolbars and navigation. When grow is false (the default), the Spacer's size is strictly the size prop.
grow and size can be combined: grow takes precedence in a flex parent, but the size still applies when the parent has enough room to honour it.
Polymorphic render
Replace the default <div> with any element.
<Spacer render={<hr />} axis="vertical" size="xl" />Accessibility
Spacer sets aria-hidden="true" by default — screen readers skip it entirely. If you need the element to be perceivable (e.g. for demonstration or a decorative element with meaning), pass aria-hidden={false}.
For semantic separation between sections, prefer Divider — it's a proper <hr> with ARIA support.
When to use Spacer vs. gap vs. Divider
| Use Spacer when… | Use gap when… | Use Divider when… |
|---|---|---|
| Only some siblings need extra space | All siblings need the same gap | You need a visible line with semantic separation |
You want to push elements apart (grow) | Regular rhythm across a layout | Content has meaningful groupings |
You're in a layout that doesn't support gap | Modern flex or grid layout | Accessibility benefits from <hr> |
In most cases prefer gap on the parent — it's terser and avoids extra DOM nodes. Reach for Spacer when the spacing is uneven or when you need the grow behaviour.
API Reference
Spacer Props
| Prop | Type | Default | Description |
|---|---|---|---|
axis | "horizontal" | "vertical" | "both" | "both" | Which dimension the size applies to |
size | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "md" | Spacer dimension |
grow | boolean | false | When true, adds flex-grow: 1 to fill remaining space |
render | ReactElement | — | Polymorphic target |
aria-hidden | boolean | true | Accessible by default hidden; pass false to expose it |
className | string | — | Extra classes |
Notes
- No intrinsic margin. Spacer doesn't push its siblings via margin — it takes its own space in the layout.
- No hooks. Pure wrapper, safe for SSR.
- Combining with gap. Using Spacer inside a flex container that already has a
gapworks, but the final gap between siblings isgap + Spacer size. If that's unexpected, drop thegapor set the Spacer tosize="none"+grow.
AspectRatio
Constrains content to a specific width/height ratio using CSS aspect-ratio. Seven named presets, arbitrary string or numeric ratios, eight corner-radius presets, automatic object-fit on single media children, and polymorphic render.
Card
A flexible surface container for grouping related content. Four variants (elevated/outlined/filled/ghost), five intents, six rounded options, five sizes, horizontal layout, interactive states, and LTR/RTL support.