Utilities

Storybook Addon

@sxl-studio/storybook-addon — Storybook panel that displays Figma design context from SXL Studio Code Connect.

What is @sxl-studio/storybook-addon

@sxl-studio/storybook-addon is a custom Storybook addon published on npm. It adds an SXL Studio panel to Storybook that displays Figma design context for each story — Figma Embed, component info, composition JSON, token status, and readiness badges.

The addon reads data from the diff-code-connect.<fileKey>.json registry generated by the SXL Studio Figma plugin, so designers and developers share a single source of truth.

Key features

  • Component name + updated date — panel header with "Open in Figma" button
  • Tokens / Status badges — color-coded status indicators
  • Description — component description from Figma
  • Figma Design Embed — interactive iframe with "Open in Figma Dev Mode" link
  • API Contract — Component Properties and variant count from Figma
  • Code Connect — Import path, implementation files (framework + path), code snippet
  • Composition JSON — "Enabled" badge when composition generation is active

Installation

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

Supported Storybook versions: v8, v9, v10.


Registering the addon (main)

The addon must appear in the addons array. The preset is applied automatically (see below); you do not import the preset in main unless you need the explicit entry — usually a single package string in addons is enough.

Option A — single config file

Use this when Storybook is fully owned by your app repo with no shared preset.

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

Option B — shared config from a package (design system, monorepo)

Often main and preview are imported from an internal package (@scope/storybook-vue, @your-org/storybook-config, etc.). Append the SXL addon to the existing list — do not replace addons wholesale:

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 ?? [] keeps addons from the shared config.
  • @sxl-studio/storybook-addon is appended (order is usually fine; if something conflicts, see the npm README).

Restart the Storybook dev server after changing main / preview.

Preset (v1.1+): not tied to one folder layout

The package ships a preset (Storybook loads it via the storybook.preset field in package.json when the addon is listed under addons). You do not need a specific monorepo layout.

  • CSP — Vite config gets frame-src for https://www.figma.com so the Figma embed iframe works in the manager panel.
  • Composition JSON — if a tokens/tokens export folder exists next to the Storybook app (or two levels above .storybook), files are served at /sxl-tokens/… in dev and copied to static output for storybook build. The registry’s compositionFilePath then resolves without hand-written Vite config.
  • Registry filename — the plugin may write diff-code-connect.<figmaFileKey>.json. If preview imports a stable name like diff-code-connect.SXL-Components.json but that file is missing while another diff-code-connect.*.json exists in the same folder, the preset adds a Vite resolve.alias (if several files match, the first sorted name wins). Alternatively, import the actual file or use fromDiffCodeConnect(raw).
  • No local folder — composition is fetched from Git using repository.url from the registry (as configured in the plugin), when raw access works.

If the preset is not picked up, add @sxl-studio/storybook-addon/preset explicitly to addons (see the npm package README).


Code Connect registry in preview

The plugin writes the registry to diff-code-connect.<figmaFileKey>.json. Load it once into parameters.sxl.registry. The import path is project-specific (app root, tokens/tokens, CI artifact, etc.) — what matters is that the JSON is available to the Storybook bundle (import from preview or equivalent).

fromDiffCodeConnect vs raw JSON

  • fromDiffCodeConnect(raw) — explicitly normalizes diff-code-connect / v2 components[] to the addon’s internal shape. Use when you want one consistent path or mix formats.
  • Direct JSON import as registry — for a current plugin export this is often enough: the addon understands the registry shape.

Option A — minimal 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) },
  },
};

Raw object:

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

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

Option B — on top of a shared preview (monorepo pattern)

If you already use a shared preview with decorators and globals, merge parameters so you do not drop shared settings. Put sxl alongside the rest:

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 },
  },
};

You can add globalTypes, initialGlobals, etc. next to this — they do not affect SXL as long as parameters.sxl.registry is set.

Filename note: the file name includes the Figma <fileKey>; if the plugin emits a new name, update the import — or rely on a stable import filename when the addon preset can map it to the single diff-code-connect.*.json in your tokens/tokens folder (see the preset section above).

Automatic matching

The addon automatically tries to match the current story to a registry entry:

  • Per-story parameters take precedence: sxl.component / sxl.figmaNodeId when set.
  • Otherwise a heuristic uses story context (title, story name, file path): the registry displayName must confidently match (internal score threshold). A single registry entry is not applied to every story — unrelated stories show the “no integration” state.

For stories with no matching registry entry, the panel indicates that Storybook integration was not set up in the plugin for that component (“No Figma integration…”).

Manual matching (optional)

When automatic matching does not work (e.g., component name differs significantly), you can explicitly set the component in per-story parameters:

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

Direct parameters (no registry)

For quick prototyping or a small number of stories:

TS
export const Default = {
  parameters: {
    sxl: {
      figmaUrl: "https://www.figma.com/design/ABC123?node-id=1-2",
      description: "Primary action button",
      tokenStatus: "assigned",
      readiness: "ready-for-dev",
    },
  },
};

Data from the plugin

The SXL Studio plugin writes the following data into the registry, which the addon displays:

Plugin fieldWhat Storybook shows
Display NamePanel header (component name)
Updated AtDate of last binding update
Design EmbedCentered Figma iframe + "Open in Figma Dev Mode" button
Composition JSON"Enabled" badge
Metadata / DescriptionComponent description block
Tokens (True/False)Badge: Tokens (green) / No tokens (gray)
StatusBadge: Complete / Ready for Dev / In Progress / Backlog
Import PathComponent import path in "Code Connect" section
FilesImplementation files with framework tag
Snippet TemplateCode snippet in code block

The Storybook Integration section in the plugin has its own Connect button — independent from the Code Connect button.


Parameters reference

ParameterTypeLocation
sxl.registrySxlRegistryglobal preview.ts
sxl.componentstringper-story
sxl.componentNamestringper-story (alias for component)
sxl.figmaNodeIdstringper-story
sxl.figmaUrlstringper-story (manual)
sxl.descriptionstringper-story override
sxl.tokenStatus"assigned" | "partial" | "none"per-story override
sxl.readiness"complete" | "ready-for-dev" | "in-progress" | "backlog"per-story override
sxl.designEmbedbooleanper-story override
sxl.compositionJsonbooleanper-story override
sxl.metadatabooleanper-story override

Architecture

Figma Plugin (Code Connect + Storybook Integration)
        │
        ▼
  diff-code-connect.<fileKey>.json   ← Git-tracked registry
        │
        ▼
  fromDiffCodeConnect()              ← converter in addon
        │
        ▼
  Storybook parameters.sxl.registry ← loaded in preview.ts
        │
        ▼
  SXL Studio Panel in Storybook     ← renders per-story data

The addon is a pure consumer — it never modifies the Figma file or the registry. All writes happen in the plugin.

Package structure

@sxl-studio/storybook-addon
├── src/
│   ├── manager.tsx      — registers the panel
│   ├── preset.ts        — viteFinal (CSP, local tokens, alias), staticDirs, managerEntries
│   ├── components/
│   │   └── SxlPanel.tsx — panel UI (useParameter hook)
│   ├── convert.ts       — fromDiffCodeConnect converter
│   ├── types.ts         — SxlRegistry, SxlRegistryEntry, etc.
│   ├── constants.ts     — ADDON_ID, PANEL_ID, PARAM_KEY
│   └── index.ts         — barrel exports

Publishing

The addon is published under the @sxl-studio npm scope:

BASH
npm publish --access public

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


Quick checklist

  1. Install @sxl-studio/storybook-addon as a dev dependency.
  2. In .storybook/main.ts, add the package to addons (minimal list or ...(sharedMain.addons ?? [])).
  3. In .storybook/preview.ts, set parameters.sxl.registry (JSON import and/or fromDiffCodeConnect).
  4. Ensure the plugin registry includes required fields (including $figmaFileKey for the embed).
  5. Restart Storybook.