Stack
Overview
The Stack component arranges its children in a vertical or horizontal stack with consistent spacing.
It’s ideal for layouts like button groups, form fields, navigation links, and responsive arrangements.
Preview
- Preview
- Code
<Stack
direction="vertical"
align="stretch"
justify="start"
spacing="normal"
wrap={false}
>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</Stack>
Installation
- npm
- Yarn
- pnpm
- manual
npx @mindfiredigital/ignix-ui add stack
yarn @mindfiredigital/ignix-ui add stack
pnpm @mindfiredigital/ignix-ui add stack
import React from "react";
import clsx from "clsx";
type StackDirection = "vertical" | "horizontal" | "responsive";
type StackAlign = "start" | "center" | "end" | "stretch";
type StackJustify = "start" | "center" | "end" | "between" | "around";
type StackSpacing = "none" | "xs" | "sm" | "normal" | "lg" | "xl" | string;
interface ResponsiveProp {
mobile?: StackDirection;
tablet?: StackDirection;
desktop?: StackDirection;
}
export interface StackProps extends React.HTMLAttributes<HTMLDivElement> {
direction?: StackDirection;
align?: StackAlign;
justify?: StackJustify;
spacing?: StackSpacing;
wrap?: boolean;
responsive?: ResponsiveProp;
children: React.ReactNode;
className?: string;
}
const directionMap = {
vertical: "flex-col",
horizontal: "flex-row",
};
const alignMap = {
start: "items-start",
center: "items-center",
end: "items-end",
stretch: "items-stretch",
};
const justifyMap = {
start: "justify-start",
center: "justify-center",
end: "justify-end",
between: "justify-between",
around: "justify-around",
};
const spacingMap = {
none: "gap-0",
xs: "gap-1",
sm: "gap-2",
normal: "gap-4",
lg: "gap-8",
xl: "gap-12",
};
export const Stack: React.FC<StackProps> = ({
direction = "vertical",
align = "stretch",
justify = "start",
spacing = "normal",
wrap = false,
responsive,
className,
children,
...rest
}) => {
// Responsive direction classes
const responsiveClasses: string[] = [];
if (responsive) {
if (responsive.mobile)
responsiveClasses.push(
responsive.mobile === "vertical" || responsive.mobile === "horizontal"
? directionMap[responsive.mobile]
: ""
);
if (responsive.tablet) {
responsiveClasses.push(
responsive.tablet === "vertical" || responsive.tablet === "horizontal"
? `sm:${directionMap[responsive.tablet]}`
: ""
);
}
if (responsive.desktop) {
responsiveClasses.push(
responsive.desktop === "vertical" || responsive.desktop === "horizontal"
? `md:${directionMap[responsive.desktop]}`
: ""
);
}
}
return (
<div
className={clsx(
"flex",
direction === "vertical" || direction === "horizontal"
? directionMap[direction]
: "",
alignMap[align],
justifyMap[justify],
(spacing in spacingMap ? spacingMap[spacing as keyof typeof spacingMap] : spacing),
wrap && "flex-wrap",
...responsiveClasses,
className
)}
{...rest}
>
{children}
</div>
);
};
Usage
Import the component:
import { Stack } from './components/ui';
Basic Usage
<Stack responsive={{ mobile: "vertical", tablet: "horizontal", desktop: "horizontal" }}>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</Stack>
Props
Prop | Type | Default | Description |
---|---|---|---|
direction | string | "vertical" | Stack direction: "vertical", "horizontal", "responsive" |
align | string | "stretch" | Alignment: "start", "center", "end", "stretch" |
justify | string | "start" | Justify: "start", "center", "end", "between", "around" |
spacing | string | "normal" | Space between items: "none", "xs", "sm", "normal", "lg", "xl", or custom |
wrap | boolean | false | Allow items to wrap to next line |
responsive | object | Responsive direction: mobile, tablet, desktop | |
className | string | Additional CSS classes | |
children | node | Content inside the stack |
Use Cases
- 👉 Horizontal button groups
- 👉 Vertical form layouts
- 👉 Navigation links in a header
- 👉 Responsive layouts (switch direction on mobile)