Словарь раскладки: нейтральный к платформе (references/layout-vocabulary.md)

Источник: ds-docs/component-contracts/skills/astra-component-contract/references/layout-vocabulary.md — справочник скилла astra-component-contract

Карточка описывает слои словами CSS — так их отдаёт Figma MCP, и так проза читается вебом. Контракт этот словарь не повторяет: CSS — язык одной платформы, а контракт читает генератор кода под React, Flutter и что угодно дальше. Поэтому имена здесь — от модели Figma, из которой выводятся обе платформы, но без жаргона инструмента.

Принцип: одно понятие — одно слово; слово называет намерение («заполнить родителя»), а не приём платформы («flex: 1 0 0»).

Таблица соответствий

layoutMode: HORIZONTAL / VERTICAL / NONElayout.direction: row / column / noneflex-direction: row / column; display: blockRow / Column / Stack
primaryAxisAlignItems: MIN / CENTER / MAX / SPACE_BETWEENlayout.mainAlign: start / center / end / spaceBetweenjustify-content: flex-start / center / flex-end / space-betweenmainAxisAlignment: start / center / end / spaceBetween
counterAxisAlignItems: MIN / CENTER / MAX / BASELINElayout.crossAlign: start / center / end / baseline / stretchalign-items: flex-start / center / flex-end / baseline / stretchcrossAxisAlignment: start / center / end / baseline / stretch
itemSpacinglayout.gapgapspacing / SizedBox между детьми
paddingTop/Right/Bottom/Leftlayout.padding — число, токен, {vertical, horizontal} или {top, right, bottom, left}paddingPadding(EdgeInsets…)
layoutWrap: WRAPlayout.wrap: trueflex-wrap: wrapWrap
layoutSizingHorizontal: HUG / FILL / FIXEDsize.width: hug / fill / число / токенwidth: auto / flex: 1 0 0 + align-self: stretch / width: Npxвнутренний размер / Expanded / SizedBox(width)
layoutSizingVerticalsize.height — те же словаheightте же
minWidth / maxWidth / minHeight / maxHeightsize.minWidth …min-width …ConstrainedBox(BoxConstraints…)
layoutPositioning: AUTO / ABSOLUTEposition: flow / absoluteposition: static / absoluteребёнок Row/Column / Positioned в Stack
x, y при ABSOLUTE + constraintsinset: {top, right, bottom, left}top / right / bottom / leftPositioned(top: …)
clipsContentclip: trueoverflow: hiddenclipBehavior / ClipRRect
fillsfill: токен; заливки нет — fill: nonebackgroundcolor / BoxDecoration.color
strokes, strokeWeight, стороныstroke: {color, weight, sides}borderBorder
topLeftRadius … bottomLeftRadiusradius: {topLeft, topRight, bottomRight, bottomLeft}border-radius четырьмя значениямиBorderRadius.only
cornerRadiusradius: токен / числоborder-radiusBorderRadius
opacityopacity: 0…1opacityOpacity
visible, привязан к булеву свойствуvisibleWhen: <свойство>условный рендерif / Visibility
characters, привязан к текстовому свойствуtextFrom: <свойство>проппараметр String
fontFamily, fontSize, lineHeight, fontWeight, letterSpacingне пишутся: их несёт стиль — text.stylefont-*, line-height, letter-spacing из класса стиляTextStyle из TextTheme
цвет текстаtext.color: токенcolorTextStyle.color
textAlignHorizontaltext.align: start / center / endtext-aligntextAlign
maxLinestext.lines: число / autowhite-space: nowrap (при 1)maxLines
textTruncation: ENDINGtext.truncate: ellipsis / nonetext-overflow: ellipsisoverflow: TextOverflow.ellipsis
componentProperties инстансаprops: {Имя: значение}пропсыаргументы конструктора
overrides инстансаoverrides: {…} в этом же словарестили поверх компонентаобёртка
textStyleIdtext.style: имя стиля; поверх инстанса — overrides.textStyleкласс типографикиTextTheme
explicitVariableModesmodes: {<коллекция>: <режим>}тема или брейкпоинт, закреплённые на узлеTheme.of(context) на поддереве
componentPropertyReferences.mainComponentswapFrom: <свойство подмены>проп-компонентпараметр Widget
isExposedInstanceexposed: true / falseпроп вложенного компонента в API родителяпараметр-объект вложенного виджета
слой состояния подкрашенfill: токен на слое состояния (hover-bg-dark, focus-bg, press-bg-dark)-hover / -pressed, см. foundations/state-layer.mdпо той же основе
порядок детейorder: [имя, имя] на родителепорядок в разметкепорядок в children

Всё, чего в таблице нет, в контракт не пишется — идёт в gaps с текстом «свойство X не переведено в словарь». Курсор-указатель и «интерактивность» — не свойства макета: Figma их не хранит, и контракт их не выдумывает.

Слова

Там, где ждётся слово, скрипт принимает только эти:

layout.directionrow, column, none
layout.mainAlignstart, center, end, spaceBetween
layout.crossAlignstart, center, end, baseline, stretch
size.*hug, fill, число, токен
positionflow, absolute
text.alignstart, center, end
text.truncateellipsis, none
text.linesчисло, auto
fill, stroke.colorтокен или none
kindframe, text, shape, instance, slot, group

Что скрипт считает CSS-словом

Если встретит у узла — ошибка с подсказкой:

flex-direction, displaylayout.direction
justify-contentlayout.mainAlign
align-items, align-selflayout.crossAlign (у родителя)
flex, flex-growsize.width: fill или size.height: fill
padding, padding-* на узлеlayout.padding
gap на узлеlayout.gap
width, height, min-*, max-* на узлеsize.width, size.minHeight …
top, right, bottom, left на узлеinset
background, background-colorfill
border, border-color, border-widthstroke
border-radiusradius
overflowclip
font-family, font-size, line-height, font-weight, letter-spacingtext.style — имя стиля файла; что внутри, знает фундамент типографики
color, text-align, text-overflow, white-spacetext.color, text.align, text.truncate, text.lines
cursorничего — курсор не свойство макета

Почему не CSS — и когда CSS всё-таки

За нейтральный словарь: генератор Flutter не переводит flex: 1 0 0 в Expanded по догадке, у каждого слова одно значение, и словарь совпадает с тем, что Figma и так хранит.

За CSS: его знают все разработчики; проза карточки уже на нём; для React перевод не нужен.

Второй вариант контракта — на CSS-именах — отличается только этим файлом и таблицей имён в скрипте. Всё остальное общее, так что сравнить можно на одном и том же компоненте.