Stack

Flex layout primitives with typed responsive gap and direction, alignment, and optional asChild composition.

<VStack className="w-full max-w-md">  <DecorativeBox className="h-10" />  <DecorativeBox className="h-10" />  <DecorativeBox className="h-10" /></VStack>

Usage

import { HStack, Stack, VStack } from "@reva/ui";

Stack is a thin wrapper around Flex that adds opinionated defaults: gap-2, vertical direction, and smart cross-axis alignment (stretch when vertical, start when horizontal). HStack and VStack set direction for you.

For un-opinionated flex, responsive direction objects ({ default: "column", md: "row" }), or CSS-native direction names ("row" / "column"), use Flex directly.

Examples

Horizontal

Use the direction prop to change the direction of the stack.

<Stack direction="horizontal" justify="center">  <DecorativeBox className="size-10" />  <DecorativeBox className="size-10" />  <DecorativeBox className="size-10" />  <DecorativeBox className="size-10" /></Stack>

HStack

Alternatively, you can use the HStack to create a horizontal stack and align its children horizontally.

<HStack align="center" justify="center">  <DecorativeBox className="h-12 w-24" />  <DecorativeBox className="size-8" />  <DecorativeBox className="size-8" />  <DecorativeBox className="h-8 w-24" />  <DecorativeBox className="size-8" /></HStack>

VStack

Use the VStack to create a vertical stack and align its children vertically.

<VStack align="center"><DecorativeBox className="h-12 w-40" /><DecorativeBox className="size-12" /><DecorativeBox className="h-12 w-64" /></VStack>

Responsive Direction

Pass a responsive object to change direction at different breakpoints.

<Stack direction={{ default: "vertical", md: "horizontal" }} gap={4} className="w-full">  <DecorativeBox className="h-20 flex-1" />  <DecorativeBox className="h-20 flex-1" />  <DecorativeBox className="h-20 flex-1" /></Stack>

Gap

gap maps to Tailwind spacing steps (096 per the supported map). The default is 2 (gap-2). You can also pass a responsive object. Compare default spacing with gap={4}.

Default (gap-2)

gap={4}

<HStack gap={8} className="w-full" justify="center" wrap>  <VStack>    <p className="text-fg-muted text-2xs font-mono">Default (gap-2)</p>    <Stack direction="horizontal" className="rounded-md border border-border-default p-2">      <DecorativeBox className="size-12" />      <DecorativeBox className="size-12" />      <DecorativeBox className="size-12" />    </Stack>  </VStack>  <VStack>    <p className="text-fg-muted text-2xs font-mono">gap={4}</p>    <Stack direction="horizontal" gap={4} className="rounded-md border border-border-default p-2">      <DecorativeBox className="size-12" />      <DecorativeBox className="size-12" />      <DecorativeBox className="size-12" />    </Stack>  </VStack></HStack>

Responsive gap

gap accepts the same responsive object shape as direction (breakpoints: default, sm, md, lg, xl, 2xl, 3xl).

<VStack gap={{ default: 2, md: 4, lg: 6 }} className="w-full max-w-md">  <DecorativeBox className="h-10" />  <DecorativeBox className="h-10" />  <DecorativeBox className="h-10" /></VStack>

Align and justify

Use align for items-* and justify for justify-*.

Left
Right
<HStack  justify="between"  align="center"  className="h-24 w-full max-w-md rounded-md border border-border-default px-3">  <DecorativeBox>Left</DecorativeBox>  <DecorativeBox>Right</DecorativeBox></HStack>

Child self-alignment

Default VStack alignment is stretch. Override a single child with self-center (or other self-* utilities).

Full width
Centered
Full width
<VStack gap={4} className="w-full max-w-md rounded-md border border-border-default p-3">  <DecorativeBox>Full width</DecorativeBox>  <DecorativeBox className="self-center">Centered</DecorativeBox>  <DecorativeBox>Full width</DecorativeBox></VStack>

asChild

With asChild, layout props merge onto the child element (via Radix Slot). Use a semantic list while keeping flex row layout.

  • Alpha
  • Beta
  • Gamma
<HStack asChild gap={4} className="rounded-md border border-border-default p-4">  <ul className="m-0 list-none p-0">    <li><DecorativeBox>Alpha</DecorativeBox></li>    <li><DecorativeBox>Beta</DecorativeBox></li>    <li><DecorativeBox>Gamma</DecorativeBox></li>  </ul></HStack>

Accessibility

Stack, HStack, and VStack are non-interactive layout wrappers. By default they render a div. Use asChild to attach layout to a semantic element (for example ul / nav) when structure matters for assistive technology. They do not set role or aria-* attributes—handle those on children when needed.

Props

Stack

Extends React.ComponentPropsWithoutRef<"div"> with the props below.

PropTypeDefaultDescription
direction"horizontal" | "vertical" or responsive object"vertical"Main axis. Responsive: { default: "vertical", md: "horizontal" }.
gapSpacing step (096 per the supported map) or responsive object2gap-*. Responsive: { default: 2, md: 4, xl: 6 }.
align"start" | "end" | "center" | "stretch" | "baseline"See descriptionMaps to items-*. If omitted: vertical stacks use stretch, horizontal stacks use start.
justify"start" | "end" | "center" | "between" | "around" | "evenly"Maps to justify-*.
wrapboolean | "wrap" | "nowrap" | "wrap-reverse"Flex wrap behaviour.
asChildbooleanfalseMerge props onto the single child via Slot.

HStack and VStack

Same props as Stack except direction: HStack fixes direction to "horizontal", VStack to "vertical". Use HStackProps and VStackProps from @reva/ui (Omit<StackProps, "direction">).

On this page