Tokens

Composition

Полный справочник по типу Composition в SXL Studio: корневые поля, структура, теги, props, component properties, styles, transitions и theme binding — каждая секция начинается с таблицы полей.

Overview

$type: "composition" — это контракт SXL Studio, который описывает Figma-компонент в виде JSON. Это единый источник правды, превращающий замысел дизайна в повторяемые запуски Generate и Apply в Figma.

Вкратце, composition собирается из этих блоков:

БлокКлюч(и)Назначение
СтруктураstructureДерево слоёв
Вариантыprops / statesОси вариантов и взаимоисключающие состояния
СтилизацияstylesLayout, оформление и переопределения по вариантам
СвойстваcomponentPropertiesНативные свойства Figma на инстансах
Поведениеtransitions / themeBindingПрототипирование и светлая/тёмная тема

Ключевая идея Один JSON-файл описывает весь набор компонентов — его форму, варианты и стилизацию — поэтому один и тот же результат можно сгенерировать, обновить и передать инженерам или агентам без ручной пересборки.


Updates

История релизов типа Composition. Новый релиз — сверху; раскройте запись, чтобы увидеть изменения.

2.7.7Актуальный
  • ref.styles применяет нормализованные стили к корневому referenced-инстансу в INSTANCE refs и default-инстансах SLOT в reference mode.
  • refStyles в style-блоке задаёт вариантные переопределения для этого referenced root, не стилизуя абстрактный host слота и preferred swaps.
2.7.1Предыдущий
  • Компактные оси states для взаимоисключающих состояний вроде loading и disabled — без раздувания декартова произведения.
  • Единая модель раскладки Composition Grid — общая для превью и сгенерированных наборов.
  • Фигуры VECTOR для кастомных силуэтов, включая vectorCornerRadii на токенах.
  • Вариантные переопределения ref для wrapper-наборов с одним вложенным INSTANCE.
  • Более понятное поведение display и visible для условных веток.
  • Быстрее Generate / Apply в больших файлах, особенно для наборов с множеством слотов и инстансов.

Где используется

Используйте Composition, когда нужна предсказуемая и повторяемая сборка компонентов в дизайн-системе.

Частые сценарии:

  • генерация новых компонентов / наборов из token-файла;
  • обновление существующих компонентов без пересборки (Apply);
  • хранение структуры вариантов, содержимого слотов и правил стилизации в одном источнике;
  • передача детерминированной модели компонента инженерам и агентам.

Как это работает в SXL Studio

  1. Вы пишете JSON вручную или бутстрапите его через Get Code.
  2. SXL Studio парсит и валидирует файл.
  3. Generate создаёт новый компонент/набор, Apply обновляет отслеживаемые ноды.
  4. Трекинг хранится в diff-id.json, чтобы обновления были стабильны между запусками.

Трансформация в React / Vue 3

Composition JSON машиночитаем и достаточно стабилен для собственных скриптов-трансформеров. Плагин использует его для генерации в Figma, а вы можете читать structure + styles и мапить компонент в свой фреймворк. В Dev Mode SXL Studio также выдаёт готовый codegen (в том числе Vue 3), который можно взять за эталон.


Generate

Generate собирает новый компонент или набор из JSON: читает structure, разворачивает props в варианты, применяет styles и резолвит ссылки на токены ({path.to.token}) на этапе сборки. Используйте для компонента, которого ещё нет в Figma.

Предпроверка перед Generate / Apply

Сначала исправьте ошибки в JSON-редакторе. Типичные причины:

  • нерезолвнутые ссылки на токены ({path.to.token});
  • невалидный синтаксис алиасов;
  • нарушения схемы (например, некорректная форма SLOT).

Рекомендуемый порядок: открыть JSON → устранить все ошибки валидации → сохранить → запустить Generate или Apply.

Get Code

Get Code читает выбранную ноду(ы) в Figma и генерирует черновик Composition JSON — быстрая стартовая точка, которую вы затем дорабатываете вручную. При множественном выборе в выводе может появиться $synthetic: true — признак синтетической сборки набора (только информационно).

Grid settings

Grid управляет тем, как варианты раскладываются на канвасе в сгенерированном наборе. Меняется только размещение — не семантика токенов и не контракт JSON.

  • Columns / Rows явно назначают оси вариантов; несколько осей в одной зоне вкладываются снаружи внутрь.
  • оси states не размещаются в Columns / Rows — они выводятся отдельной state-полосой снизу или справа.
  • отступы разделены по смыслу: variant gap, prop/group gap, padding набора, label gap и state-band gap.
  • аннотации сетки рендерятся вне набора на тех же дорожках размещения, поэтому подписи совпадают с превью и выводом.

Рекомендация В больших файлах Figma тот же JSON остаётся стабильным, а SXL Studio уменьшает лишнюю перестилизацию для слот-тяжёлых компонентов. Держите значения class / name стабильными на слоях, которые адресуются из styles, и используйте states для взаимоисключающих состояний вместо разворачивания всех булевых комбинаций.


Apply

Apply обновляет существующий отслеживаемый компонент на месте, используя трекинг из diff-id.json, поэтому идентичность и инстансы сохраняются.

РежимДля чегоРезультат
GenerateНовый компонент / наборСоздаёт новый вывод
ApplyОбновление отслеживаемого компонентаОбновляет существующие ноды с трекингом

Автоматический режим выбирает операцию по контексту (выбранный якорь, трекинг, наличие локального компонента).

Разрешение цели и сохранение идентичности

Каждый выбранный корень composition обрабатывается со своим явным anchor. SXL Studio разрешает всё выделение до первой мутации canvas, поэтому цепочка sm → md и md → lg не позволяет первому переименованию забрать цель второго JSON-файла.

  • Уникальная живая identity обновляет этот Component или ComponentSet на месте. ID ноды Figma остаётся стабильным, поэтому существующие инстансы сохраняют связь с компонентом.
  • В режиме Automatic stale или cross-file identity без живого кандидата в текущем документе Figma создаёт новый результат.
  • Явный Apply без подходящей цели просит выбрать нужный корень или использовать Generate. Неоднозначные, конфликтующие или не полностью просканированные кандидаты останавливаются до мутации.
  • Apply сохраняет overrides пользовательских инстансов. Он не выполняет blanket reset текста, component properties, instance swaps и свойств, которых нет в composition.
  • Generate и Apply из UI плагина не требуют Bridge. Remote Connect и Git Sync Local Storage по-прежнему используют Bridge для собственных transport/storage-контрактов.

SXL Studio управляет переносимой source identity в $extensions["sxl.studio"].composition. Старые JSON без этого блока остаются поддержанными; успешный Generate или anchored Apply пытается добавить его, не переписывая посторонние $extensions:

JSON
{
  "$extensions": {
    "sxl.studio": {
      "composition": {
        "id": "11111111-1111-4111-8111-111111111111",
        "roots": [
          {
            "nodeId": "21649:1480",
            "key": "figma-component-key",
            "type": "COMPONENT_SET"
          }
        ]
      }
    }
  }
}

Это управляемые метаданные, а не авторский input. Если storage временно недоступен, canvas-операция остаётся успешной и сообщает warning; persistence identity повторяется в одном из следующих запусков.

Adopt и Audit для существующих компонентов

Компонент, созданный вручную до появления Composition JSON, удалять не нужно. Используйте контекстное меню бейджа composition:

ДействиеЧто делаетКогда использовать
Adopt compositionСвязывает выбранный компонент/набор с JSON без пересборки слоёв.Когда компонент в Figma уже есть и будущий Apply должен обновлять его.
Audit compositionСравнивает выбранный/связанный компонент с JSON и сообщает статус синхронизации.Перед adopt для легаси-компонента, после ручных правок или перед repair.

Adopt консервативен: сохраняет идентичность компонента (инстансы в других файлах не теряют связь), проверяет соответствие имён вариантов матрице из JSON и не переписывает слои, стили и свойства, пока audit/apply не подтвердит реальную структуру.


Root fields

Корневые ключи файла composition.

ПолеТипОбязательноПримечания
$type"composition"Маркер типа файла
namestringИмя компонента / набора
structureнодаДерево слоёв
stylesобъектБазовые стили + правила селекторов
propsобъектОси вариантов
statesstring[]Взаимоисключающие оси, взятые из props
componentPropertiesобъектНативные свойства Figma
transitionsобъектПрототип-переходы (transition в ед. ч. принимается как легаси-алиас)
themeBindingобъектОсь варианта → режимы коллекции переменных
componentbooleanПо умолчанию true; false строит plain-ноды и запрещает непустые props
$descriptionstringОписание Figma на корневом компоненте/наборе
$metadataanyНепрозрачные метаданные для тулинга; на генерацию не влияют
size / styleобъектОпциональные встроенные token-блоки (см. Advanced-поля)
slotHostPipelineобъектПродвинутые host/slot-системы (см. Advanced-поля)
segmentIconPostPassRefMarkersstring[]Продвинутые маркеры синхронизации иконок
selectorsautoautoГенерируется парсером из ключей styles — вручную не писать

Внимание Удалённые легаси-ключи дают ошибку парсинга: adapters, sizeStyles, colorStyles. А component: false несовместим с непустыми props.


Structure

structure — это дерево слоёв, которое строит генератор. У каждой ноды обязательны tag и class; всё остальное опционально.

Поля ноды

ПолеОбязательноЧто делаетАналог в FigmaАналог во Frontend
tagТип создаваемой нодыТип слояТип элемента
classКлюч привязки стилей/целиСелектор слояclassName
nameЯвное имя слоя в FigmaИмя слояdata-name / подпись
layerАлиас name, если name не заданИмя слояdata-name
contentТекстовое содержимое (в основном TEXT)Значение текстатекст-нода / children
descriptionЗаметка для человека, без визуалаОписание слоякомментарий в коде
refКакой компонент инстанцировать + конфигInstance → main comp.импортированный компонент
slotКонфиг нативного слота (reference mode)Свойство Slot<slot> / children
childrenВложенные дочерние нодыВложенные слоидочерние элементы
vectorPathsSVG-подобные path-данные (только VECTOR)Vector paths<path d="…">
vectorNetworkРедактируемая геометрия вершин (VECTOR)Vector network
viewBoxКоординатный бокс [x, y, w, h] (VECTOR)SVG viewBox
JSON
"structure": {
  "tag": "FRAME",
  "class": "root",
  "name": "Root",
  "children": []
}

JSON-пример на каждое поле:

JSON
{ "tag": "FRAME", "class": "card" }
JSON
{ "tag": "TEXT", "class": "label", "name": "Label", "content": "Continue" }
JSON
{ "tag": "INSTANCE", "class": "icon", "ref": { "component": "circle-info", "properties": { "size": "md" } } }
JSON
{ "tag": "SLOT", "class": "content-slot", "slot": { "default": "WButton", "preferred": ["WButton", "WChip"] } }
JSON
{ "tag": "FRAME", "class": "row", "description": "Строка шапки", "children": [{ "tag": "TEXT", "class": "title", "content": "Title" }] }

Примечание class — ключ стилей, name — имя слоя в Figma. Для вложенной адресации (ref.nested, NESTED_INSTANCE) всегда задавайте явный стабильный name.

Поддерживаемые значения tag

TagЧто создаётАналог в FigmaАналог во FrontendОграничения
FRAMEКонтейнер / auto-layout фреймFrame / Auto Layout<div> (flex-контейнер)
TEXTТекстовый слойText<span> / <p>значение из content
COMPONENTВложенная нода main-компонентаComponentопределение компонента
INSTANCEИнстанс из refInstanceиспользование <Component />нужен ref; плейсхолдер, если не резолвится
ICONИконка-инстанс, резолвится из refIcon instance<Icon />как INSTANCE; color перекрашивает глиф
SLOTНативный слот (или fallback)Slot<slot> / {children}reference или children mode, не оба
RECTANGLEПрямоугольникRectangleблочный <div>заливка через fill
ELLIPSEЭллипсEllipseborder-radius: 50% div
LINEЛинияLine<hr> / разделитель
VECTORКастомный вектор из path / vector networkVector (Pen)инлайновый <svg><path>не импорт «сырого» SVG

JSON-пример на каждый тег:

JSON
{ "tag": "FRAME", "class": "card", "children": [] }
JSON
{ "tag": "TEXT", "class": "label", "content": "Continue" }
JSON
{ "tag": "COMPONENT", "class": "chip" }
JSON
{ "tag": "INSTANCE", "class": "cta", "ref": { "component": "WButton", "properties": { "variant": "primary" } } }
JSON
{ "tag": "ICON", "class": "leading-icon", "ref": { "component": "circle-info" } }
JSON
{ "tag": "SLOT", "class": "content-slot", "slot": { "default": "WButton" } }
JSON
{ "tag": "RECTANGLE", "class": "bg" }
JSON
{ "tag": "ELLIPSE", "class": "avatar-mask" }
JSON
{ "tag": "LINE", "class": "divider" }
JSON
{
  "tag": "VECTOR",
  "class": "body-shape",
  "vectorPaths": [{ "data": "M 0 140 L 564 140 L 540 0 L 24 0 Z", "windingRule": "NONZERO" }],
  "viewBox": [0, 0, 564, 140]
}

Используйте VECTOR, когда фигура не является прямоугольником, эллипсом или линией — скошенное тело кнопки, волна, вырез вкладки, кастомный бейдж. Он принимает SVG-подобные vectorPaths или Figma-подобный vectorNetwork для редактируемых вершин и получает те же визуальные стили, что и другие фигуры. Скругление вершин можно токенизировать из styles через vectorCornerRadii.

Паттерн скошенной кнопки

Держите редактируемую геометрию фигуры в structure, а цвет/размер/скругление управляйте из styles. Середина остаётся обычным auto-layout FRAME, поэтому текст и иконки ведут себя как обычно.

JSON
{
  "tag": "FRAME",
  "class": "wrap",
  "children": [
    { "tag": "VECTOR", "class": "left-shape", "vectorNetwork": { "vertices": [{ "x": 18, "y": 56 }, { "x": 0, "y": 56 }, { "x": 10, "y": 0 }, { "x": 18, "y": 0 }], "segments": [{ "start": 0, "end": 1 }, { "start": 1, "end": 2 }, { "start": 2, "end": 3 }, { "start": 3, "end": 0 }], "regions": [{ "windingRule": "NONZERO", "loops": [[0, 1, 2, 3]] }] } },
    { "tag": "FRAME", "class": "content", "children": [{ "tag": "TEXT", "class": "label", "content": "PRIMARY" }] }
  ]
}
JSON
".left-shape": { "widthType": "fixed", "heightType": "fixed", "width": 18, "height": 56, "fill": "{button.bg.accent}", "vectorCornerRadii": [0, "{radius.md}", "{radius.md}", 0] }

vectorCornerRadii принимает массив (в порядке вершин) или объект ({ "1": "{radius.md}" }). Индексы вершин с нуля. VECTOR — не импорт «сырого» SVG: кривые, скос и вырезы кладите в vectorPaths / vectorNetwork.

Режимы и правила SLOT

У SLOT строгие режимы: reference mode (конфиг slot с опциональным шаблоном ref) или children mode (инлайновые children). Никогда оба сразу.

JSON
{
  "tag": "SLOT",
  "class": "content-slot",
  "slot": { "default": "WButton", "preferred": ["WButton", "WChip"] },
  "ref": { "component": "WButton", "properties": { "size": "md" } }
}
JSON
{
  "tag": "SLOT",
  "class": "rows",
  "children": [{ "tag": "FRAME", "class": "row", "children": [] }]
}

Ограничения: у SLOT не может быть одновременно slot и непустых children; SLOT.ref валиден только в reference mode. SLOT ровно с одним дочерним INSTANCEref, без slot) трактуется как сокращение reference mode.

Примечание Канонический и переносимый между схемами формат для slot.preferred и componentProperties.*.preferred — массив имён компонентов. Apply также принимает записи из Figma API, например { "type": "COMPONENT_SET", "key": "..." }; дополнительная отображаемая метка вроде component игнорируется. Используйте имена компонентов, если файл должен проходить внешнюю схему, разрешающую только строки.

ref для INSTANCE / SLOT

ПолеЧто делаетПример
componentИмя целевого компонента (обязательно при наличии ref)"component": "WButton"
libraryПодсказка библиотеки"library": "SXL DS"
keyПодсказка publish-key"key": "abc123"
propertiesПримитивные значения свойств инстанса"properties": { "state": "active" }
stylesСтили корня referenced-инстанса"styles": { "width": "{size.icon}" }
iconBindPropertyЯвное имя свойства для icon swap"iconBindProperty": "icon"
iconДескриптор вложенного icon swap"icon": { "component": "fire-3" }
overridesПереопределения содержимого детей"overrides": { "label": "Apply" }
slotsПереопределения слотов у referenced-инстансасм. ниже
nestedОбновления вложенных инстансов по имени слоясм. ниже
descriptionОпциональная заметка"description": "Primary CTA"

ref.styles относится к материализованному корню referenced INSTANCE. Используйте его, когда самому default-инстансу нужны layout- или paint-bindings, например binding размера иконки внутри SLOT. Поддерживаются те же aliases и token refs, что и в обычных styles: widthType, heightType, width, height, fill, color.

Style-блок host по-прежнему стилизует сам composition node. В reference-mode слотах используйте refStyles внутри обычного style-блока, если варианты должны переопределять referenced root. refStyles мержится поверх ref.styles и применяется только пока текущий slot child совпадает с ref.component; он не каскадится на preferred/user swap вроде WBadge.

JSON
{
  "tag": "SLOT",
  "class": "leading-slot",
  "slot": { "default": "circle-info", "preferred": ["circle-info", "WBadge"] },
  "ref": {
    "component": "circle-info",
    "properties": { "style": "filled" },
    "styles": {
      "widthType": "fixed",
      "heightType": "fixed",
      "width": "{sz.fixed.reg.xs}",
      "height": "{sz.fixed.reg.xs}"
    }
  }
}
JSON
"styles": {
  "$placement=inner .leading-slot": {
    "refStyles": {
      "width": "{sz.fixed.reg.3xs}",
      "height": "{sz.fixed.reg.3xs}"
    }
  }
}

ref.nested — адресует вложенные инстансы по имени слоя:

JSON
"nested": {
  "Badge": {
    "properties": { "label": "3" },
    "icon": { "component": "fire-3", "properties": { "style": "filled" } }
  }
}

ref.slots — переопределяет слоты внутри referenced-инстанса (op: replace, append, patch):

JSON
"slots": {
  "footer": {
    "op": "replace",
    "nodes": [{ "component": "WButton", "name": "apply", "properties": { "variant": "primary" } }]
  }
}

Вариант набора может оборачивать другой существующий компонент, переопределяя ref из вариантного селектора, — тогда одна нода INSTANCE обслуживает весь wrapper-набор:

JSON
"styles": {
  "$item=neutral-secondary-sm .item": {
    "ref": { "component": "WButton", "properties": { "style": "neutral", "variant": "secondary", "size": "sm" } }
  }
}

Props

КлючТипЧто делает
propsRecord<string, (string | boolean | number)[]>Объявляет каждую ось вариантов и её допустимые значения
statesstring[]Имена осей из props, которые являются взаимоисключающими состояниями

props объявляет все допустимые значения для каждой оси; каждая комбинация становится одним сгенерированным вариантом.

JSON
"props": {
  "size": ["sm", "md", "lg"],
  "state": ["default", "hover", "active"],
  "compact": [true, false]
}

Поведение: при сопоставлении селекторов значения сравниваются как строки; ось с default использует его как fallback для отсутствующих правил, иначе fallback — первое значение. Держите число осей осознанным — комбинации растут мультипликативно.

states (взаимоисключающие оси)

states перечисляет оси из props, которые ведут себя как взаимоисключающие UI-состояния (:disabled, :loading), а не как комбинируемые варианты. Они исключаются из декартова произведения — каждое не-дефолтное значение добавляет один вариант поверх дефолтов.

JSON
"props": {
  "_state": ["default", "hover", "focus", "select"],
  "loading": ["false", "true"],
  "disabled": ["false", "true"]
},
"states": ["loading", "disabled"]

Без states это матрица 4 × 2 × 2 = 16 вариантов; со states она схлопывается до 6 (4 интерактивных + loading=true + disabled=true). Правила: off-значение — первое значение оси; каждое имя в states должно быть в props; Apply декларативно пере-схлопывает существующий набор. Обычные визуальные выборы (size, variant, tone, theme) держите только в props.

Маппинг в codegen:

  • React / Vue: ось, значения которой ровно false / true, становится boolean-пропом (напр. loading?: boolean);
  • DivKit: наборы эмитятся через card.states / state_id; states лишь управляет тем, какие варианты материализуются, и не создаёт фиктивный custom_type;
  • ось с префиксом _ (напр. _state) — внутренняя ось interaction-состояния, исключена из публичного codegen-API (её ведёт собственный :hover / :focus CSS потребителя); не-_ оси вроде loading / disabled эмитятся как реальные пропсы.

Расширенная объектная форма с combineWith (скрещивание состояния со структурными осями) зарезервирована, но пока не реализована — её использование вызывает ошибку валидации.


Component Properties

componentProperties задаёт нативные свойства Figma, доступные на инстансах.

ТипНа что указывает layerdefaultValue
TEXTclass в structureОбязателен; авто-выводится из content, если опущен
BOOLEANclass в structureОбязателен; по умолчанию true, если опущен
INSTANCE_SWAPclass в structureОбязателен
SLOTclass в structureОбязателен
NESTED_INSTANCEИмя слоя вложенного инстанса (не class)Не обязателен

Пример на каждый тип:

JSON
"title": { "type": "TEXT", "layer": "title", "defaultValue": "Promo title" }
JSON
"showMeta": { "type": "BOOLEAN", "layer": "meta", "defaultValue": true }
JSON
"icon": { "type": "INSTANCE_SWAP", "layer": "icon", "defaultValue": "circle-info", "preferred": ["circle-info", "star"] }
JSON
"media": { "type": "SLOT", "layer": "media-slot", "defaultValue": "WImageTile" }
JSON
"badge": { "type": "NESTED_INSTANCE", "layer": "Badge" }

Правило layer: для TEXT, BOOLEAN, INSTANCE_SWAP, SLOT используйте class из structure; для NESTED_INSTANCE — реальное имя вложенного слоя в Figma.


Styles

styles управляет оформлением слоя, layout и переопределениями по вариантам. Ключ — это CSS-подобный класс (.card), легаси-класс (card) или вариантный селектор ($state=hover .card); блоки можно вкладывать. Каждое свойство ниже показано с точным написанием в JSON, сгруппировано по назначению:

ГруппаЧто покрывает
Контейнер & auto-layoutdirection, justifyContent, alignItems, gap, padding, …
Размер слояwidthType, width, min/maxWidth, aspectRatio, …
Позиционированиеposition, top/right/bottom/left, x/y, alignSelf, …
Gridrows/columns, rowGap/columnGap, выравнивание/спан grid-ребёнка
Фон/заливка/цветbackground, fill, color
Границы & углыborder, borderRadius, strokeAlign, cornerSmooth, …
Тени & эффектыboxShadow, backgroundBlur, layerBlur, opacity, glass
ТипографикаfontFamily, fontSize, lineHeight, textCase, …
Видимость & сбросvisible, display, очистка через none
Управление инстансомcomponent, instanceProperties, nestedInstanceProperties, ref
Переменные & метаданныеexplicitVariableModes, layoutGrids, exportSettings, mask
JSON
"styles": {
  ".root": { "direction": "row", "gap": 8, "padding": "12 16" },
  "$state=hover .root": { "background": "{color.brand.hover}" }
}

Селекторы и каскад

  • сначала применяются базовые стили; затем совпавшие селекторы по специфичности (больше условий — выше приоритет);
  • одинаковая специфичность → побеждает более позднее объявление в JSON;
  • descendant-селекторы резолвятся через dot-пути (.footer .itemfooter.item);
  • когда класс повторяется в разных ветках, предпочитайте полный путь (.header .item) вместо голого .item.
JSON
"styles": {
  ".wrap": {
    "padding": 8,
    ".item": { "widthType": "fill" },
    "$state=active": { ".item": { "opacity": 1 } }
  }
}

Контейнер и auto-layout

СвойствоЧто делает — значенияПример
directionОсь раскладки — row, column, grid, none"direction": "row"
justifyContentРаспределение по главной оси — start, center, end, space-between"justifyContent": "space-between"
alignItemsВыравнивание по поперечной оси — start, center, end, baseline"alignItems": "center"
alignContentРаспределение перенесённых рядов — auto, space-between"alignContent": "space-between"
flexWrapПеренос — nowrap, wrap"flexWrap": "wrap"
gapОтступ между детьми (px)"gap": 12
wrapGapПоперечный отступ между перенесёнными рядами (px)"wrapGap": 8
paddingВнутренние отступы — число, "T R B L" или "none""padding": "16 16 20 16"
overflowОбрезка — hidden, clip, visible, auto, scroll"overflow": "hidden"
primaryAxisSizingModeРазмер контейнера по главной оси — auto, fixed"primaryAxisSizingMode": "auto"
counterAxisSizingModeРазмер контейнера по поперечной оси — auto, fixed"counterAxisSizingMode": "fixed"
boxSizingОбводка учитывается в layout — border-box, content-box"boxSizing": "border-box"
canvasStackingZ-порядок сиблингов — first-on-top, last-on-top"canvasStacking": "first-on-top"
JSON
".header": { "direction": "row", "justifyContent": "space-between", "alignItems": "center", "gap": 8, "padding": "12 16" }

Размер слоя

СвойствоЧто делает — значенияПример
widthType / heightTypeРежим размера — fixed, hug, fill"widthType": "fill"
width / heightФиксированный размер (px)"width": 360
minWidth / maxWidthГраницы ширины (px)"maxWidth": 480
minHeight / maxHeightГраницы высоты (px)"minHeight": 40
aspectRatioФиксация пропорции — "1/1", или "none" / false для сброса"aspectRatio": "1/1"
constrainProportionsБлокировка пропорций ширина/высота — true, false"constrainProportions": true

targetAspectRatio — принимаемый алиас aspectRatio.

Позиционирование

СвойствоЧто делает — значенияПример
positionПоток — relative, absolute, none"position": "absolute"
top / right / bottom / leftAbsolute-инсеты (px)"top": 8
x / yАбсолютные координаты на канвасе (px)"x": 24
alignSelfПереопределение поперечного выравнивания — inherit, stretch, start, center, end"alignSelf": "stretch"
flexGrowКоэффициент роста"flexGrow": 1
rotateПоворот (град)"rotate": 45
constraintH / constraintVКонстрейнты Figma — left, center, right, scale, stretch"constraintH": "center"
JSON
".badge": { "position": "absolute", "top": 8, "right": 8 }

Grid-раскладка

Задаётся, когда direction равен grid.

СвойствоЧто делаетПример
rows / columnsЧисло дорожек"columns": 3
rowGap / columnGapОтступы дорожек (px)"columnGap": 8
gridTemplateRows / gridTemplateColumnsРазмеры дорожек"gridTemplateColumns": "1fr 1fr"
justifySelf / gridAlignSelfВыравнивание grid-ребёнка (H / V) — start, center, end, auto"justifySelf": "center"
gridRowSpan / gridColumnSpanРастяжение grid-ребёнка (дорожки)"gridColumnSpan": 2

Фон, заливка, цвет

СвойствоЧто делает — значенияПример
backgroundЗаливка контейнера — hex, градиент, массив слоёв или "none" / "transparent""background": "#FFFFFF"
fillЗаливка фигуры / вектора / иконки — hex или токен, "none" очищает"fill": "{button.primary}"
colorCSS-подобный currentColor (текст + краска иконки) — hex или токен, "none""color": "{text.primary}"

color — это CSS-подобный currentColor: на TEXT задаёт заливку текста; на ICON / иконках-инстансах перекрашивает глиф (fill-иконки получают заливку, stroke-иконки — обводку). Ссылки на токены сохраняют привязку к переменной; литеральные цвета её заменяют. fill и strokes — низкоуровневые: используйте их для заливок фигур или прямой обводки. Для stroke-only иконки "fill": "none" оставляет только краску обводки.

Градиентный фон:

JSON
".hero": { "background": "linear-gradient(135deg, #7B5CFA 0%, #FA5CB4 100%)" }

Многослойный фон (изображение + оверлей):

JSON
".media-slot": {
  "background": [
    { "type": "image", "url": "https://images.unsplash.com/photo-1498050108023-c5249f4df085", "scaleMode": "FILL", "opacity": 0.72, "blendMode": "NORMAL" },
    "rgba(0,0,0,0.24)"
  ]
}

Границы, обводка, скругления

СвойствоЧто делает — значенияПример
borderShorthand "<толщина> <стиль> <цвет>""border": "1px solid #E7EAF1"
borderColorЦвет обводки"borderColor": "#E7EAF1"
borderWidthТолщина обводки (px)"borderWidth": 1
borderStyleСтиль обводки — solid, dashed"borderStyle": "dashed"
borderRadiusРадиус скругления (px)"borderRadius": 20
cornerSmoothСглаживание углов 01 (squircle)"cornerSmooth": 0.6
strokeAlignПоложение обводки — inside, center, outside"strokeAlign": "inside"
strokeCap / strokeJoinСтиль конца / соединения линии"strokeCap": "ROUND"
strokeTopWeightstrokeLeftWeightТолщина обводки по стороне (px)"strokeTopWeight": 2
dashPatternПунктир — массив длин штрих/пропуск"dashPattern": [4, 4]
outline / outlineOffsetВнешняя обводка + отступ"outline": "2px solid #0D6EFD"
vectorCornerRadiiРадиусы по вершинам VECTOR (в порядке вершин)"vectorCornerRadii": [0, 8, 8, 0]
JSON
".card": { "border": "1px solid #E7EAF1", "borderRadius": 20 },
"$state=active .card": { "outline": "2px solid #0D6EFD", "outlineOffset": "2px" }

Тени и эффекты

СвойствоЧто делает — значенияПример
boxShadowТени — массив объектов теней, или "none"см. блок
backgroundBlurРадиус размытия фона (px), или "none""backgroundBlur": 12
layerBlurРадиус размытия слоя (px), или "none""layerBlur": 8
opacityПрозрачность слоя 01, или "none" (= 1)"opacity": 0.56
glassЭффект стекла, или "none" для сброса"glass": "none"
effectsПолный композит эффектов (алиас токена или слои)"effects": "{shadow.md}"
JSON
".card": { "boxShadow": [{ "x": 0, "y": 8, "blur": 24, "spread": 0, "color": "rgba(16,24,40,0.14)" }] },
"$state=hover .card": { "boxShadow": [{ "x": 0, "y": 14, "blur": 36, "spread": 0, "color": "rgba(16,24,40,0.20)" }] }

Типографика

Задаётся на ноде TEXT.

СвойствоЧто делает — значенияПример
fontFamilyСемейство шрифта"fontFamily": "Inter"
fontWeightНасыщенность"fontWeight": 600
fontSizeРазмер (px)"fontSize": 18
lineHeightМежстрочный интервал"lineHeight": "24px"
letterSpacingТрекинг"letterSpacing": "0px"
textAlignПо горизонтали — left, center, right, justify"textAlign": "left"
verticalAlignПо вертикали — top, center, middle, bottom"verticalAlign": "center"
textCaseРегистр — none, uppercase, lowercase, capitalize, small-caps"textCase": "uppercase"
textDecorationОформление — none, underline, line-through"textDecoration": "underline"
textSizingАвто-размер — fixed, height-auto, auto, truncate"textSizing": "height-auto"
textTruncationОбрезка — disabled, ending (многоточие)"textTruncation": "ending"
maxLinesМаксимум строк до обрезки"maxLines": 2
paragraphSpacingОтступ между абзацами (px)"paragraphSpacing": 8
paragraphIndentОтступ первой строки (px)"paragraphIndent": 16
leadingTrim / verticalTrimОбрезка leading строки — CAP_HEIGHT, NONE"leadingTrim": "CAP_HEIGHT"
JSON
".title": { "fontFamily": "Inter", "fontWeight": 600, "fontSize": 18, "lineHeight": "24px", "textAlign": "left", "textSizing": "height-auto" }

Композитный ключ typography / font применяет полный текстовый стиль сразу.

Видимость и сброс

  • visible: false — слой остаётся в варианте, но скрыт в Figma;
  • display: "none" — ветка исключается из собранного варианта;
  • если заданы оба, побеждает display: "none". Когда более поздний селектор снова показывает ветку, укажите нужные ей размеры/layout.
JSON
"$loading=true": {
  ".button": {
    ".label": { "visible": false },
    ".spinner": { "display": "flex", "visible": true, "width": "{button.size.icon}" }
  }
}

CSS-подобные очищающие значения (пишутся, чтобы сбросить свойство):

Написание сбросаЭффект
"background": "none" / "transparent"Очищает заливки
"color": "none" / "fill": "none"Очищает текст/currentColor/краску
"boxShadow": "none" / "effects": "none"Очищает эффекты
"padding": "none"Все паддинги 0
"opacity": "none"Резолвится в 1
"mask": "none" / falseСнимает маску
"aspectRatio": "none" / falseРазблокирует пропорцию

Управление инстансом

Задаётся на ноде INSTANCE.

СвойствоЧто делаетПример
componentСмена main-компонента (swap по имени)"component": "WButton"
instanceProperties / propertiesЗначения свойств инстансасм. блок
nestedInstancePropertiesСвойства вложенных инстансов по имени слоясм. блок
refПолное переопределение цели инстансасм. раздел ref
JSON
".action-main": { "component": "WButton", "instanceProperties": { "variant": "primary", "size": "md", "label": "Continue" } }
JSON
".badge": { "nestedInstanceProperties": { "Badge": { "label": "2" } } }

Режимы переменных и Figma-метаданные

СвойствоЧто делаетПример
explicitVariableModesПринудительный режим переменной по коллекции"explicitVariableModes": { "Themes": "Dark" }
variableModesАлиас explicitVariableModes"variableModes": { "Themes": "Dark" }
layoutGridsМассив layout-сеток Figmaсм. блок
exportSettingsМассив настроек экспорта Figmaсм. блок
mask / maskTypeМаска слоя — alpha, vector, luminance, none"mask": "alpha"
JSON
".root": {
  "explicitVariableModes": { "Themes": "Dark" },
  "layoutGrids": [{ "pattern": "GRID", "sectionSize": 8, "color": { "r": 0, "g": 0, "b": 1, "a": 0.12 } }],
  "exportSettings": [{ "format": "PNG", "suffix": "@2x", "constraint": { "type": "SCALE", "value": 2 } }]
}

Сбросить явный режим для коллекции можно через null, false, "none", "auto" или "unset".


Transitions

Прототип-переходы задаются на корне composition (shorthand или объектная форма), но никогда как ключ стиля слоя.

ПолеЧто делаетЗначения
triggerКогда срабатываетon-hover, on-click, on-press, on-drag, on-enter, on-leave, mouse-up, mouse-down, after-timeout: 500
animationТип переходаsmart-animate, dissolve, instant, scroll-animate, slide-in, slide-out, push, move-in, move-out
durationДлительностьнапр. 200ms
easingКриваяlinear, ease-in, ease-out, ease-in-out, ease-in-back, ease-out-back, ease-in-out-back, gentle, quick, bouncy, slow, cubic-bezier(...), spring(...)
directionОпциональное направлениеleft, right, top, bottom
conditionОпциональное условие по переменной{ "variable": …, "op": "==", "value": … }

Shorthand — порядок: trigger animation duration easing [direction]:

JSON
"transitions": { "hover-in": "on-hover smart-animate 200ms ease-out" }

Объектная форма с условием:

JSON
"transitions": {
  "hover-in": {
    "trigger": "on-hover",
    "animation": "smart-animate",
    "duration": "200ms",
    "easing": "ease-out",
    "direction": "right",
    "condition": { "variable": "motion.enabled", "op": "==", "value": true }
  }
}

Theme binding

themeBinding связывает ось варианта (обычно theme) с режимами коллекции переменных для корректного рендера светлой/тёмной темы.

ПолеЧто делаетПример
targetМетка цели привязки"target": "root"
propИмя оси из props"prop": "theme"
modesКарта значение оси → конфиг режима{ "light": { "type": "local", "collection": "Themes", "mode": "Light" } }
applyToКакие домены переключать["variables", "textStyles", "effectStyles"]
JSON
"themeBinding": {
  "target": "root",
  "prop": "theme",
  "modes": {
    "light": { "type": "local", "collection": "Themes", "mode": "Light" },
    "dark": { "type": "local", "collection": "Themes", "mode": "Dark" }
  },
  "applyTo": ["variables", "typography", "textStyles", "effectStyles", "paintStyles"]
}

prop должен существовать в props. У источника режима есть type (local / library), collection, mode и опциональный library. Каждый modes.<value> — это либо плоский источник, либо обёртка { primary, fallback[] }.


Advanced-поля

Встроенные size / style

Файл composition может встраивать DTCG-блоки токенов size и style для самодостаточных пакетов компонентов (неймспейс по имени компонента). Они опциональны и сами по себе на layout не влияют.

JSON
"size": { "md": { "height": "40px", "paddingX": "16px" } },
"style": { "primary": { "bg": "{color.brand.primary}" } }

Slot-host pipeline

Для host/item-систем (segmented controls, вкладки, группы элементов) slotHostPipeline связывает host-набор с его item-набором. slotItemComponentSetName обязателен. Если любой composition-файл определяет slotHostPipeline, легаси-дефолты WSegmentControl не применяются — объявляйте каждый host/item-набор, на который опираетесь.

JSON
"slotHostPipeline": {
  "hostComponentSetName": "WSegmentControl",
  "hostCompositionTokenName": "WSegmentControl",
  "slotName": "item-group",
  "slotItemComponentSetName": "WSegmentControlItem"
},
"segmentIconPostPassRefMarkers": ["WSegmentControl", "WSegmentControlItem"]

Оба ключа также принимаются под обёрткой $figma ($figma.slotHostPipeline, $figma.segmentIconPostPassRefMarkers).


Полный пример

Полный набор компонентов, затрагивающий большинство возможностей: многоосевые props, componentProperties, SLOT и INSTANCE, переопределения по селекторам, корневые transitions и themeBinding.

JSON
{
  "$type": "composition",
  "name": "WPromoCard",
  "$description": "Промо-карточка с медиа-слотом, действием и состояниями.",
  "props": {
    "theme": ["light", "dark"],
    "size": ["sm", "md"],
    "state": ["default", "hover", "disabled"]
  },
  "states": ["disabled"],
  "componentProperties": {
    "title": { "type": "TEXT", "layer": "title", "defaultValue": "Promo title" },
    "showMeta": { "type": "BOOLEAN", "layer": "meta", "defaultValue": true },
    "media": { "type": "SLOT", "layer": "media-slot", "defaultValue": "WImageTile" }
  },
  "structure": {
    "tag": "FRAME",
    "class": "card",
    "name": "Card",
    "children": [
      { "tag": "SLOT", "class": "media-slot", "slot": { "default": "WImageTile" } },
      { "tag": "TEXT", "class": "title", "content": "Promo title" },
      { "tag": "TEXT", "class": "meta", "content": "Meta" },
      { "tag": "INSTANCE", "class": "cta", "ref": { "component": "WButton", "properties": { "variant": "primary" } } }
    ]
  },
  "styles": {
    ".card": {
      "direction": "column",
      "gap": 12,
      "padding": 16,
      "background": "{card.bg}",
      "borderRadius": 16,
      "widthType": "fixed",
      "width": 320
    },
    "$size=sm .card": { "width": 260 },
    "$state=hover .card": { "boxShadow": [{ "x": 0, "y": 12, "blur": 32, "spread": 0, "color": "rgba(0,0,0,0.18)" }] },
    "$state=disabled .card": { "opacity": 0.56 },
    ".title": { "fontFamily": "Inter", "fontWeight": 600, "fontSize": 16 }
  },
  "transitions": { "hover-in": "on-hover smart-animate 160ms ease-out" },
  "themeBinding": {
    "target": "root",
    "prop": "theme",
    "modes": {
      "light": { "type": "local", "collection": "Themes", "mode": "Light" },
      "dark": { "type": "local", "collection": "Themes", "mode": "Dark" }
    },
    "applyTo": ["variables", "textStyles", "effectStyles"]
  }
}

Чеклист адаптации: замените имена компонентов (WImageTile, WButton) на имена из своей библиотеки; создайте коллекцию Themes или уберите themeBinding; начните с Generate, затем итерируйте Apply; держите name стабильным на нодах, адресуемых вложенно.


Для агентов и трансформеров

A) Figma → Composition JSON

  1. Задайте $type: "composition" и стабильный name.
  2. Стройте props только из реальных осей вариантов; добавляйте states для взаимоисключающих условий.
  3. Для каждой ноды пишите валидные tag и class; добавляйте стабильный name для вложенно-адресуемых нод.
  4. Для инстансов пишите ref.component и только валидные примитивные ref.properties.
  5. Для слотов используйте reference mode (slot) или children mode (children), никогда оба.
  6. Все визуальные/layout-правила кладите в styles (база + переопределения по селекторам).
  7. Используйте корневые transitions и themeBinding, а не хаки на уровне слоя.
  8. Проверьте, что referenced-компоненты/токены существуют.

B) Composition JSON → React / Vue

  1. Читайте structure как дерево элементов; используйте class/path-ключи для резолва стилей.
  2. Резолвьте вариантные селекторы ($prop=value .class) против входящих пропсов.
  3. Уважайте видимость веток (display: "none").
  4. Трактуйте ref.component → импорт компонента, ref.properties → передаваемые пропсы.
  5. Трактуйте componentProperties, themeBinding, slotHostPipeline и $figma как метаданные дизайн-тайма, если рантайм их не поддерживает.
  6. Сохраняйте ссылки на токены ({...}) или пре-резолвьте их через свой token-движок.

C) Pre-flight валидация

  • structure существует и у каждой ноды есть tag + class;
  • styles существует и содержит только объектные значения;
  • themeBinding.prop существует в props;
  • нет удалённых легаси-ключей (adapters, sizeStyles, colorStyles);
  • нет конфликта режимов SLOT (slot с непустыми children).

Авторский ключ → runtime-ключ Figma (справка)

Авторский ключRuntime-ключ
directionlayoutMode
justifyContentprimaryAxisAlignItems
alignItemscounterAxisAlignItems
alignContentcounterAxisAlignContent
flexWraplayoutWrap
gap / wrapGapitemSpacing / counterAxisSpacing
widthType / heightTypelayoutSizingHorizontal / Vertical
alignSelf / flexGrowlayoutAlign / layoutGrow
positionlayoutPositioning
top / right / bottom / leftinsets → layout/position
rows / columnsgridRowCount / gridColumnCount
rowGap / columnGapgridRowGap / gridColumnGap
borderWidth / borderAlignstrokeWeight / strokeAlign
borderRadius / cornerSmoothcornerRadius / cornerSmoothing
textSizingtextAutoResize
textAlign / verticalAligntextAlignHorizontal / Vertical
rotaterotation
boxSizing / canvasStackingstrokesIncludedInLayout / itemReverseZIndex
justifySelf / gridAlignSelfgridChildHorizontalAlign / VerticalAlign

Авторское значение → enum Figma (справка)

СвойствоАвтор → enum
directionrow/column/none/gridHORIZONTAL/VERTICAL/NONE/GRID
justifyContentstart/center/end/space-betweenMIN/CENTER/MAX/SPACE_BETWEEN
alignItemsstart/center/end/baselineMIN/CENTER/MAX/BASELINE
widthType / heightTypefixed/hug/fill (алиасы: auto→HUG, stretch→FILL) → FIXED/HUG/FILL
positionrelative/absolute/noneAUTO/ABSOLUTE/AUTO
textSizingfixed/height-auto/auto/truncateNONE/HEIGHT/WIDTH_AND_HEIGHT/TRUNCATE
textCasenone/uppercase/lowercase/capitalize/small-capsORIGINAL/UPPER/LOWER/TITLE/SMALL_CAPS
strokeAligninside/center/outsideINSIDE/CENTER/OUTSIDE
maskalpha/vector/luminance/noneALPHA/VECTOR/LUMINANCE или isMask:false

Примечания: ссылки на токены ({...}) сохраняются и резолвятся во время apply; числовые строки и строки с единицами (px, rem, deg) нормализуются в числа там, где нужно.


Ограничения и предупреждения

  • Неподдерживаемые сочетания свойств/нод игнорируются.
  • Внутренности сторонних/библиотечных инстансов могут быть частично защищены Figma.
  • NESTED_INSTANCE и ref.nested зависят от стабильных имён слоёв.
  • Большие матрицы props дают тяжёлое число вариантов — где уместно, применяйте states.
  • Generate/Apply в Figma тихо пропускает неизвестные ключи стилей, не блокируя документированные свойства и алиасы. Оставляйте unknown keys только если их использует другой output, например code generation.
  • Удалённые легаси-ключи дают ошибку парсинга: adapters, sizeStyles, colorStyles. component: false несовместим с непустыми props.

Связанные страницы