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
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.
// .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:
// .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-addonis 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-srcforhttps://www.figma.comso the Figma embed iframe works in the manager panel. - Composition JSON — if a
tokens/tokensexport 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 forstorybook build. The registry’scompositionFilePaththen resolves without hand-written Vite config. - Registry filename — the plugin may write
diff-code-connect.<figmaFileKey>.json. Ifpreviewimports a stable name likediff-code-connect.SXL-Components.jsonbut that file is missing while anotherdiff-code-connect.*.jsonexists 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 usefromDiffCodeConnect(raw). - No local folder — composition is fetched from Git using
repository.urlfrom 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 normalizesdiff-code-connect/ v2components[]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
// .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:
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:
// .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.figmaNodeIdwhen set. - Otherwise a heuristic uses story context (
title, story name, file path): the registrydisplayNamemust 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:
export const Default = {
parameters: {
sxl: { component: "WButton" },
},
};
Direct parameters (no registry)
For quick prototyping or a small number of stories:
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 field | What Storybook shows |
|---|---|
| Display Name | Panel header (component name) |
| Updated At | Date of last binding update |
| Design Embed | Centered Figma iframe + "Open in Figma Dev Mode" button |
| Composition JSON | "Enabled" badge |
| Metadata / Description | Component description block |
| Tokens (True/False) | Badge: Tokens (green) / No tokens (gray) |
| Status | Badge: Complete / Ready for Dev / In Progress / Backlog |
| Import Path | Component import path in "Code Connect" section |
| Files | Implementation files with framework tag |
| Snippet Template | Code snippet in code block |
The Storybook Integration section in the plugin has its own Connect button — independent from the Code Connect button.
Parameters reference
| Parameter | Type | Location |
|---|---|---|
sxl.registry | SxlRegistry | global preview.ts |
sxl.component | string | per-story |
sxl.componentName | string | per-story (alias for component) |
sxl.figmaNodeId | string | per-story |
sxl.figmaUrl | string | per-story (manual) |
sxl.description | string | per-story override |
sxl.tokenStatus | "assigned" | "partial" | "none" | per-story override |
sxl.readiness | "complete" | "ready-for-dev" | "in-progress" | "backlog" | per-story override |
sxl.designEmbed | boolean | per-story override |
sxl.compositionJson | boolean | per-story override |
sxl.metadata | boolean | per-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:
npm publish --access public
Peer dependencies: storybook ^8.0.0 || ^9.0.0 || ^10.0.0, react.
Quick checklist
- Install
@sxl-studio/storybook-addonas a dev dependency. - In
.storybook/main.ts, add the package toaddons(minimal list or...(sharedMain.addons ?? [])). - In
.storybook/preview.ts, setparameters.sxl.registry(JSON import and/orfromDiffCodeConnect). - Ensure the plugin registry includes required fields (including
$figmaFileKeyfor the embed). - Restart Storybook.
Related
- Code Connect & Storybook — full setup guide from the plugin side
- Bridge — MCP/WS/HTTP connection to Figma
- Transformer — token transformer CLI