Marble UI
← Components

Stack / Flex / Group

Preview: H / V stack

Flex stack with token gaps. HStack/VStack are presets; Center and Spacer cover the rest.

Import

import { Stack, HStack, VStack, Center, Spacer } from '@marbleui/ui'

Props

<Stack>

PropTypeDefaultDescription
align'center' | 'start' | 'end' | 'stretch' | 'baseline'—
asElementType'div'
direction'row' | 'column''column'
dividerboolean—Insert a divider line between children.
gapGap4
justify'center' | 'start' | 'end' | 'between'—
wrapboolean—

Also accepts HTML element props (278).

<HStack>

PropTypeDefaultDescription
align'center' | 'start' | 'end' | 'stretch' | 'baseline'—
asElementType—
dividerboolean—Insert a divider line between children.
gapGap—
justify'center' | 'start' | 'end' | 'between'—
wrapboolean—

Also accepts HTML element props (278).

<VStack>

PropTypeDefaultDescription
align'center' | 'start' | 'end' | 'stretch' | 'baseline'—
asElementType—
dividerboolean—Insert a divider line between children.
gapGap—
justify'center' | 'start' | 'end' | 'between'—
wrapboolean—

Also accepts HTML element props (278).

<Center>

No props of its own.

Also accepts HTML element props (278).

<Spacer>

No props of its own.

Usage notes

Flex layout with spacing from the token scale. HStack and VStack are row and column presets, Center centers its content, and Spacer pushes what follows to the far end. For two-dimensional layouts use Grid.

<HStack gap={3}>
  <Avatar size="sm" name="Maya Chen" />
  <VStack gap={0}><span>Maya Chen</span><span className="text-fg-muted">Owner</span></VStack>
  <Spacer />
  <Button size="sm" variant="ghost">Edit</Button>
</HStack>
  • gap is a spacing step: 0, 1, 2, 3, 4, 6, 8 or 12 (default 4, which is 1 rem). Other numbers aren’t accepted.
  • HStack vertically centers its children by default (align="center"); Stack and VStack are columns. Add wrap to let a row wrap, and as to render a ul, nav or other element.
  • divider draws lines between children and pads each child after a line by the gap, so the line sits midway. With gap={0} there’s no padding; give the children their own, as in a settings list.
  • Spacer is a flex-1 element, so it only works as a direct child of a stack.
Example source · show
import { Avatar } from '../avatar'
import { Badge } from '../badge'
import { Button } from '../button'
import { Center, HStack, Spacer, VStack } from './stack'

const Box = ({ t }: { t: string }) => <div className="rounded-md border border-dashed border-border-strong bg-surface-muted px-3 py-2 text-xs text-fg-muted">{t}</div>
export const styles = {
  'H / V stack': () => <VStack gap={3} className="w-80"><HStack gap={2}><Box t="A" /><Box t="B" /><Box t="C" /></HStack><VStack gap={1}><Box t="1" /><Box t="2" /></VStack></VStack>,
  'With spacer': () => <HStack gap={3} className="w-96 rounded-xl border border-border bg-surface p-3"><Avatar size="sm" name="Maya Chen" /><VStack gap={0}><span className="text-sm font-medium text-fg">Maya Chen</span><span className="text-xs text-fg-muted">Owner</span></VStack><Spacer /><Badge>Online</Badge><Button size="sm" variant="ghost">Edit</Button></HStack>,
  Dividers: () => <VStack gap={0} divider className="w-72 rounded-xl border border-border bg-surface [&>*]:px-4 [&>*]:py-2.5">{['Profile', 'Notifications', 'Billing'].map((t) => <span key={t} className="text-sm text-fg">{t}</span>)}</VStack>,
  Center: () => <Center className="h-40 w-72 rounded-xl border border-dashed border-border-strong"><Box t="Centered" /></Center>,
}

Source: packages/ui/src/stack/stack.tsx

Catalog

Category
layout
Priority
Extra
Primitive
custom