Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsLayout Blocks

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/ui

Usage

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

ValueCSS 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

ValueTailwindpx
"none"—0
"xs"w-1 / h-1 / size-14
"sm"w-2 / h-2 / size-28
"md" (default)w-4 / h-4 / size-416
"lg"w-6 / h-6 / size-624
"xl"w-8 / h-8 / size-832
"2xl"w-12 / h-12 / size-1248
"3xl"w-16 / h-16 / size-1664

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 spaceAll siblings need the same gapYou need a visible line with semantic separation
You want to push elements apart (grow)Regular rhythm across a layoutContent has meaningful groupings
You're in a layout that doesn't support gapModern flex or grid layoutAccessibility 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

PropTypeDefaultDescription
axis"horizontal" | "vertical" | "both""both"Which dimension the size applies to
size"none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl""md"Spacer dimension
growbooleanfalseWhen true, adds flex-grow: 1 to fill remaining space
renderReactElement—Polymorphic target
aria-hiddenbooleantrueAccessible by default hidden; pass false to expose it
classNamestring—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 gap works, but the final gap between siblings is gap + Spacer size. If that's unexpected, drop the gap or set the Spacer to size="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.

On this page

PlaygroundInstallationUsageShowcaseAxisSizeGrowPolymorphic renderAccessibilityWhen to use Spacer vs. gap vs. DividerAPI ReferenceSpacer PropsNotes