Стек

Стек расставляет пространство между вещами. Это flex-контейнер с единственной задачей и ответ почти на любой вопрос «как мне их раздвинуть»: по вертикали — по умолчанию, по горизонтали — через direction: 'row'.

Промежутки берутся из шкалы интервалов, поэтому ритм страницы остаётся ровным, и никому не приходится подбирать значения в пикселях.

Простой стек

Первая
Вторая
Третья
stack({ gap: 'md' },
  card(cardBody('Первая')),
  card(cardBody('Вторая')),
  card(cardBody('Третья')),
)

Направление

stack({ direction: 'row', gap: 'md' },
  button('Раз'),
  button({ variant: 'outline' }, 'Два'),
  button({ variant: 'outline' }, 'Три'),
)

Промежуток

Имя токена ('xs' … '3xl'), число единиц интервала или обычная CSS-длина.

xsxsxs
mdmdmd
6 единиц6 единиц
3rem3rem
stack({ gap: 'lg' },
  stack({ direction: 'row', gap: 'xs' }, chip('xs'), chip('xs'), chip('xs')),
  stack({ direction: 'row', gap: 'md' }, chip('md'), chip('md'), chip('md')),
  stack({ direction: 'row', gap: 6 }, chip('6 единиц'), chip('6 единиц')),
  stack({ direction: 'row', gap: '3rem' }, chip('3rem'), chip('3rem')),
)

Выравнивание

align и justify принимают обычные значения flexbox, так что работает всё, что понимает CSS.

началоконец
и выровнено
stack({ gap: 'md' },
  stack({ direction: 'row', gap: 'sm', justify: 'space-between', style: 'background: var(--su-surface-2); padding: 0.6rem; border-radius: 0.5rem' },
    chip('начало'),
    chip('конец'),
  ),
  stack({ direction: 'row', gap: 'sm', justify: 'center', align: 'center', style: 'background: var(--su-surface-2); padding: 0.6rem; border-radius: 0.5rem' },
    button({ size: 'sm' }, 'По центру'),
    chip('и выровнено'),
  ),
)

Перенос

Строке из чипов или кнопок, которая может не поместиться, нужен wrap: без него они сжимаются, вместо того чтобы уйти на следующую строку.

routingdataislandsimagespagefindlighthousesitemaprss
stack({ direction: 'row', gap: 'sm', wrap: true },
  ...['routing', 'data', 'islands', 'images', 'pagefind', 'lighthouse', 'sitemap', 'rss'].map(
    (name) => chip({ color: 'neutral' }, name),
  ),
)

Строчный вариант

inline делает стек inline-flex, и он встаёт в строку текста, а не занимает всю ширину.

Сделано на

sitelovite
и больше ни на чём.

text(
  'Сделано на ',
  stack({ direction: 'row', gap: 'xs', inline: true, align: 'center' },
    chip({ color: 'primary', size: 'sm' }, 'sitelo'),
    chip({ color: 'neutral', size: 'sm' }, 'vite'),
  ),
  ' и больше ни на чём.',
)

Как другой элемент

stack({ as: 'nav', direction: 'row', gap: 'sm' },
  navLink({ href: '/ru/docs' }, 'Документация'),
  navLink({ href: '/ru/ui', current: true }, 'UI'),
  navLink({ href: '/ru/examples' }, 'Примеры'),
)

Пропсы

ПропТипПо умолчаниюОписание
direction'row' | 'column''column'Главная ось.
gapSpace'md'Расстояние между потомками.
alignstring'stretch'Любое значение align-items.
justifystring'flex-start'Любое значение justify-content.
wrapboolean | stringfalsetrue — переносить; строка передаётся напрямую в flex-wrap.
inlinebooleanfalseРендерится как inline-flex.
asstring'div'Какой элемент рендерить, например nav или ul.