Stack
A 1D flexbox layout shorthand for arranging children vertically or horizontally with consistent spacing, alignment, and wrapping controls.
Installation
npm install @designforge/uiUsage
import { Stack, stackVariants } from "@designforge/ui";Examples
Vertical Stack (Default)
The default Stack flows children top-to-bottom with gap={4}.
import { Stack } from "@designforge/ui";
export default function VerticalStack() {
return (
<Stack>
<div className="p-3 border rounded-md">First item</div>
<div className="p-3 border rounded-md">Second item</div>
<div className="p-3 border rounded-md">Third item</div>
</Stack>
);
}Horizontal Stack
Set direction="horizontal" to arrange children in a row.
import { Stack } from "@designforge/ui";
export default function HorizontalStack() {
return (
<Stack direction="horizontal" gap={4}>
<div className="px-4 py-2 bg-muted rounded-md">Alpha</div>
<div className="px-4 py-2 bg-muted rounded-md">Beta</div>
<div className="px-4 py-2 bg-muted rounded-md">Gamma</div>
</Stack>
);
}Centered Stack
Use align="center" and justify="center" together to center children on both axes.
import { Stack } from "@designforge/ui";
export default function CenteredStack() {
return (
<Stack align="center" justify="center" className="h-40 border rounded-xl">
<p className="text-sm font-medium">Centered content</p>
<p className="text-xs text-muted-foreground">Both axes aligned</p>
</Stack>
);
}Justify Between
Use justify="between" in a horizontal stack to push items to the edges.
import { Stack } from "@designforge/ui";
export default function JustifyBetween() {
return (
<Stack direction="horizontal" justify="between" align="center" className="w-full px-4 py-3 border rounded-lg">
<span className="font-medium text-sm">Section Title</span>
<button className="text-sm text-primary hover:underline">View all</button>
</Stack>
);
}Navigation Links
A horizontal Stack is a clean way to build a top-level navigation bar.
import { Stack } from "@designforge/ui";
export default function NavLinks() {
const links = ["Products", "Pricing", "Docs", "Blog", "Support"];
return (
<nav>
<Stack direction="horizontal" gap={1} align="center">
{links.map((link) => (
<a
key={link}
href="#"
className="px-3 py-2 rounded-md text-sm hover:bg-muted transition-colors"
>
{link}
</a>
))}
</Stack>
</nav>
);
}Form Fields
Vertically stacked form fields with controlled spacing.
import { Stack } from "@designforge/ui";
export default function FormFields() {
return (
<form className="w-80">
<Stack gap={5}>
<div className="space-y-1.5">
<label htmlFor="name" className="text-sm font-medium">Full name</label>
<input
id="name"
type="text"
placeholder="Jane Smith"
className="w-full px-3 py-2 border rounded-md text-sm"
/>
</div>
<div className="space-y-1.5">
<label htmlFor="email" className="text-sm font-medium">Email</label>
<input
id="email"
type="email"
placeholder="jane@example.com"
className="w-full px-3 py-2 border rounded-md text-sm"
/>
</div>
<div className="space-y-1.5">
<label htmlFor="message" className="text-sm font-medium">Message</label>
<textarea
id="message"
rows={4}
placeholder="Your message..."
className="w-full px-3 py-2 border rounded-md text-sm resize-none"
/>
</div>
<button
type="submit"
className="w-full py-2 bg-primary text-primary-foreground rounded-md text-sm font-medium"
>
Send message
</button>
</Stack>
</form>
);
}Card List
Map a data array into a vertically stacked list of cards.
import { Stack } from "@designforge/ui";
const users = [
{ name: "Alice Chen", role: "Design Lead" },
{ name: "Marcus Webb", role: "Frontend Engineer" },
{ name: "Priya Nair", role: "Product Manager" },
];
export default function CardList() {
return (
<Stack gap={3} className="w-72">
{users.map((user) => (
<div
key={user.name}
className="flex items-center gap-3 p-3 border rounded-lg hover:bg-muted/50 transition-colors"
>
<div className="h-9 w-9 rounded-full bg-muted flex items-center justify-center font-medium text-sm">
{user.name[0]}
</div>
<div>
<p className="text-sm font-medium">{user.name}</p>
<p className="text-xs text-muted-foreground">{user.role}</p>
</div>
</div>
))}
</Stack>
);
}Mixed Gap
Nest Stacks with different gap values to achieve hierarchy in spacing.
import { Stack } from "@designforge/ui";
export default function MixedGap() {
return (
<Stack gap={8} className="w-80">
{/* Tight group */}
<Stack gap={2}>
<p className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
Recent
</p>
<div className="p-3 border rounded-md text-sm">Invoice #1042</div>
<div className="p-3 border rounded-md text-sm">Invoice #1041</div>
</Stack>
{/* Loose group */}
<Stack gap={6}>
<p className="text-xs font-semibold text-muted-foreground uppercase tracking-wider">
Archived
</p>
<div className="p-3 border rounded-md text-sm">Invoice #1040</div>
<div className="p-3 border rounded-md text-sm">Invoice #1039</div>
</Stack>
</Stack>
);
}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "vertical" | "horizontal" | "vertical" | Controls whether children are arranged in a column or a row. |
gap | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 4 | Spacing between children using Tailwind gap tokens. |
align | "start" | "center" | "end" | "stretch" | — | Cross-axis alignment (align-items). Defaults to browser default when unset. |
justify | "start" | "center" | "end" | "between" | — | Main-axis justification (justify-content). Defaults to browser default when unset. |
wrap | boolean | false | When true, children wrap onto new lines when the container is too narrow. |
className | string | — | Additional Tailwind or custom classes applied to the Stack container. |
ref | React.Ref<HTMLDivElement> | — | Forwarded ref to the underlying <div> element. |
Accessibility
- Stack renders a plain
<div>with no implicit ARIA role. Its purpose is purely compositional layout. - Avoid using Stack as the sole semantic structure for content that requires a list relationship. When children are semantically a list, use a
<ul>or<ol>with<li>elements and apply Stack styling throughclassNameor wrap the list element. - Nesting Stacks deeply does not introduce any additional accessibility concerns, as each is invisible to assistive technology as a structural container.
- When using
direction="horizontal"for navigation, wrap the Stack inside a<nav>element and ensure each child link has a descriptive label.