Flex
Контейнер для flex-раскладки. Управляет направлением, выравниванием, переносом и отступами между детьми через пропсы — без ручных display: flex и gap в разметке потребителя.
Демо
aligndata-test-iddirectiongapjustifywrap<Flex direction="row" justify="space-between" align="center" gap="2m" wrap="nowrap" />Когда использовать
- Нужно расположить несколько элементов в ряд или столбец с предсказуемым отступом между ними.
- Требуется выравнивание группы по главной (
justify) или поперечной (align) оси. - Элементы должны переноситься на новую строку при нехватке места (
wrap).
Когда не нужен:
- Двумерная сетка с явными строками и колонками:
- используйте CSS Grid.
- Единичный элемент без соседей — обёртка-flex ничего не даёт.
Do / Don’t
- ✅ Задавайте отступы через
gap(токен модульной шкалы) — единый ритм с дизайн-системой. - ❌ Не вставляйте distance-обёртки или
marginмежду детьми вручную. - ✅ Для произвольной ширины/высоты используйте
width/height(число, keywordElementSizeили CSS-строка). - ❌ Не оборачивайте
Flexв дополнительныйdivсо своимdisplay: flexради выравнивания. - ✅ Берите
Flexдля одномерной раскладки (ряд или столбец). - ❌ Не стройте на
Flexдвумерные сетки — это задача CSS Grid. - ✅ Полиморфизм через
as(as='nav',as='ul') — семантический тег без потери раскладки. - ❌ Не дублируйте
Flexради смены тега — передайтеas.
Анатомия
Direction (default row)
Направление главной оси (проп direction). Тип — Extract валидных значений flex-direction:
row/row-reverse— строка (и в обратном порядке).column/column-reverse— столбец (и в обратном порядке).
Justify
Выравнивание по главной оси (justify-content). Тип — Extract из CSSProperties['justifyContent']:
flex-start/center/flex-end— к началу / центру / концу.space-between/space-around/space-evenly/stretch— распределение свободного пространства.
Align
Выравнивание по поперечной оси (align-items). Тип — Extract из CSSProperties['alignItems']:
flex-start/center/flex-end— к началу / центру / концу.self-start/self-end— по краю с учётомalign-self.baseline— по базовой линии текста.stretch— растянуть детей по поперечной оси.
Align content
Выравнивание строк многострочного flex (align-content, проп alignContent, работает при wrap).
Тип — Extract из CSSProperties['alignContent']: flex-start / center / flex-end /
space-between / space-around / space-evenly / stretch / baseline.
Wrap (default nowrap)
Перенос детей (flex-wrap). Принимает boolean (true → wrap) либо явное значение:
nowrap— без переноса.wrap— перенос на новую строку.wrap-reverse— перенос в обратном порядке.
Gap (default нет)
Отступ между детьми. Пропсы gap (CSS gap), columnGap (column-gap) и rowGap
(row-gap) принимают только токен модульной шкалы (m = модуль 8px, привязан к
dimension-токенам DS). Произвольные числа/строки не поддерживаются.
Модульная шкала:
025m— 2px050m— 4px1m— 8px2m— 16px3m— 24px4m— 32px5m— 40px6m— 48px7m— 56px8m— 64px9m— 72px10m— 80px
Токены резолвятся через data-* + SCSS в CSS-переменные --sn-primitive-dimension-* (тема, override через CSS), без инлайн-стилей.
Overflow
Поведение переполнения по осям (overflow / overflowX / overflowY). Тип — Extract из
CSSProperties['overflow']:
visible— контент выходит за границы (по умолчанию).hidden/clip— обрезается.scroll— всегда со скроллом.auto— скролл при переполнении.
Size (width / height / flex)
width, height и flex используют один тип Size:
- keyword
ElementSize—max-content/min-content/fit-content/auto/inherit/initial/unset. Резолвится черезdata-*+ SCSS. - число — интерпретируется как px для
width/height(width={200}), какflex-growдляflex(flex={1}). Инлайн-стилем. - CSS-строку —
'50%','12rem', дляflex— shorthand'1 1 auto'. Инлайн-стилем.
fullWidth — shorthand для width: 100%.
Установка
pnpm add @cloud-ru/ds-uikit-product-flex
import { Flex } from '@cloud-ru/ds-uikit-product-flex'
import '@cloud-ru/ds-uikit-product-flex/style.css'
Примеры использования
Тулбар
import { Button } from '@cloud-ru/ds-button';
import { Flex } from '@cloud-ru/ds-uikit-product-flex';
export function Toolbar() {
return (
<Flex justify='space-between' align='center' gap='2m' fullWidth>
<Button label='Назад' view='outline' appearance='neutral' />
<Flex gap='1m'>
<Button label='Отмена' view='outline' appearance='neutral' />
<Button label='Сохранить' />
</Flex>
</Flex>
);
}Вертикальный стек
import { Button } from '@cloud-ru/ds-button';
import { Flex } from '@cloud-ru/ds-uikit-product-flex';
export function Stack() {
return (
<Flex direction='column' gap='1m' width={220}>
<Button label='Первый' fullWidth />
<Button label='Второй' fullWidth view='outline' appearance='neutral' />
<Button label='Третий' fullWidth view='outline' appearance='neutral' />
</Flex>
);
}Перенос
import { Flex } from '@cloud-ru/ds-uikit-product-flex';
const items = ['React', 'TypeScript', 'SCSS', 'Vite', 'Storybook', 'Playwright'];
const chipStyle = {
display: 'inline-flex',
alignItems: 'center',
padding: '4px 12px',
borderRadius: 16,
background: 'var(--sn-theme-color-neutral-background1Level)',
boxShadow: 'inset 0 0 0 1px var(--sn-theme-color-available-borderColor)',
} as const;
export function WrapTags() {
return (
<Flex wrap gap='1m' width={240}>
{items.map(item => (
<span key={item} style={chipStyle}>
{item}
</span>
))}
</Flex>
);
}Props
Types
FlexProps| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
align | "baseline" | "center" | "flex-end" | "flex-start" | "self-end" | "self-start" | "stretch" | — | no | Выравнивание по поперечной оси (`align-items`). |
alignContent | "baseline" | "center" | "flex-end" | "flex-start" | "space-around" | "space-between" | "space-evenly" | "stretch" | — | no | Выравнивание строк многострочного flex (`align-content`, работает при `wrap`). |
as | ElementType | — | no | Элемент или компонент для рендера. По умолчанию `div`. |
children | ReactNode | — | no | Содержимое контейнера. |
className | string | — | no | Дополнительный класс. |
columnGap | "025m" | "050m" | "10m" | "1m" | "2m" | "3m" | "4m" | "5m" | "6m" | "7m" | "8m" | "9m" | — | no | Отступ между колонками (CSS `column-gap`). Только токен модульной шкалы (см. `gap`). |
data-test-id | string | — | no | Стабильный идентификатор для e2e/tests. |
direction | "column" | "column-reverse" | "row" | "row-reverse" | — | no | Направление главной оси (`flex-direction`). По умолчанию `row`. |
flex | Size | — | no | Значение CSS-свойства `flex`. Keyword (`ElementSize` — `auto` / `max-content` / … → через `data-*`), число (`flex-grow`) или shorthand-строка (`'1 1 auto'`). |
fullWidth | boolean | false | no | Растянуть контейнер на всю ширину родителя (`width: 100%`). |
gap | "025m" | "050m" | "10m" | "1m" | "2m" | "3m" | "4m" | "5m" | "6m" | "7m" | "8m" | "9m" | — | no | Отступ между детьми (CSS `gap`). Только токен модульной шкалы (привязан к dimension-токенам DS). <pre> 025m - 2px 050m - 4px 1m - 8px 2m - 16px 3m - 24px 4m - 32px 5m - 40px 6m - 48px 7m - 56px 8m - 64px 9m - 72px 10m - 80px </pre> |
height | Size | — | no | Высота контейнера. Keyword (`ElementSize`), число (px) или CSS-строка (`'50%'`). |
innerRef | any | — | no | Ref на реальный DOM-элемент/инстанс, который рендерится через `as`. |
justify | "center" | "flex-end" | "flex-start" | "space-around" | "space-between" | "space-evenly" | "stretch" | — | no | Выравнивание по главной оси (`justify-content`). |
overflow | "auto" | "clip" | "hidden" | "scroll" | "visible" | — | no | Переполнение по обеим осям (`overflow`). |
overflowX | "auto" | "clip" | "hidden" | "scroll" | "visible" | — | no | Переполнение по горизонтали (`overflow-x`). |
overflowY | "auto" | "clip" | "hidden" | "scroll" | "visible" | — | no | Переполнение по вертикали (`overflow-y`). |
rowGap | "025m" | "050m" | "10m" | "1m" | "2m" | "3m" | "4m" | "5m" | "6m" | "7m" | "8m" | "9m" | — | no | Отступ между строками (CSS `row-gap`). Только токен модульной шкалы (см. `gap`). |
style | CSSProperties | — | no | Инлайн-стили, домешиваются последними и перекрывают `width`/`height`/`flex`. |
width | Size | — | no | Ширина контейнера. Keyword (`ElementSize`), число (px) или CSS-строка (`'50%'`). |
wrap | boolean | Wrap | — | no | Перенос детей (`flex-wrap`). `true` → `wrap`, `false` → `nowrap`, либо явное значение `nowrap` | `wrap` | `wrap-reverse`. |