Skip to content
LuoForge/Tungsten
Components/Stack·Experimental

Stack

since v2.1.0

Vertical flex stack — enforces spacing-scale gap values.

Install

Add the package and import the component.

pnpm add @hey-mike/tungsten
pnpm add @hey-mike/tungsten
import { Stack } from '@hey-mike/tungsten';
import { Stack } from '@hey-mike/tungsten';

Preview

Same fixtures used by the visual-regression suite.

Usage

apps/docs/app/snapshots/stack/page.tsx

import { Stack } from '@hey-mike/tungsten';
import { HeroSpecimen } from '../_components/HeroSpecimen';

function Item({ label }: { label: string }) {
  return (
    <div className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-4 py-2 font-mono text-xs text-ink-2">
      {label}
    </div>
  );
}

export default function StackSnapshot() {
  return (
    <main data-testid="snapshot-root" className="bg-page text-ink-1 min-h-screen py-8">
      <h1 className="text-ink-2 mb-8 px-8 font-mono text-sm uppercase tracking-widest">Stack</h1>

      <dl className="flex flex-col gap-10 px-8">
        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=2</dt>
          <dd className="m-0">
            <Stack gap={2}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 (default)</dt>
          <dd className="m-0">
            <Stack gap={4}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=8</dt>
          <dd className="m-0">
            <Stack gap={8}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · align=center</dt>
          <dd className="m-0">
            <Stack gap={4} align="center">
              <Item label="short" />
              <Item label="a longer label" />
              <Item label="x" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · justify=between · fixed height</dt>
          <dd className="m-0 h-40">
            <Stack gap={4} justify="between" className="h-full">
              <Item label="top" />
              <Item label="middle" />
              <Item label="bottom" />
            </Stack>
          </dd>
        </div>
      </dl>

      {/* Gallery thumbnail (`?hero`): three stacked pills show the vertical
          rhythm. Hidden in the detail view; revealed by the hero CSS. */}
      <div data-hero-specimen className="hidden">
        <HeroSpecimen className="max-w-[160px]">
          <Stack gap={2}>
            <Item label="alpha" />
            <Item label="beta" />
            <Item label="gamma" />
          </Stack>
        </HeroSpecimen>
      </div>
    </main>
  );
}
import { Stack } from '@hey-mike/tungsten';
import { HeroSpecimen } from '../_components/HeroSpecimen';

function Item({ label }: { label: string }) {
  return (
    <div className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-4 py-2 font-mono text-xs text-ink-2">
      {label}
    </div>
  );
}

export default function StackSnapshot() {
  return (
    <main data-testid="snapshot-root" className="bg-page text-ink-1 min-h-screen py-8">
      <h1 className="text-ink-2 mb-8 px-8 font-mono text-sm uppercase tracking-widest">Stack</h1>

      <dl className="flex flex-col gap-10 px-8">
        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=2</dt>
          <dd className="m-0">
            <Stack gap={2}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 (default)</dt>
          <dd className="m-0">
            <Stack gap={4}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=8</dt>
          <dd className="m-0">
            <Stack gap={8}>
              <Item label="alpha" />
              <Item label="beta" />
              <Item label="gamma" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · align=center</dt>
          <dd className="m-0">
            <Stack gap={4} align="center">
              <Item label="short" />
              <Item label="a longer label" />
              <Item label="x" />
            </Stack>
          </dd>
        </div>

        <div>
          <dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · justify=between · fixed height</dt>
          <dd className="m-0 h-40">
            <Stack gap={4} justify="between" className="h-full">
              <Item label="top" />
              <Item label="middle" />
              <Item label="bottom" />
            </Stack>
          </dd>
        </div>
      </dl>

      {/* Gallery thumbnail (`?hero`): three stacked pills show the vertical
          rhythm. Hidden in the detail view; revealed by the hero CSS. */}
      <div data-hero-specimen className="hidden">
        <HeroSpecimen className="max-w-[160px]">
          <Stack gap={2}>
            <Item label="alpha" />
            <Item label="beta" />
            <Item label="gamma" />
          </Stack>
        </HeroSpecimen>
      </div>
    </main>
  );
}

Props

Surface specific to <Stack />.

PropTypeDefaultDescription
gap0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 124
align"start" | "center" | "end" | "stretch"Cross-axis alignment. baseline is intentionally absent — use Cluster for row/wrapping layouts.
justify"start" | "center" | "end" | "between" | "around"

Source