Direction-controlled flex stack — vertical by default, horizontal when
direction="row". Thin specialization of
<Flex> with locked nowrap and 4 ergonomic props
(direction, gap, align, justify). For
row-only clusters with edge-to-edge behaviour use
<Group>; for the full flex API (including
wrap and per-axis gaps) drop down to <Flex>.
Stack is eidos-native — no soma split. The
4 container props below pass through to the underlying <Flex>.
Stack also inherits every Box prop (padding,
margin, size, position) via Flex composition.
{eidosSnippet}
Stack is a thin, opinionated specialization of <Flex>: it locks wrap to nowrap, defaults direction to
column, and exposes only the four most-used container props. Drop down to
<Flex> when you need wrap, rowGap,
columnGap or inline.
| Prop | Type | Default | Notes |
|---|---|---|---|
| direction | row | row-reverse | column | column-reverse | 'column' | flex-direction. |
| gap | number | string | — | Number → var(--space-N). |
| align | stretch | start | center | end | baseline | flex-start | flex-end | — | align-items — cross-axis. |
| justify | start | center | end | space-between | space-around | space-evenly | stretch | flex-start | flex-end | — | justify-content — main-axis. |
Every BoxProps field is forwarded through Flex:
padding*, margin*, width, height,
position, top/right/bottom/left, overflow*, plus
item-side props (alignSelf, gridColumn, …).
wrap, inline, rowGap, columnGap —
Stack intentionally omits these. Use <Flex> when you need them.
| Library | Closest equivalent | Difference |
|---|---|---|
| radix-themes | <Flex direction="column"> | Radix doesn't ship a separate Stack — they use Flex with direction. UIX names the direction-locked variant for the most common case. |
| chakra-ui | <Stack> / <VStack> / <HStack> | Chakra exposes three components (Stack/VStack/HStack). UIX collapses to a single Stack with a direction prop — <Group> covers the row-cluster case. |
| mantine | <Stack> / <Group> | Mantine has the same split: vertical Stack + horizontal Group. UIX matches Mantine here. |
| Field | Value |
|---|---|
| name | {stackMorfo.name} |
| kebab | {stackMorfo.kebab} |
| scope | {stackMorfo.scope.join(', ')} |
| parts | {partsList.length} |
| events | 0 |
| kebab | marker | element | archetype | optional |
|---|---|---|---|---|
| {part.kebab} | [{part.marker}] |
<{part.defaultElement}> | {part.archetype} | {part.optional ? 'yes' : 'no'} |
Stack composes through <Flex> which composes through
<Box>, so the rendered DOM is a single
div[data-box][data-flex][data-stack] shell. Recipe lives at
src/uix/eidos/components/stack/stack.css — currently just the marker; all
behaviour comes from the Flex layer.
Stack declares no semantic events. As a passive layout primitive, it does not commit, emerge, or react to anything — it just arranges its children. Components that animate on appearance should compose Stack with an interactive primitive (popover, drawer, collapsible) that owns the relevant sema verbs.
Recipe lives in src/uix/eidos/components/stack/stack.css — currently
declaration-only (the [data-stack] marker exists so consumers can target
stacks specifically). All visual behaviour layers on top of the Flex recipe.
| Selector | Owner | Purpose |
|---|---|---|
[data-stack] |
morfo | Provider marker. Used by consumers for targeting; behaviour inherited from Flex. |
| Concern | Contract |
|---|---|
| Role | None implicit. Default element is <div> — semantically neutral. Wrap Stack in a landmark (<nav>, <section>, <ul role="list">) when content needs one. |
| Label | Not applicable — Stack has no content semantics. Labels belong to the interactive children. |
| Keyboard | Stack is not focusable. Tab order follows DOM order even when direction visually reverses (row-reverse / column-reverse). Verify visual order matches focus order for keyboard users. |
| Reduced motion | Stack does not animate. |