Узнайте, как связать переменные Figma с Angular-проектом и синхронизировать дизайн-систему с помощью Style Dictionary.

В предыдущих статьях мы разобрали, как подключить CSS-фреймворк, структурировать SCSS, собрать цветовую палитру и кастомизировать компоненты за пределами того, что позволяют одни только переменные. К концу первой серии статей в проекте появился централизованный файл переменных и чистый слой кастомизации над Bootstrap. Это руководство предполагает, что такая настройка у вас уже есть. В этой статье мы делаем следующий шаг — подключаем источник этих переменных напрямую к Figma.

Что такое дизайн-токены

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

Проблема, которую решают токены, — это расхождение. Со временем значение цвета в SCSS и «тот же» цвет в Figma незаметно расходятся. Дизайнер обновляет цвет бренда в Figma. Разработчик не замечает. Через полгода в продакшене оказывается два чуть разных оттенка синего. Знакомо? Если вы хоть раз искали hex-значение цвета по всему коду, чтобы массово его обновить, вы уже сталкивались с этой проблемой на практике.

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

На практике процесс выглядит так:

  1. Figma (переменные)

  2. tokens.json (экспорт из Figma)

  3. Пакет Style Dictionary в проекте

  4. SCSS-переменные

  5. Bootstrap встраивает цветовые токены в свою палитру


Настройка переменных в Figma

В вашем Figma-файле откройте панель Local variables, создайте новую коллекцию с именем Brand и добавьте шесть цветовых переменных:

Brand/primary   → #0d6efd
Brand/secondary → #6c757d
Brand/success   → #198754
Brand/info      → #0dcaf0
Brand/warning   → #ffc107
Brand/danger    → #dc3545

Такое именование не случайно. Функция экспорта в Figma использует последний сегмент пути переменной как ключ токена, с учётом регистра — как напишете, так и попадёт в JSON. То есть Brand/primary становится токеном primary, и так далее — пишите последний сегмент в нижнем регистре, чтобы он совпадал с именами токенов, которые генерирует Style Dictionary ($token-primary, а не $token-Primary).

Это значит, что коллекцию в Figma можно организовать как угодно — Brand/colors/primary, Semantic/states/success — пока совпадает последний сегмент. Одно правило вместо жёсткой структуры папок, которую нужно соблюдать — гораздо более гибкий подход.

Поскольку это нативные переменные Figma, любой, кто откроет Dev Mode или панель Inspect, увидит имя переменной — Brand/primary — рядом с любым слоем, который её использует.


Экспорт переменных в JSON

Вот часть, которую легко переусложнить: синхронизация файла токенов с Figma.

Вы можете использовать плагин, который выкладывает изменения токенов прямо в ваш GitHub-репозиторий, но это решает проблему, которой у этого проекта на самом деле нет. Цвета бренда меняются нечасто. Основной цвет может измениться раз в год, но не каждую неделю. Автоматизация редкого события в основном добавляет сложность, которая вам не нужна. Поэтому лучше оставить реализацию простой.

В Figma уже есть всё необходимое для этого шага. Откройте панель Local variables, выберите коллекцию Brand и нажмите Export modes. Figma создаёт .zip-архив с одним файлом на каждый режим, названным по его имени — для коллекции с одним режимом распакуйте архив, и вы получите файл вроде tokens.json:

{
    "primary": {
        "$type": "color",
        "$value": {
            "colorSpace": "srgb",
            "components": [0.05098039, 0.43137255, 0.99215686],
            "alpha": 1,
            "hex": "#0d6efd"
        },
        "$extensions": {
            "com.figma.variableId": "VariableID:1:2",
            "com.figma.scopes": ["ALL_SCOPES"]
        }
    },
    // ...та же структура для secondary, success, info, warning, danger
    "$extensions": { "com.figma.modeName": "Mode 1" }
}

Это настоящий файл токенов — $type и $value в точности то, что ожидает Style Dictionary — с одним отличием: $value здесь объект — colorSpacecomponentsalphahex, а не простая hex-строка. Это отличие в форме — вопрос конфигурации, а не ручного редактирования — следующий раздел покажет как Style Dictionary может читать его в таком виде.

Когда вы запускаете сборку локально и проверяете сгенерированный SCSS-файл, это позволяет протестировать все изменения перед релизом. В этом случае нет автоматического деплоя, который придётся откатывать, если что-то пойдет не так.


Сборка Style Dictionary

Чисто декларативного JSON-конфига здесь было бы достаточно, если бы наши токены уже были простыми значениями DTCG (Design Tokens Community Group) — без единой строчки собственного кода. В нашем случае — почти так: экспорт из Figma оборачивает каждый цвет в { colorSpace, components, alpha, hex } вместо простой строки, и ни один встроенный трансформ не понимает такую форму. Это единственное, что наш конфиг должен обрабатывать сам, через небольшой препроцессор — всё остальное может оставаться встроенным трансформом Style Dictionary, включая и сам вывод цвета.

yarn add style-dictionary --dev

Создайте /src/sd.config.mjs:

import StyleDictionary from 'style-dictionary';

// Понимает исходный файл, который Figma создаёт по кнопке "Export modes" —
// превращает {$value: {hex, ...}} в простую hex-строку, отбрасывает
// шум $extensions и оставляет имена токенов плоскими в корне.
StyleDictionary.registerPreprocessor({
    name: 'figma-export',
    preprocessor: (tokens) => {
        const { $extensions, ...rest } = tokens;
        return Object.fromEntries(
            Object.entries(rest).map(([name, t]) => [
                name,
                { $type: t.$type, $value: t.$value.hex ?? t.$value },
            ]),
        );
    },
});

export default {
    usesDtcg: true,
    preprocessors: ['figma-export'],
    source: ['design-tokens/tokens.json'], // файл прямо из экспортного zip-архива Figma

    platforms: {
        scss: {
            prefix: 'token',
            transforms: ['name/kebab', 'color/css'], // primary → token-primary
            buildPath: 'src/styles/_/',
            files: [
                {
                    destination: 'tokens.generated.scss',
                    format: 'scss/variables',
                    options: { outputReferences: true },
                },
            ],
        },
    },
};

Препроцессор figma-export — единственная кастомная часть, и это единственная причина, по которой этот файл написан на JS, а не в виде JSON — всё остальное (name/kebab, color/css, scss/variables) — встроенные трансформы/форматы Style Dictionary. Как только форма приведена к плоской, это обычная декларативная сборка — та же схема, которую вы бы использовали для экспорта из Zeplin или любого другого инструмента со своим форматом токенов: указываете source на файл, учите Style Dictionary его структуре и оставляете остальной пайплайн универсальным.

Примечание: папка design-tokens добавлена в .gitignore. Поскольку файл tokens.json используется только для регенерации новых SCSS-переменных, хранить его в репозитории не имеет смысла.

Укажите конфиг в скрипте через CLI Style Dictionary в package.json:

{
    "scripts": {
        "tokens:build": "style-dictionary build --config src/sd.config.mjs"
    }
}

Запустите yarn tokens:build, чтобы сгенерировать файл в первый раз.


Сгенерированный результат

После сборки вы получаете src/styles/_/tokens.generated.scss:

// Do not edit directly, this file was auto-generated.

$token-primary:   #0d6efd;
$token-secondary: #6c757d;
$token-success:   #198754;
$token-info:      #0dcaf0;
$token-warning:   #ffc107;
$token-danger:    #dc3545;

Обратите внимание, что файл лежит в подпапке _/ — по соглашению из предыдущей статьи, где такая папка содержит автогенерируемые SCSS-файлы.

Примечание: если позже какой-то функции понадобятся эти значения во время выполнения, то стоит добавить CSS-переменные или TypeScript-константы. До этого момента проект использует цвета только на этапе компиляции SCSS.


Подключение токенов к Bootstrap

Теперь встроим токены в тему Bootstrap. Сгенерированный файл лежит в _/, поэтому в src/styles/variables/palette.scssмы импортируем его на уровень выше и связываем переменные $token-* с семантическими именами цветов Bootstrap:

// ── Дизайн-токены
// Источник истины: design-tokens/tokens.json
// Как обновить: экспортировать заново из Figma (Local Variables → Export modes) → `yarn tokens:build`
@import '../_/tokens.generated';

// Связываем переменные токенов с цветами темы Bootstrap
$primary:   $token-primary;
$secondary: $token-secondary;
$success:   $token-success;
$info:      $token-info;
$warning:   $token-warning;
$danger:    $token-danger;

Это и есть место подключения. Когда Bootstrap генерирует свою систему компонентов — кнопки, бейджи, алерты, состояния валидации форм — он использует $primary, $success и остальные переменные. Привязав их к $token-primary и другим дизайн-токенам, вы сделали всю тему Bootstrap продолжением Figma файла, а не копией с него.

Порядок импорта в vendor.scss — то, что заставляет это работать:

// функции Bootstrap (нужны всему остальному)
@import 'bootstrap/scss/functions';
// стандартные переменные Bootstrap
@import 'bootstrap/scss/variables';

// наши переопределения — должны идти ПОСЛЕ переменных Bootstrap,
// чтобы можно было использовать собственные функции Bootstrap в наших значениях
@import 'variables/variables'; // импортирует _palette.scss → ../_/tokens.generated.scss

// теперь Bootstrap может строить систему компонентов на основе наших цветов
@import 'bootstrap/scss/maps';
@import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/utilities';
// ... импорты компонентов

Порядок импорта критичен. Наши собственные переменные должны идти после стандартных переменных Bootstrap (шаг 3), потому что Bootstrap использует свои функции, например tint-color(), для генерации оттенков. Если импортировать наши переопределения до загрузки функций, сборка завершится ошибкой.

Итоговый результат — цепочка переменных из пяти шагов:

  1. Переменная Figma — Brand/primary установлена в #0d6efd.

  2. Экспорт — нажатие Export modes записывает это значение в tokens.json.

  3. Сборка — yarn tokens:build превращает его в $token-primary: #0d6efd внутри tokens.generated.scss (не редактировать вручную).

  4. Связывание — _palette.scss импортирует этот файл и задаёт $primary: $token-primary.

  5. Результат в компонентах — система переменных Bootstrap подхватывает $primary, поэтому .btn-primary { background: $primary; }.

Меняете цвет в Figma → заново экспортируете режим → запускаете yarn tokens:build → каждый компонент Bootstrap обновляется автоматически, по вашему собственному графику.


Заключение

В этой статье мы разобрали, как построить процесс передачи дизайн-токенов из Figma в код на основе нативных переменных Figma и её собственного JSON-экспорта, с ревью перед сборкой вместо синхронизации без присмотра.

К концу статьи у вас должно быть:

  1. Коллекция Brand из нативных переменных Figma, экспортированная в файл design-tokens/tokens.json.

  2. Декларативный конфиг Style Dictionary с небольшим препроцессором figma-export, генерирующий src/styles/_/tokens.generated.scss в виде SCSS-переменных.

  3. Новый слой в _palette.scss, который связывает переменные $token-* с системой темы Bootstrap.

В следующей статье пойдём глубже — подключим Figma к пайплайну через плагин Tokens Studio и построим автоматизированный процесс деплоя для команд, где токены меняются достаточно часто, чтобы ручной экспорт не стал узким местом. Следите за обновлениями!

Комментарии (0)