Utilities

Storybook Addon

@sxl-studio/storybook-addon — панель Storybook, отображающая дизайн-контекст Figma из SXL Studio Code Connect.

Overview

@sxl-studio/storybook-addon — кастомный аддон для Storybook, опубликованный в npm. Добавляет панель SXL Studio в Storybook, которая отображает дизайн-контекст Figma для каждой story — Figma Embed, информацию о компоненте, резолвнутый JSON композиции, статус токенов и бейджи готовности.

Аддон читает данные из файла реестра diff-code-connect.<fileKey>.json, генерируемого плагином SXL Studio для Figma, — дизайнеры и разработчики используют единый источник истины.

Ключевые возможности

  • Название компонента + дата обновления — заголовок панели с кнопкой «Open in Figma»
  • Бейджи Tokens / Status — цветовые индикаторы состояния
  • Description — описание компонента из Figma
  • Figma Design Embed — интерактивный iframe со ссылкой «Open in Figma Dev Mode»
  • Индикатор подключения во вкладке — точка рядом с SXL Studio показывает, связан ли текущий story
  • API Contract — Component Properties и количество вариантов из Figma
  • Code Connect — Import path, файлы реализации (фреймворк + путь), шаблон кода
  • Composition JSON — блок JSON с копированием, состояниями загрузки и диагностикой источника

Установка

BASH
npm i -D @sxl-studio/storybook-addon

Поддерживаемые версии Storybook: v9, v10.


Регистрация аддона (main)

Аддон должен оказаться в массиве addons. Preset подтягивается автоматически (см. ниже), отдельно импортировать его в main не нужно, если всё работает — только строка пакета в addons.

Вариант A — один файл конфигурации

Подходит, если весь Storybook настроен в вашем репозитории без общего пресета.

TS
// .storybook/main.ts
export default {
  addons: [
    "@storybook/addon-docs",
    "@sxl-studio/storybook-addon",
  ],
};

Вариант B — общий конфиг из пакета (design system, монорепозиторий)

Часто main и preview импортируются из внутреннего пакета (@scope/storybook-vue, @your-org/storybook-config и т.д.). Важно не заменить список аддонов целиком, а дописать SXL к уже существующим:

TS
// .storybook/main.ts
import sharedMain from "@your-org/storybook-vue/main";

const config = {
  ...sharedMain,
  addons: [...(sharedMain.addons ?? []), "@sxl-studio/storybook-addon"],
};

export default config;
  • sharedMain.addons ?? [] сохраняет аддоны из shared-конфига.
  • @sxl-studio/storybook-addon добавляется в конец (порядок обычно не критичен; при конфликтах см. README пакета).

Перезапустите dev-сервер Storybook после изменения main/preview.

Пресет (v1.1+): не привязан к одной структуре папок

Пакет объявляет preset (Storybook подключает его через поле storybook.preset в package.json, когда аддон указан в addons). Фиксированная раскладка монорепозитория не требуется.

  • CSP — для Figma Embed в панели менеджера в конфиг Vite добавляются заголовки frame-src для https://www.figma.com.
  • Composition JSON — если относительно каталога Storybook (или на два уровня выше .storybook) существует папка tokens/tokens с выгрузкой токенов из плагина, файлы отдаются по /sxl-tokens/… в dev и копируются в статику при storybook build. Тогда поле compositionFilePath из реестра подхватывается без ручной настройки Vite.
  • Имя файла реестра — плагин может записывать diff-code-connect.<figmaFileKey>.json. Если в preview импортируется стабильное имя вроде diff-code-connect.SXL-Components.json, а такого файла нет, но в том же каталоге есть другой diff-code-connect.*.json, пресет добавляет resolve.alias в Vite (при нескольких кандидатах берётся первый по сортировке имён). Альтернатива — импортировать фактический файл или fromDiffCodeConnect(raw).
  • Без локальной папки — composition запрашивается по Git из repository.url в реестре (как настроено в плагине), если raw-доступен.

Если preset не подхватился автоматически, в addons можно явно указать @sxl-studio/storybook-addon/preset (см. README npm-пакета).


Реестр Code Connect в preview

Плагин записывает реестр в файл вида diff-code-connect.<figmaFileKey>.json. Его нужно один раз подключить в parameters.sxl.registry. Путь к файлу зависит от вашего репозитория (корень приложения, папка tokens/tokens, CI-артефакт и т.д.) — главное, чтобы JSON попал в бандл Storybook (импорт из preview или копирование в staticDirs).

fromDiffCodeConnect или сырой JSON

  • fromDiffCodeConnect(raw) — явно приводит diff-code-connect / v2 components[] к формату аддона. Используйте, если хотите единообразный слой или смешиваете форматы.
  • Прямой импорт JSON в registry — для актуального файла из плагина обычно достаточно: аддон понимает структуру реестра.

Вариант A — минимальный preview

TS
// .storybook/preview.ts
import raw from "../path/to/diff-code-connect.<fileKey>.json";
import { fromDiffCodeConnect } from "@sxl-studio/storybook-addon";

export default {
  parameters: {
    sxl: { registry: fromDiffCodeConnect(raw) },
  },
};

Сырой объект:

TS
import registry from "../path/to/diff-code-connect.<fileKey>.json";

export default {
  parameters: {
    sxl: { registry },
  },
};

Вариант B — поверх shared-preview (как в монорепозитории)

Если у вас уже есть sharedPreview с декораторами и глобальными параметрами, смержите parameters, чтобы не потерять настройки shared-слоя. Поле sxl задаётся рядом с остальными:

TS
// .storybook/preview.ts
import sharedPreview from "@your-org/storybook-vue/preview";
import registry from "../../tokens/tokens/diff-code-connect.<fileKey>.json";

export default {
  ...sharedPreview,
  parameters: {
    ...sharedPreview.parameters,
    sxl: { registry },
  },
};

При необходимости добавьте свои globalTypes, initialGlobals и т.д. рядом — на работу SXL это не влияет, если parameters.sxl.registry присутствует.

Практическое замечание: имя файла содержит <fileKey> из Figma; при смене файла в Figma плагин может выдать новое имя — обновите импорт или используйте стабильное имя импорта при условии, что пресет аддона может сопоставить его с единственным diff-code-connect.*.json в каталоге tokens/tokens (см. раздел про пресет выше).

Автоматический матчинг

Аддон автоматически пытается сопоставить текущую story с записью реестра:

  • Сначала учитываются явные параметры story: sxl.component / sxl.figmaNodeId (если заданы).
  • Иначе выполняется эвристика по контексту story (title, имя story, путь файла): имя из реестра (displayName) должно пройти порог уверенного совпадения. Одна запись в реестре не подставляется ко всем stories — на чужих компонентах будет сообщение об отсутствии интеграции.
  • Редактировать story-файлы не обязательно, если имена в реестре и в Storybook согласованы.

Для stories без подходящей записи в реестре панель показывает, что интеграция Storybook в плагине для этого компонента не настроена («No Figma integration…»).

Ручная привязка (опционально)

При необходимости (когда автоматический матчинг не срабатывает) можно явно указать компонент в per-story параметрах:

TS
export const Default = {
  parameters: {
    sxl: { component: "WButton" },
  },
};

Прямые параметры (без реестра)

Для быстрого прототипирования или малого числа stories:

TS
export const Default = {
  parameters: {
    sxl: {
      figmaUrl: "https://www.figma.com/design/ABC123?node-id=1-2",
      description: "Основная кнопка действия",
      tokensBool: "true",
      readiness: "ready-for-dev",
    },
  },
};

Данные из плагина

Плагин SXL Studio записывает следующие данные в реестр, которые аддон отображает:

Поле в плагинеЧто отображается в Storybook
Display NameЗаголовок панели (название компонента)
Updated AtДата последнего обновления привязки
Design EmbedЦентрированный iframe Figma + кнопка «Open in Figma Dev Mode»
Composition JSONРезолвнутый JSON (inline/map/resolver/fetch), состояния load/error, кнопка Copy JSON
Metadata / DescriptionБлок описания компонента
Tokens (True/False)Бейдж tokensBool (true/false) с legacy fallback от tokenStatus
StatusБейдж: Complete / Ready for Dev / In Progress / Backlog
Import PathImport-путь компонента в секции «Code Connect»
FilesФайлы реализации с фреймворком
Snippet TemplateШаблон кода в блоке кода

Секция Storybook Integration в плагине имеет свою кнопку Connect — независимую от кнопки Code Connect.


Справочник параметров

ПараметрТипГде задаётся
sxl.registrySxlRegistryглобально в preview.ts
sxl.componentstringper-story
sxl.componentNamestringper-story (алиас для component)
sxl.figmaNodeIdstringper-story
sxl.figmaUrlstringper-story (manual)
sxl.descriptionstringper-story override
sxl.tokensBool"true" | "false"явный override бейджа Tokens
sxl.tokenStatus"assigned" | "partial" | "none"legacy-override (маппится в tokensBool)
sxl.readiness"complete" | "ready-for-dev" | "in-progress" | "backlog"per-story override
sxl.designEmbedbooleanper-story override
sxl.compositionJsonbooleanper-story override
sxl.metadatabooleanper-story override
sxl.compositionSourcesRecord<string, string>map compositionFilePath → raw JSON
sxl.compositionFetchBaseUrlstringбазовый URL для fetch по compositionFilePath
sxl.compositionDevProxyPrefixstringsame-origin proxy prefix для private Git/CORS
sxl.resolveComposition(path) => Promise<string | undefined>кастомный resolver до fetch-fallback
sxl.debugFigmaEmbedbooleandebug-логи embed (resolved, iframe-load, iframe-error)
sxl.embedUrlMode"auto" | "embed-kit-2" | "legacy"стратегия URL embed (auto: Safari+localhost → legacy, non-localhost браузеры → Embed Kit 2.0)

Диагностика Embed (CSP)

Если iframe Figma пустой:

  1. Включите parameters.sxl.debugFigmaEmbed: true и проверьте события [SXL Studio addon] Figma embed в консоли браузера.
  2. В Vite-конфиге Storybook смержите CSP через mergeSxlFigmaFrameSrcHeader из @sxl-studio/storybook-addon/preset.
  3. Проверьте, что ссылка Open embed in new tab открывается с тем же URL.
  4. Аддон поддерживает оба формата: Embed Kit 2.0 (embed.figma.com) и legacy (www.figma.com/embed). В режиме auto для Safari+localhost используется legacy, а для Safari/Chromium/Firefox на non-localhost — Embed Kit 2.0.
  5. Аддон подставляет embed-host из текущего host Storybook (например, localhost:6006 или storybook.company.com) для стабильной идентификации локации.
  6. Если логин запрашивается при каждом обновлении страницы, разрешите third-party cookies и Storage Access для figma.com в настройках браузера (авторизация embed контролируется privacy-политикой браузера).

Архитектура

Figma Plugin (Code Connect + Storybook Integration)
        │
        ▼
  diff-code-connect.<fileKey>.json   ← реестр в Git
        │
        ▼
  fromDiffCodeConnect()              ← конвертер в аддоне
        │
        ▼
  Storybook parameters.sxl.registry ← загружается в preview.ts
        │
        ▼
  Панель SXL Studio в Storybook     ← рендерит данные для story

Аддон — чистый потребитель данных. Он не модифицирует ни Figma-файл, ни реестр. Все записи происходят в плагине.

Структура пакета

@sxl-studio/storybook-addon
├── src/
│   ├── manager.tsx      — регистрация панели
│   ├── preset.ts        — viteFinal (CSP, локальные tokens, alias), staticDirs, managerEntries
│   ├── components/
│   │   └── SxlPanel.tsx — UI панели (useParameter hook)
│   ├── convert.ts       — конвертер fromDiffCodeConnect
│   ├── types.ts         — SxlRegistry, SxlRegistryEntry и т.д.
│   ├── constants.ts     — ADDON_ID, PANEL_ID, PARAM_KEY
│   └── index.ts         — barrel-экспорты

Публикация

Аддон публикуется под npm scope @sxl-studio:

BASH
npm publish --access public

Peer dependencies: storybook ^9.0.0 || ^10.0.0, react.


Краткий чеклист

  1. Установить @sxl-studio/storybook-addon в devDependencies.
  2. В .storybook/main.ts добавить пакет в addons (к минимальному списку или через ...(sharedMain.addons ?? [])).
  3. В .storybook/preview.ts задать parameters.sxl.registry (импорт JSON и/или fromDiffCodeConnect).
  4. Убедиться, что в реестре из плагина заполнены нужные поля (в т.ч. $figmaFileKey для embed).
  5. Перезапустить Storybook.

Связанные разделы

  • Code Connect & Storybook — полный гайд настройки со стороны плагина
  • Bridge — MCP/WS/HTTP соединение с Figma
  • Transformer — CLI трансформер токенов