Layout Components
Stack
A flexible layout component that arranges its children with consistent spacing. It can be used for both vertical and horizontal layouts.
A vertical flex container with built-in padding and flexWrap. Think of Stack as Col plus padding and wrap — reach for it when you want a self-contained surface that breathes, not a structural skeleton.
Basic Stack
Stack defaults to column, flex, gap, padding, flexWrap, md, noBorder, noRing, outline, and sharp — you don't need to pass any of these. Pass href to render Stack as <a> instead of <div> — a focus-visible outline auto-enables when href is set.
<Stack> <div className="p-4 bg-gray-100 rounded">Item 1</div> <div className="p-4 bg-gray-100 rounded">Item 2</div> <div className="p-4 bg-gray-100 rounded">Item 3</div></Stack>Stack vs Col
Stack and Col are both vertical flex columns. The difference is opinion:
Use Stack when the column owns its own breathing room. Use Col when an outer Card / Section / Container already supplies the padding.
Stack (padded by default)
Col (no padding)
<Row itemsStart> <Col flex1> <Text semibold>Stack (padded by default)</Text> <Stack className="border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> </Col> <Col flex1> <Text semibold>Col (no padding)</Text> <Col className="border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Col> </Col></Row>Stack Direction
Use row for horizontal layout. Default is column (vertical).
column (default)
row
<Row itemsStart> <Col flex1> <Text semibold>column (default)</Text> <Stack className="border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> </Col> <Col flex1> <Text semibold>row</Text> <Stack row className="border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> </Col></Row>Stack Spacing
Use size props (xs, sm, md, lg, xl) to scale gap and padding together, or noGap to remove the gap.
xs
sm
md (default)
lg
xl
<Row itemsStart> <Stack xs flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>xs</Text> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> <Stack sm flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>sm</Text> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> <Stack flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>md (default)</Text> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> <Stack lg flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>lg</Text> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack> <Stack xl flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>xl</Text> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> </Stack></Row>Padding Sizes
padding is on by default. The padding value scales with the size prop. Use noPadding to remove it entirely.
xs padding
md padding (default)
xl padding
noPadding
<Row itemsStart> <Stack xs filled secondary flex1> <Text semibold>xs padding</Text> <div className="p-2 bg-white/80 rounded">Item</div> </Stack> <Stack filled secondary flex1> <Text semibold>md padding (default)</Text> <div className="p-2 bg-white/80 rounded">Item</div> </Stack> <Stack xl filled secondary flex1> <Text semibold>xl padding</Text> <div className="p-2 bg-white/80 rounded">Item</div> </Stack> <Stack noPadding filled secondary flex1> <Text semibold>noPadding</Text> <div className="p-2 bg-white/80 rounded">Item</div> </Stack></Row>Items (Cross Axis)
Stack has no items default, so children stretch to fill the width. Override with itemsStart, itemsCenter, itemsEnd, itemsBaseline, or itemsStretch.
default (stretch)
itemsStart
itemsCenter
itemsEnd
<Row itemsStart> <Stack flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>default (stretch)</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack itemsStart flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>itemsStart</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack itemsCenter flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>itemsCenter</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack itemsEnd flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>itemsEnd</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack></Row>Justify (Main Axis)
Control vertical distribution with justifyStart, justifyEnd, justifyCenter, justifyBetween, justifyAround, or justifyEvenly. The Stack needs a fixed height for these to have any effect.
justifyStart
justifyCenter
justifyEnd
justifyBetween
justifyAround
justifyEvenly
<Row itemsStart> <Stack justifyStart flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyStart</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack justifyCenter flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyCenter</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack justifyEnd flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyEnd</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack justifyBetween flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyBetween</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack justifyAround flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyAround</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack> <Stack justifyEvenly flex1 className="h-48 border-2 border-dashed border-gray-300"> <Text semibold>justifyEvenly</Text> <div className="p-2 bg-gray-100 rounded">A</div> <div className="p-2 bg-gray-100 rounded">B</div> </Stack></Row>Wrap Behavior
flexWrap is on by default. In a horizontal Stack, items wrap to the next line when they would overflow the container. Use flexNoWrap to force everything onto a single line.
flexWrap (default) — items wrap when they overflow
flexNoWrap — items shrink to fit
<Col> <Text semibold>flexWrap (default) — items wrap when they overflow</Text> <Stack row className="max-w-md border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> <div className="p-3 bg-gray-100 rounded">Item 3</div> <div className="p-3 bg-gray-100 rounded">Item 4</div> <div className="p-3 bg-gray-100 rounded">Item 5</div> </Stack> <Text semibold>flexNoWrap — items shrink to fit</Text> <Stack row flexNoWrap className="max-w-md border-2 border-dashed border-gray-300"> <div className="p-3 bg-gray-100 rounded">Item 1</div> <div className="p-3 bg-gray-100 rounded">Item 2</div> <div className="p-3 bg-gray-100 rounded">Item 3</div> <div className="p-3 bg-gray-100 rounded">Item 4</div> <div className="p-3 bg-gray-100 rounded">Item 5</div> </Stack></Col>Stack Variants
Use filled or outline with appearance props for styled containers. Stack defaults to sharp — pair with rounded or pill for curved corners.
<Row itemsStart> <Stack filled primary rounded flex1> <div className="p-4 bg-white/80 rounded">Filled Primary</div> <div className="p-4 bg-white/80 rounded">Item 2</div> </Stack> <Stack border success rounded flex1> <div className="p-4 rounded">Outline Success</div> <div className="p-4 rounded">Item 2</div> </Stack></Row>Text Alignment
Use textLeft, textCenter, textRight, or textJustify to control text alignment within the stack.
Left Aligned
Content aligned to the left.
Center Aligned
Content centered within the stack.
Right Aligned
Content aligned to the right.
<Row itemsStart> <Stack textLeft flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>Left Aligned</Text> <Text>Content aligned to the left.</Text> </Stack> <Stack textCenter flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>Center Aligned</Text> <Text>Content centered within the stack.</Text> </Stack> <Stack textRight flex1 className="border-2 border-dashed border-gray-300"> <Text semibold>Right Aligned</Text> <Text>Content aligned to the right.</Text> </Stack></Row>Responsive Layout
Use mobileCol or tabletCol on a horizontal Stack to switch back to a column on narrower viewports.
Column 1
Horizontal on desktop, stacked on tablet and below.
Column 2
Resize to see the responsive behavior.
<Stack row tabletCol> <Col flex1 className="p-4 bg-primary-100 rounded"> <Text semibold>Column 1</Text> <Text>Horizontal on desktop, stacked on tablet and below.</Text> </Col> <Col flex1 className="p-4 bg-primary-100 rounded"> <Text semibold>Column 2</Text> <Text>Resize to see the responsive behavior.</Text> </Col></Stack>As a Form Container
Stack's built-in padding makes it a natural container for a form — each Label becomes a row with its input, and the Stack provides the vertical rhythm and outer breathing room without any extra wrapper.
Sign in
Remember me
<Stack border rounded className="max-w-sm"> <Title>Sign in</Title> <Label> Email <Input type="email" placeholder="you@example.com" /> </Label> <Label> Password <Input type="password" placeholder="********" /> </Label> <Row> <Checkbox /> <Text sm>Remember me</Text> </Row> <Button filled>Sign in</Button></Stack>As Link
Add href to render the Stack as an <a> tag — useful for hero cards and large clickable surfaces. A keyboard focus-visible outline auto-renders so the link is reachable via Tab; opt out with noFocusVisible.
<Stack href="#get-started" border rounded itemsStart className="max-w-md"> <Zap size={28} /> <PageTitle>Get started in minutes</PageTitle> <Text>Install the package, drop in ThemeProvider, and start shipping.</Text> <Button filled>Read the guide</Button></Stack>Next.js Link Integration
Use the tag prop to render the Stack as a Next.js Link for client-side navigation.
import Link from 'next/link';import { Stack, PageTitle, Text, Button } from '@vaneui/ui';
<Stack href="/docs/getting-started" tag={Link} border rounded itemsStart> <PageTitle>Get started in minutes</PageTitle> <Text>Install the package, drop in ThemeProvider, and start shipping.</Text> <Button filled>Read the guide</Button></Stack>Stack Props
| Prop | Category | Default | Description |
|---|---|---|---|
accent | Appearance | Accent color appearance (rose) | |
brand | Appearance | Brand color appearance (blue) | |
danger | Appearance | Danger color appearance (red) | |
info | Appearance | Info color appearance (cyan) | |
inherit | Appearance | Inherit appearance from parent — suppresses own data-appearance/data-variant, uses parent's CSS variables | |
link | Appearance | Link color appearance (blue, for hyperlinks) | |
primary | Appearance | Primary color appearance (gray) | |
secondary | Appearance | Secondary color appearance (gray) | |
success | Appearance | Success color appearance (green) | |
tertiary | Appearance | Tertiary color appearance | |
warning | Appearance | Warning color appearance (amber) | |
desktopCol | Breakpoint | Switch to column layout on desktop and below (max-desktop: 80rem) | |
mobileCol | Breakpoint | Switch to column layout on mobile and below (max-mobile: 48rem) | |
tabletCol | Breakpoint | Switch to column layout on tablet and below (max-tablet: 64rem) | |
flex1 | Flex | Take up remaining space (= `flex-1`, i.e. `flex: 1 1 0%`) | |
flexAuto | Flex | Grow but respect intrinsic size (= `flex-auto`, i.e. `flex: 1 1 auto`) | |
flexNone | Flex | Don't grow and don't shrink (= `flex-none`, i.e. `flex: none`) | |
noPadding | Padding | Disable internal padding | |
padding | Padding | ✓ | Enable internal padding |
paddingX | Padding | Enable only horizontal padding | |
paddingY | Padding | Enable only vertical padding | |
pill | Shape | Fully rounded corners (circular) | |
rounded | Shape | Medium rounded corners (default) | |
sharp | Shape | ✓ | No rounded corners (square) |
noShrink | Shrink | Prevent the flex item from shrinking below its content size (= `shrink-0`) | |
lg | Size | Large size | |
md | Size | ✓ | Medium size (default) |
sm | Size | Small size | |
xl | Size | Extra large size | |
xs | Size | Extra small size | |
textCenter | Text Align | Align text to center | |
textJustify | Text Align | Justify text | |
textLeft | Text Align | Align text to left | |
textRight | Text Align | Align text to right | |
filled | Variant | Filled variant - solid background with contrasting text color | |
ghost | Variant | Ghost variant - transparent background, no border, appearance-colored text, tinted hover background | |
outline | Variant | ✓ | Outline variant - transparent background with border and colored text (default) |
Layout & utility props (gap, padding, hide, items, justify, ...) — documented on Common Props
| Prop | Category | Default | Description |
|---|---|---|---|
border | Border | Enable border on all sides | |
borderB | Border | Enable border on bottom | |
borderL | Border | Enable border on left | |
borderR | Border | Enable border on right | |
borderT | Border | Enable border on top | |
borderX | Border | Enable border on left and right | |
borderY | Border | Enable border on top and bottom | |
noBorder | Border | ✓ | Disable all borders |
block | Display | Block display - takes full width, new line | |
contents | Display | Contents display - element's box is removed, children display as if parent didn't exist | |
flex | Display | ✓ | Flex display - flexbox container |
grid | Display | Grid display - CSS grid container | |
hidden | Display | Hidden display - element is not visible | |
inline | Display | Inline display - flows with text | |
inlineBlock | Display | Inline-block display - inline but with block properties | |
inlineFlex | Display | Inline-flex display - inline flexbox container | |
inlineGrid | Display | Inline-grid display - inline grid container | |
table | Display | Table display - behaves like table element | |
tableCell | Display | Table-cell display - behaves like td element | |
column | Flex Direction | ✓ | Flex direction column (vertical) |
columnReverse | Flex Direction | Flex direction column-reverse | |
row | Flex Direction | Flex direction row (horizontal) | |
rowReverse | Flex Direction | Flex direction row-reverse | |
focusVisible | Focus Visible | Enable focus-visible outline | |
noFocusVisible | Focus Visible | Disable focus-visible outline | |
gap | Gap | ✓ | Enable gap spacing between children |
noGap | Gap | Disable gap spacing | |
hAuto | Height | Set height to auto | |
hFit | Height | Set height to fit-content | |
hFull | Height | Set height to 100% | |
hScreen | Height | Set height to 100vh (viewport height), removes max-height constraint | |
desktopHide | Hide | Hide element on desktop devices and below (max-desktop: 80rem) | |
mobileHide | Hide | Hide element on mobile devices and below (max-mobile: 48rem) | |
tabletHide | Hide | Hide element on tablet devices and below (max-tablet: 64rem) | |
itemsBaseline | Items | Align items to baseline | |
itemsCenter | Items | Align items to center | |
itemsEnd | Items | Align items to end (bottom/right) | |
itemsStart | Items | Align items to start (top/left) | |
itemsStretch | Items | Stretch items to fill container | |
justifyAround | Justify | Distribute items with space around them | |
justifyBaseline | Justify | Align items along their baseline on main axis | |
justifyBetween | Justify | Distribute items with space between them | |
justifyCenter | Justify | Center items along the main axis | |
justifyEnd | Justify | Pack items toward the end of the main axis | |
justifyEvenly | Justify | Distribute items with equal space around them | |
justifyStart | Justify | Pack items toward the start of the main axis | |
justifyStretch | Justify | Stretch items to fill the main axis | |
overflowAuto | Overflow | Auto overflow - show scrollbars if needed | |
overflowClip | Overflow | Clip overflow - hard clip without scrollbars | |
overflowHidden | Overflow | Hidden overflow - clip content without scrollbars | |
overflowScroll | Overflow | Scroll overflow - always show scrollbars | |
overflowVisible | Overflow | Visible overflow - content extends beyond bounds | |
overflowXAuto | Overflow | Auto overflow on X-axis only | |
overflowXClip | Overflow | Clip overflow on X-axis only | |
overflowXHidden | Overflow | Hidden overflow on X-axis only | |
overflowXScroll | Overflow | Scroll overflow on X-axis only | |
overflowXVisible | Overflow | Visible overflow on X-axis only | |
overflowYAuto | Overflow | Auto overflow on Y-axis only | |
overflowYClip | Overflow | Clip overflow on Y-axis only | |
overflowYHidden | Overflow | Hidden overflow on Y-axis only | |
overflowYScroll | Overflow | Scroll overflow on Y-axis only | |
overflowYVisible | Overflow | Visible overflow on Y-axis only | |
absolute | Position | Absolute positioning | |
fixed | Position | Fixed positioning | |
relative | Position | Relative positioning | |
static | Position | Static positioning | |
sticky | Position | Sticky positioning | |
responsive | Responsive | Enable responsive sizing - uses breakpoint-specific classes for font size, padding, and gap | |
reverse | Reverse | Reverse the order of children | |
noRing | Ring | ✓ | Disable focus ring |
ring | Ring | Enable focus ring | |
noShadow | Shadow | Disable drop shadow | |
shadow | Shadow | Enable drop shadow | |
transparent | Transparent | Disable background color - makes component background transparent | |
wAuto | Width | Set width to auto | |
wFit | Width | Set width to fit-content | |
wFull | Width | Set width to 100% | |
wScreen | Width | Set width to 100vw (viewport width), removes max-width constraint | |
flexNoWrap | Wrap | Force flex items to stay on single line (may overflow) | |
flexWrap | Wrap | ✓ | Allow flex items to wrap to new lines when container is too narrow |
flexWrapReverse | Wrap | Wrap flex items in reverse order (last items wrap first) |