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

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.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import { Stack, HStack, VStack } from "@tessinaui/ui";
{/* Vertical stack (default) */}
<Stack gap="md">
  <div>First</div>
  <div>Second</div>
  <div>Third</div>
</Stack>

{/* Horizontal row */}
<Stack direction="horizontal" gap="sm" align="center">
  <Avatar src="/me.png" />
  <div>
    <p className="font-medium">Jane Doe</p>
    <p className="text-muted-foreground">jane@example.com</p>
  </div>
</Stack>

{/* Convenience wrappers */}
<HStack gap="sm">…</HStack>
<VStack gap="md">…</VStack>

{/* Dividers between items */}
<Stack
  direction="horizontal"
  align="center"
  divider={<span className="w-px self-stretch bg-border" />}
>
  <span>Home</span>
  <span>Products</span>
  <span>About</span>
</Stack>

{/* Wrapping with reverse order */}
<Stack direction="horizontal" wrap reverse gap="sm">
  {tags.map((t) => <Chip key={t}>{t}</Chip>)}
</Stack>

{/* Polymorphic — render as <nav> */}
<Stack
  direction="horizontal"
  gap="sm"
  render={<nav aria-label="Primary" />}
>
  <a href="/">Home</a>
  <a href="/about">About</a>
</Stack>

{/* RTL */}
<Stack direction="horizontal" dir="rtl" gap="sm">
  <span>أول</span>
  <span>ثاني</span>
  <span>ثالث</span>
</Stack>

Showcase

Direction

Switch between a column and a row with direction.

ValueFlex mapping
"horizontal"flex-row
"vertical" (default)flex-col

Combine with reverse to flip item order.

directionreverseResult
"horizontal"falseflex-row
"horizontal"trueflex-row-reverse
"vertical"falseflex-col
"vertical"trueflex-col-reverse

Gap

Controls the spacing between items (and between items and dividers when present).

ValueTailwindpx
"none"gap-00
"xs"gap-14
"sm"gap-28
"md" (default)gap-416
"lg"gap-624
"xl"gap-832
"2xl"gap-1248

Align (cross-axis)

Maps to flex align-items. In a vertical stack, this controls the horizontal alignment of children.

ValueFlex mapping
"start"items-start
"center"items-center
"end"items-end
"stretch" (default)items-stretch
"baseline"items-baseline

Justify (main-axis)

Maps to flex justify-content.

ValueFlex mapping
"start" (default)justify-start
"center"justify-center
"end"justify-end
"between"justify-between
"around"justify-around
"evenly"justify-evenly

Wrap

wrap={true} enables flex-wrap so items fall to a new line when the container cannot fit them on the main axis. Useful for chip groups, tag clouds, or responsive toolbars.

Divider

Pass any node to divider to render it between each child. Stack handles the interleaving — you just describe the separator.

<Stack
  direction="horizontal"
  align="center"
  gap="md"
  divider={<span className="w-px self-stretch bg-border" />}
>
  <span>Alpha</span>
  <span>Beta</span>
  <span>Gamma</span>
</Stack>

For vertical stacks, render a horizontal rule instead:

<Stack
  gap="md"
  divider={<span className="h-px self-stretch bg-border" />}
>…</Stack>

Inline

inline={true} swaps flex for inline-flex so the stack can sit inline with surrounding text or flow alongside other inline-block elements.

HStack and VStack

Direction-locked convenience wrappers that preserve the full API otherwise.

<HStack gap="sm">…</HStack>  {/* direction="horizontal" */}
<VStack gap="md">…</VStack>  {/* direction="vertical" */}

They accept every Stack prop except direction.

Polymorphic render

Keep Stack styling while swapping the underlying element for semantic HTML.

<Stack direction="horizontal" gap="sm" render={<nav aria-label="Primary" />}>
  <a href="/">Home</a>
  <a href="/about">About</a>
</Stack>

<Stack gap="sm" render={<ul />}>
  <li>First</li>
  <li>Second</li>
</Stack>

The passed element's existing className is merged with Stack's generated classes, and its own children (if any) are preserved over the Stack's children.

RTL

dir="rtl" flips the main-axis direction of horizontal stacks and is forwarded to the underlying element. Per-component dir means you can mix LTR and RTL stacks on the same page without changing the global document direction.

Accessibility

  • Stack is a structural layout primitive — it does not apply any ARIA roles on its own.

  • Use render to wrap semantic HTML (<nav>, <ul>, <section>, <header>) when the grouping has meaning. Keep <div> (the default) for purely presentational arrangements.

  • Dividers are cosmetic. Mark them as aria-hidden so they are not announced by screen readers:

    divider={<span aria-hidden className="w-px self-stretch bg-border" />}
  • focus-visible rings on Stack's children remain visible because Stack sets no overflow clipping.

API Reference

Stack Props

PropTypeDefaultDescription
direction"horizontal" | "vertical""vertical"Axis on which children flow
reversebooleanfalseReverses child order via flex-*-reverse
gap"none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl""md"Space between children
align"start" | "center" | "end" | "stretch" | "baseline""stretch"Cross-axis alignment (align-items)
justify"start" | "center" | "end" | "between" | "around" | "evenly""start"Main-axis distribution (justify-content)
wrapbooleanfalseEnables flex-wrap
inlinebooleanfalseUses inline-flex instead of flex
dividerReactNode—Node rendered between each direct child
renderReactElement—Polymorphic target — clones this element and applies Stack styling to it
dir"ltr" | "rtl"—Text / flow direction, forwarded to the DOM node
classNamestring—Additional classes on the root element

HStack / VStack

Both accept every prop above except direction, which is locked to "horizontal" and "vertical" respectively.

Notes

  • Default direction is vertical. This matches the convention of most React layout primitives (Chakra, Radix Themes) and reads naturally in JSX where children are typed top-to-bottom.
  • align="stretch" is the default. In a column, children expand to fill the horizontal width. Switch to "start", "center", or "end" to let children size themselves.
  • Divider interleaving uses React.Children.toArray, so keyed lists (.map() output) work without warnings — Stack assigns its own keys to the divider fragments.
  • render precedence: when passed, Stack renders the provided element type with its original props merged in, its original className concatenated with Stack's generated classes, and its original children (if any) preserved over the Stack's children.
  • No SSR caveats. Stack is a pure layout primitive with no hooks beyond useMemo for divider interleaving — safe to render on the server.

Container

A layout primitive that constrains content to a maximum width, applies consistent horizontal padding, and centers it within the viewport. Seven sizes, seven padding presets, polymorphic rendering, and RTL support.

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.

On this page

PlaygroundInstallationUsageShowcaseDirectionGapAlign (cross-axis)Justify (main-axis)WrapDividerInlineHStack and VStackPolymorphic renderRTLAccessibilityAPI ReferenceStack PropsHStack / VStackNotes