Stack

Layers its children into a peeking deck (first child on top). With interactive, clicking (or Enter/Space) cycles the front card to the back so you can flip through the deck; the re-stack animates.

Real use · interactive peeking deck (click to cycle)

1
2
3

Peek direction

1
2
3
1
2
3
1
2
3
1
2
3

Fan distance

xs
1
2
3
sm
1
2
3
md
1
2
3
lg
1
2
3
xl
1
2
3

Large cards · the peek scales with the card

480 × 448
1
2
3
480 × 448 · [--stack-peek:4%]
1
2
3

Using Stack

Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.

Plain HTML — CSS classes

The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path is complete for Stack — it needs no JavaScript, so the classes below are the whole story.

/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";

Root class stack, with 8 modifiers:

  • .stack
  • .stack-bottom
  • .stack-end
  • .stack-lg
  • .stack-md
  • .stack-sm
  • .stack-start
  • .stack-xl
  • .stack-xs

React

Typed components over those same classes, with behavior and accessibility from Base UI.

npm i @wizeworks/silicaui-react
import { Stack } from "@wizeworks/silicaui-react";

Props

PropTypeRequiredDescription
peekStackPeeknoWhich way the deck peeks. top (default), bottom, start, or end.
sizeSilicaSizenoHow far the deck fans, as a share of the card's own size — xs (2%) through xl (9%), default md (5%). It scales with the card, so one value reads the same on a 128px thumbnail and a 600px hero card.
interactivebooleannoMake the deck clickable — sends the front card to the back to reveal the next.

Source of the demo above

The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.

Show source
import { Stack, Card, CardBody } from "@wizeworks/silicaui-react";
import type { SilicaSize } from "@wizeworks/silicaui-react";
import { Section, LabeledRow } from "../lib/Section";

const CARDS = [
    { label: "1", tone: "bg-primary text-primary-content" },
    { label: "2", tone: "bg-secondary text-secondary-content" },
    { label: "3", tone: "bg-accent text-accent-content" },
];

/**
 * The deck's three cards. A `stack` stretches its children to its own WIDTH but
 * leaves their height to them, so the height class goes here on the card — not
 * on the `<Stack>`, where it would size an empty box around content-height
 * cards and make the fan look far smaller than asked for.
 */
function Deck({ card, body }: { card: string; body: string }) {
    return (
        <>
            {CARDS.map((c) => (
                <Card key={c.label} className={`${c.tone} ${card}`}>
                    <CardBody className={`items-center justify-center ${body}`}>
                        {c.label}
                    </CardBody>
                </Card>
            ))}
        </>
    );
}

export function StackDemo() {
    return (
        <>
            <Section title="Real use · interactive peeking deck (click to cycle)">
                <Stack interactive className="w-48" data-demo="interactive">
                    <Deck card="h-32" body="text-2xl font-bold" />
                </Stack>
            </Section>

            <Section title="Peek direction">
                <div className="flex gap-8">
                    {(["top", "bottom", "start", "end"] as const).map((peek) => (
                        <Stack
                            key={peek}
                            peek={peek}
                            className="w-28"
                            data-demo={`dir-${peek}`}
                        >
                            <Deck card="h-20" body="text-sm" />
                        </Stack>
                    ))}
                </div>
            </Section>

            <Section title="Fan distance">
                <div className="flex flex-wrap items-end gap-8">
                    {(["xs", "sm", "md", "lg", "xl"] as SilicaSize[]).map((size) => (
                        <LabeledRow key={size} label={size}>
                            <Stack
                                size={size}
                                className="w-32"
                                data-demo={`size-${size}`}
                            >
                                <Deck card="h-24" body="text-sm" />
                            </Stack>
                        </LabeledRow>
                    ))}
                </div>
            </Section>

            {/*
              The peek is a share of the card's own size, so it survives a real
              content-height card. Fixed-distance nudges did not: the shrink from
              `scale()` out-ran them and the deck collapsed to a single card above
              ~320px. Keep a large specimen here so that cannot come back
              unnoticed — e2e/stack-peek.spec.ts measures exactly these two.
            */}
            <Section title="Large cards · the peek scales with the card">
                <div className="flex flex-wrap items-end gap-10">
                    <LabeledRow label="480 × 448">
                        <Stack className="w-[480px]" data-demo="large">
                            <Deck card="h-[448px]" body="text-4xl" />
                        </Stack>
                    </LabeledRow>
                    <LabeledRow label="480 × 448 · [--stack-peek:4%]">
                        <Stack
                            className="w-[480px] [--stack-peek:4%]"
                            data-demo="large-tuned"
                        >
                            <Deck card="h-[448px]" body="text-4xl" />
                        </Stack>
                    </LabeledRow>
                </div>
            </Section>
        </>
    );
}

Vanilla — node tree to HTML

Stack — lowers to <div>, holding its children. Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.

npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviors
import { atom, toHtml } from "@wizeworks/silicaui-html";

const node = atom("Stack", "stack", { /* props */ }, [/* children */]);
const markup = toHtml(node);

Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "stack stack-primary" rather than passing a colour as a prop.

Takes children
yes
Hydrated by
nothing — this one is static markup

The full API for Stack, on every path, is available through the Silica MCP server.