Introduction

What's new

Changes in the latest SXL Studio versions in plain words, and the compatibility table of the plugin with Bridge, Transformer, Resolver and the Storybook Addon.

The installed plugin version is shown on the Tokens tab at the bottom of the empty work area and in the first line of the Diagnostics tab. The plugin updates through Figma Community automatically.

Compatibility

ComponentVersionWhere to get it
SXL Studio plugin2.9.4Figma Community
SXL Bridge1.9.0npm i -g @sxl-studio/bridge, see Bridge utility
Transformer3.4.1npm i -g @sxl-studio/token-transformer, see Transformer
Resolver for VS Code2.3.4VS Code Marketplace, see Resolver
Storybook Addon2.0.2npm, see Storybook Addon

Plugin 2.9.x works with Bridge 1.10.0. If your Bridge is older, update it: Local Workspace and Local Storage may not open.

Transformer: token preservation

Transformer 3.4.0 adds sync --preserve-existing to retain previously generated tokens after JSON removal, update matching declarations and add new ones across all formats. Version 3.4.1 additionally stabilizes repeated force and XML preserve runs, avoids unnecessary smart writes and fixes text escaping. Preserve is enabled only by a CLI flag; see the smart, force and preserve examples.

Utilities accompanying 2.9.3

  • Bridge 1.9.0: more reliable installation through npm, working CLI help/version commands and clearer diagnostics for installed packages.
  • Transformer 3.3.1: improved DTCG objects, gradients, composite aliases, image URLs and easing; corrected repeated SCSS generation and one-time regeneration after upgrading. Platform limitations now produce explicit diagnostics; see Transformer.

2.9.5

  • Responsive variant bindings: STRING tokens in ref.properties, including tokens exported to another file of the workspace (Core library → components file): the variable is imported by its published key. The initial variant follows the placement's mode; unused variable modes do not prevent binding, the active instance value is checked.

  • Variant matrix migration: changing the number of variants or the axes updates the existing ComponentSet in place with preserved IDs; instances of retired variants move to retained ones by native swap with preserved overrides; published variants and removed axis values require an explicit variantMigration map.

  • Unresolved references: the result becomes an error with the primary reason, the current layer keeps its id without cascading errors or repeated stand-ins, and once the reference is fixed Apply brings it to JSON.

  • Full Grid and wrap in compositions: the Figma grid with every setting — column and row counts, fr/px/hug tracks (including repeat(7, 1fr)), gaps, automatic positioning (gridAutoFlow, gridAutoRows), explicit placement of instances into cells (gridRow, gridColumn, spans, alignment); wrapping with wrapGap: "auto" and space-evenly/space-around. Grid and wrap keys removed from the JSON are reset on Apply; a track count that disagrees with the column count is an authoring error with a fix.

  • Hover without moving neighbors: a recipe for independently scaling the entire card in Auto Layout and Grid uses a fixed cell to preserve its footprint and min/max variables, with an inner layer preserving proportions. This is an explicit composition structure, not an automatic wrapper.

  • Proportions and size limits: scaling accounts for min/max variables; a JSON lock with different variables on the two sides of one pair (width/height, minWidth/minHeight, maxWidth/maxHeight) is an authoring error naming the layer, the pair and the fix before any change; the same token on both sides of a pair and variables in different pairs are allowed; a canvas lock (inherited or manual) yields an aspect-lock-settled warning; a failing root style no longer leaves a variant empty. Fixed the reset of explicitly enabled constrainProportions on FRAME nodes.

  • Managed binding recovery in Smart: supported direct variable bindings are checked even when their JSON block has not changed. Manual slot content and inherited instance layers are preserved.

  • Instance scale from JSON: absolute scale for explicitly declared INSTANCE and ICON layers, including a native slot's default instance. Repeated Apply does not accumulate scale; removing the value returns scale to one. See Composition for supported combinations and limits.

  • Late style bindings: a style of any kind (text, fill, gradient, shadow, blur, grid) exported before its variables existed keeps a literal and reports a notice per field with the fix; once the dependencies are exported, an ordinary re-export restores the bindings without Force update all and keeps the style ID.

  • Opacity and blend mode of a layer with a variable-bound colour: a fill layer that references a colour variable and carries its own opacity gets that opacity on the very first export — Figma reset it when the style was created, so the value only landed on the second export. Figma does not keep a blend mode on such a layer: the export leaves NORMAL and reports a notice; use a literal colour on the layer to keep the blend mode.

  • Local Workspace and editor saves (Bridge 1.10.0): after the plugin wrote a file, the Bridge could stop noticing later editor saves of that same file until a restart. Write-finish detection is now done by the Bridge itself, and the momentary absence of the file during a journaled replace no longer derails it.

  • Font-size binding: fontSize retains its numeric variable after the size is written; binding failures appear in diagnostics.

  • Three result statuses and Auto-fix: success, warning with itemized recommendations, error with the list of fixes; Repair and Auto-fix buttons right in the notification (re-link variants, wait for Local Workspace, Repair, then Smart). Bridge 1.10.0 returns status, diagnostics (with details and fixes) and suggestedAction; new auto_fix_composition and reload_local_workspace commands; get_plugin_status reports the Local Workspace state. Notices and errors in every notification — compositions, variables and styles export, Apply Tokens, Apply Data — share one list: a severity glyph, errors first; a long message is broken into a headline and “what is wrong” lines, the fix into separate arrow steps, properties and tokens emphasised, a shared set of steps shown once above the list; the “N errors · M notices” count, Show N more for long lists. Apply Data lists the skipped fields with the reason and the fix instead of a bare “Applied to 0 layers”.

  • Editing the active Local Workspace profile: the name and folders of the active profile change without deactivating it — Save and reopen saves the profile and reopens the workspace from the new folders; an unsaved editor draft or a disk conflict stops the save with an explanation; deleting the active profile still requires Use Plugin Local. Next to the root, tokens and data fields a folder button opens the system folder dialog (Bridge 1.10.0 required); the tokens and data folders must sit inside the Git root.

  • No incomplete operations from Local Workspace reloads: waits for the workspace before writing and retries the tracking write after a canvas change; a disk change that lands during an operation is applied at that operation's readiness wait, and a conflict between an unsaved editor draft and disk stays the user's decision.

  • Variable-bound VARIANT properties with per-variant ref: a ref block inside a $prop=value style section changes only the properties it names on the nested instance; {token} bindings from the structure ref (for example _breakpoint: "{breakpoint}") stay, and after every Apply stage each such binding is verified: a lost binding is an error, not a success.

  • Layer kind switch FRAME ↔ SLOT: Apply changes the tag of an existing layer in place: a standalone component gets a native slot, a variant set gets a SLOT property with bound layers; switching back removes the property without recreating nodes.

  • Literal reference properties in Smart: Smart Apply compares the text, boolean and variant values of nested instances' ref.properties with the live ones and re-applies the ones that drifted, for example after a property rename in the source component.

  • INSTANCE_SWAP and per-variant references: the default comes from JSON; a per-variant component swap on a bound layer is reported, and the audit understands per-variant swaps on ordinary layers.

  • More reliable Generate and Apply: fixes for target-page selection, native slot addition and renaming, adoption of existing slots and cancellation handling. An incomplete operation does not receive a successful update stamp.

2.9.4

  • Native slot settings from JSON: descriptions, preferred components, minimum and maximum layer counts, empty-slot display and the stretch-on-insert setting. Layer-count limits are advisory and do not remove existing content.
  • Rename slot properties with Apply: changing the name under componentProperties while keeping the same layer preserves the property ID, binding and slot content. Unchanged JSON preserves a manual name in Figma. For compositions from earlier versions, apply the original JSON once before changing the name. See Slot settings.
  • Slot defaults by variant: Generate and Apply use the default component, its properties and styles for each parent variant. A nested native slot can also receive a default component. Manual swaps, changed properties, hidden content and intentionally empty slots are protected from overwrites.
  • More accurate component selection: a published component-set key selects the requested variant; name lookup no longer substitutes a component merely because part of its name matches. An exact local name takes precedence when resolving a reference. If a slot default was already created through another name match, use Repair to resolve its reference again. Explicit key and library references retain their precedence and source restrictions.
  • Recover lost component links: Apply can reconnect an existing instance whose local main was deleted to a unique verified component from the same JSON source. Ambiguous targets or unverified preservation of manual content produce a diagnostic.
  • Opacity references in colour expressions: supported rgb, rgba, hsl, hsla, lch, oklch and color(...) values can retain an opacity-token reference without requiring figma.modify. A linked base colour must be opaque for a native separate opacity link. Where Figma does not support the required link, export keeps the computed colour and reports the limitation.
  • Images in composition JSON: Get Code embeds PNG, JPEG and GIF images and preserves crop, reflection, hidden layers and the order of supported effects. Generate and Apply read embedded images; unavailable sources report an error and preserve existing fills. GLASS depends on availability in Figma and is supported without variable bindings.
  • More reliable Apply and Get Code: slot bindings and settings, descriptions, preferred components and empty slots are preserved. Property-binding failures and incomplete updates are no longer reported as successful applications. Invalid outer-property bindings to ordinary layers inside slots are diagnosed before structural changes.
  • Local Workspace and repeated Apply: generation and updates check that synchronization is ready before changing layers. A failed binding save is reported explicitly, and retrying with incomplete tracking does not duplicate existing variants.
  • Remote Connect batch commands: invalid requests are rejected before work starts, and Cancel stops subsequent compositions in the active run. Completed changes remain in place.

2.9.3

  • Apply can recreate a deleted plain composition root (component: false). An unavailable default for an instance-swap property produces a warning without marking the whole Apply as unfinished.

  • Grid labels follow a moved component set on Apply, and old labels on another page are removed. Repeated Apply keeps unchanged labels and repairs manual changes to their text and appearance.

  • Repeated Apply in Local Workspace is faster: composition tracking data is written only when it changes.

  • After a network failure, Local Workspace no longer reports a successful save based on an old copy of the file. If the write outcome is unknown, the workspace must be reloaded before another save.

  • After an interrupted composition Apply, completed variants are remembered and the next Apply resumes unfinished work. Repeated Apply also preserves the link between each variant and its layers.

  • Composition Apply keeps an existing component on its original page and at its original position, including changes between a single component and a variant set. If the target page is unavailable, Apply stops before changing the canvas.

  • Compositions respect an explicit library or published component key, including nested icon replacements. Unavailable references show a warning instead of silently selecting a local component with the same name.

  • Local Workspace: after reopening the plugin, a successful connection restores export and saving even if the first connection check failed.

  • Export has one Sort switch for styles and style folders. Sorting preserves identifiers and bindings; the collection recreation option was removed. Figma does not let plugins reorder existing collections, modes or variables.

  • Compositions: removing a layer from the JSON is applied reliably by smart Apply. After a structural edit the set's non-styling hash stamp was not refreshed, so the next Apply treated a removed layer as a style-only change and left it on the canvas until a repair. The style fast path now also checks live layers against the structure. The Apply result carries applyPlan: which plan ran and why. ref.nested.<layer>.component swaps a nested instance like a manual swap in Figma; instance overrides survive Apply and node ids stay stable.

  • Compositions: an INSTANCE_SWAP property defaults to the variant the layer already shows (ref.properties) instead of the set's default, so binding the property no longer resets variant=secondary. The drift audit compares the composition hash with the last Generate/Apply, honours per-variant instanceProperties overrides, does not count hand-made prototype reactions as drift and understands component: false; component: false roots are tracked in diff-id. The Bridge get_drift_status command answers by hash instead of always reporting no drift.

  • Compositions: an angled CSS gradient (linear-gradient(135deg, …)) on a shape is now written: stops are brought into Figma's range by sliding the handles, where Figma used to reject the fill silently. backgroundBlur / layerBlur from a style token ({blur.bound}{core.space.md}) take the radius from the reference chain and bind the variable; a rejected fill or stroke write shows up in the result warnings.

  • Compositions: a fill from a style token (fill: "{gradient.brand}", "{img.logo}", "{fill.surface-tinted}") links the Figma paint style or builds the layers from the token value; blendMode can be set on a layer; enum values coming from tokens (textCase, textDecoration) are translated to Figma terms; Apply works for component: false; audits and variable usage search now see text-field bindings (size, style, line height, characters).

  • Local Workspace: after a branch switch or a commit in the token repository the session reopens by itself, no Reload needed. With an unsaved draft in the editor the plugin shows a conflict and waits for your decision.

  • Compositions: Apply no longer wipes prototype reactions added by hand and rewrites only the ones created from transitions; variants added by Apply get their own transitions instead of copies of the template's; Apply keeps an existing set where it is instead of moving it to the viewport centre; the first Apply after Adopt keeps component properties made by the designer; array padding maps to sides like CSS; lineHeight and letterSpacing from a token without a Figma variable are written correctly.

  • Compositions: a selector with a condition and a class ("$variant=secondary .root") accepts nested class blocks, and conditions and classes may appear in any order. Such rules used to be dropped while the nested block leaked into the base styles.

  • Compositions: visible: "{token}" binds the boolean variable; a font weight reference binds Font style for a string variable and Font weight for a number; border: "none" removes the stroke; grid track sizes fr / px / auto are written in the current Figma format and the string form "1fr 200px auto" works too; textSizing: "truncate" becomes ellipsis truncation without the deprecated mode.

  • Transitions: named rules ("hover-in") work through from / to in the object form, and a rule without a destination is reported (such rules from the docs used to author no reaction at all); hyphenated axis values in rules ($size=extra-large -> …), after-timeout 500 in the shorthand, matchLayers on directional transitions; an unknown animation or easing now shows up as a warning instead of a silent default.

  • Italic in a text style survives a weight bound to a string variable: the face is written as a literal with a hint in the report.

  • Styles by variable reference: a fill made of one colour reference and a blur / backdrop-blur made of a number reference bind the variable; STRETCH, MIN, MAX and CENTER grids pass Figma's validation; a noise layer is written without blendMode.

  • DTCG value forms: { "value", "unit" } objects for lengths and durations, colour channels { r, g, b, a } and the DTCG colour object (colorSpace, components, alpha, hex) are read as ordinary values. Formulas for duration are evaluated in milliseconds.

  • Colour with opacity exports as a composed Figma cell: a colour token with an alpha modifier gets a colour variable and an opacity variable in one cell, like in the Variables panel, and this also works for a colour reference with a numeric opacity. Where Figma has not opened the write yet, the colour keeps its baked opacity and the report lists such variables.

  • Files, collections and folders on the Tokens screen open in tabs, as in an IDE: rename by double-click, an unsaved dot, a question on close, tab and view memory per workspace. Datasets and mappings of the Database tab live in the same strip.

  • The token card shown on badge hover is rebuilt: the full path and type, a preview, the value as written in JSON and the references with the files that define them; a reference to a formula computes to a number; a click copies the value. Without a chosen mode the preview computes values for the mode of the open file.

  • Fill styles: video and pattern layers, images and videos from the Database, scale mode, rotation and image adjustments, layer visibility, layer opacity as a token reference. Gradients: repeating-*, directions in words, shape, size and position of radial and conic gradients, stop positions in pixels and fractions, references in the angle and positions. Every colour reference still becomes a variable in the style.

  • Text styles: variable-font axes fontVariationSettings (Figma Plugin API 1.138), listSpacing, textWrapStyle, hangingPunctuation, hangingList; the typography form can add them.

  • Token forms no longer lose fields on edit: visibility, blend mode and "shadow behind the layer" of shadows, object values of blurs and images, grid colour and visibility.

  • Import from Figma reads every layer of a fill style instead of the first one and keeps hidden effect layers.

2.9.2

  • The new Figma variable types Timing and Easing are supported: duration tokens export as Timing, cubicBezier and the new easing type as Easing, including presets and springs. Importing from Figma brings them back into JSON. The Export and Import windows got Timing and Easing switches.
  • Effect styles support every current Figma effect: regular and progressive blur, noise, texture, glass and shaders, with variables bound to shadow colour, offset, radius and blur.
  • Colour with an opacity variable: once Figma enables this in your file, a colour token with an alpha modifier that references another token binds the opacity variable itself; until then export works as before.
  • Saving a token file can no longer hang silently: after 20 seconds without a response the editor shows the reason, and the status command in Diagnostics prints the operation queue and the last saves.

2.9.1

  • The Git connection form got the Test connection and Fix buttons: a check of the token, repository, branch and folders with a report and automatic correction of typos in paths and the branch name.
  • The new Diagnostics tab in the synchronization window: the status, diag, test, log and other commands, and a report for support without tokens.
  • The Git Sync window is simpler: sources switch with the Use Git and Set Active buttons in connection rows, and the status shows the time of the last check.
  • The Pull and Push windows compare files like an IDE: unchanged regions are folded, there is navigation between changes and filters by change type.
  • Switching from Local Workspace to Git checks the connection first and never leaves the plugin without a source if Git is unavailable.
  • Clear GitHub and GitLab error texts: a 404 is explained in terms of token permissions, and authorization or rate-limit errors no longer look like an empty repository.

2.9.0

  • The new Local Workspace source: the plugin works directly with a repository folder on disk through SXL Bridge, watches file changes and protects an unsaved editor draft from being overwritten.
  • Several Local Workspace profiles with quick switching from the footer; the last source is remembered per Figma file.
  • The Git connection got the Figma File URL or Key field for cases when the plugin cannot detect the file key itself.
  • Fixed re-applying compositions to regular components.

2.8.10

  • Compositions got a Markdown description and documentation links that reach the Figma panel on Generate and Apply.
  • Get Code updates only the generated fields of a composition and keeps your edits.
  • In the token editor boolean variables have no scopes, and fontWeight allows only FONT_STYLE.

2.8.9

  • Smart matching of variables and styles on export: no duplicate styles and no orphaned variables.
  • Compositions report missing components and unbound variables in the Apply report.
  • The Diff-ID service file is compared by content, not formatting; add diff-id.*.json to .prettierignore.

See also