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.6Figma Community
SXL Bridge1.11.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 and newer. If your Bridge is older, update it: Local Workspace and Local Storage may not open. Several tabs, Figma Desktop control and destructive commands that turn on by themselves need Bridge 1.11.

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.6

  • Library components by name from anywhere in the file: a ref.component without key or library finds the published component through an instance on any page of the document — even under a renamed layer or inside another instance. Previously the instance had to lie on the current page and carry the component's name, otherwise Generate and Apply failed with "Unresolved component". This applies to INSTANCE and ICON layers, nested references, icon swaps and INSTANCE_SWAP values given by name; preferred lists and property defaults are not searched in the document. The variant is selected from the published default variant by properties and its key is remembered for later runs; the existing lookup order and its cost are unchanged — the document search runs only where the reference used to stay unresolved. Same-named components from different libraries are never chosen automatically (the message lists their keys for key), and a workspace composition that no other file generates is never replaced by a published namesake. Details: Composition.
  • Icon by name without a manual index (optional): when the Bridge runs with a Figma token, one icon of a library in the file is enough — the others are found by name automatically; the token stays in the Bridge.
  • Smaller diff-id file: the ledger is written one entry per line without indentation — the same data, about a third smaller (5.7 MB → 3.6 MB on a real design system), and a changed variable or mode is a one-line Git diff. The first save rewrites the whole file once. Keep diff-id.*.json in .prettierignore if your repository formats JSON. Older plugin versions read the new file as usual and may write the indented form back — harmless. Clean up Diff-ID converts the file without an export.
  • Clean up Diff-ID forgets deleted components without a JSON: the former Compact Diff-ID action is now called Clean up Diff-ID (the compact_diff_id agent command keeps its name; its result gained a removedRoots[] field). When a generated component is no longer in the file and its composition JSON is not in the workspace, its record is removed from the diff-id. A component whose JSON remains is still remembered: after a restore from version history Apply finds it again. The same happens on an export with Delete or Force enabled: in the deletion list such records are shown as informational rows marked "Diff-ID", are not counted among the objects to delete, do not trigger the confirmation on their own, and are forgotten only after a successful export. Generate and Apply forget no records. For agents preview_export_variables returns them in deletionPlan.forgottenCompositionRecords[]. Details: Exporting variables and styles.
  • Diff-ID actions moved to where they belong: the bottom of the Tokens tree keeps three actions, always visible: Export variables & styles, Import variables & styles and Collection Settings. Clean up Diff-ID, Reset Diff-ID for one collection… and Reset Diff-ID… are in the Export window, the Diff-ID sub-block of Export settings; the one-collection reset moved there from Collection Settings. Index library components and Clean up Diff-ID are in the Local Workspace window, the Workspace tools section; the only remaining warning about a Diff-ID above 28 MiB is there too. Confirmations are shown in a plugin window. Reset Diff-ID for a single file is still in the file's context menu in the tree, and the Compact Diff-ID button in the oversized-file error is unchanged.
  • The same collapsible blocks in every window: Import, Collection Settings, the Git connection form, Local Workspace and Cross-file are built from the same collapsible blocks as the Export window. The open or collapsed state is remembered per window; a block that gets an error or a warning opens by itself, and the problem is shown in its header.
  • Removing a published variant no longer blocks Apply: when an axis value is removed from the JSON, published variants are removed with a warning instead of a refusal that asked for a variantMigration block. Instances in this file move to a surviving variant; instances in other files lose their library link only after your next publication — Figma's publish dialog lists the removed variants.
  • A slot holding an instance of a deleted component is repaired by Apply: when a slot's default instance points to a deleted component (Figma shows "Missing variant"), Apply switches the same layer to the component from the JSON and reports which deleted component was replaced. Before, such an instance was treated as manual content and stayed broken. An instance of a live component chosen by hand is still kept.
  • A variant deleted by hand is re-created in the same set: deleting the default variant no longer makes Apply build a second set with new ids, and deleting any other variant no longer fails the first Apply with "binding target … is missing".
  • Delete removes what the plan promised: a collection removed from config and its Styles are removed with any collection selection. Before, one frozen Variable in an unrelated collection (for example a token path defined in two collections) silently cancelled every whole-collection removal. When an export still keeps an object of the confirmed plan, it names the object and the reason.
  • Applying a selected component no longer rebuilds every variant: Apply from the composition badge (and with anchorNodeId over the Bridge) now skips unchanged variants and rebuilds only the changed ones, like a regular Smart Apply. Before, every such Apply rebuilt the whole set: about two minutes for a 120-variant set even with no JSON change.
  • Editing ref.styles and refStyles no longer rebuilds variants: when the only JSON change is the styles of a referenced instance's root — ref.styles in structure, refStyles in styles, or styles inside a variant ref — Smart Apply writes those styles again on the instances of the changed variants and repeats what a full Apply writes on the same instance after them: the layer's own styles, its root and dot blocks. Variants, slots and instances are not re-created. Before, such an edit rebuilt every affected variant (about a second per variant). When the result cannot be proven equal to a full Apply — for example the slot default was replaced by hand, the reference has ref.slots or scale, or an icon colour edit could be overwritten by another block — Apply runs in full, as before. More: Composition.
  • Slots after Generate on a large page: right after a set is assembled Figma refuses a native slot's binding to its component property for a while; on a page with hundreds of components the plugin waited too little and reported "SLOT bindings could not be established", even though the next Apply bound the slot. The wait is now longer and is spent only while Figma refuses. For a single component (no variants) the slot binding result is now awaited: before, a failure could miss the operation result.
  • A component that gains axes stays the same node: when the JSON of a component without props gains axes, Smart Apply makes it the default variant of a new set with the same id and instances. Before, this only worked when the tracking already held the component under a variant key: usually it holds it under the single-component key, and after a failed Apply (for example an unresolved reference) not at all, so Apply built a new set next to it, left the original component alone and reported success. Now such a run either includes the original component in the set or stops before combining with an error and removes the variants it created (before, they stayed on the page as separate components). The set lands in the section or frame the component lived in (before, on the page at the section's coordinates, far from it). Back — when the axes are removed from the JSON — the set collapses into its default variant with its id, in the set's place; before, this transition stopped with a variant migration error ("invalid variant key") or created a new component. More: Composition.
  • The agent drives the plugin by itself: Remote Connect turns on every time the plugin starts and waits for commands in the background. The interface stays usable, and the link comes back by itself after a rebuild and after a Bridge restart. Destructive commands turn on by themselves with Bridge 1.11, except in protected files; the agent controls them with set_session_policy and protect_file. Bridge 1.11 keeps the plugin connected in several tabs at once and sends each command to the chosen file: every plugin tool accepts targetFileKey, the answer shows where the command went, and a protected file never becomes the target by itself. On macOS it opens files in Figma Desktop and runs and restarts the plugin. More: Bridge.
  • The deletion plan shows variables that are still in use: when an export with Delete or Force removes a variable that layers of the file are still bound to, the confirmation window says how many layers, and on which pages, would point at a deleted variable.
  • First export of a large DS in one run: collections are filled in dependency order (ref), deferred aliases are bound until they converge; the order of collections in the Variables panel stays the config order.
  • Font weight name no longer depends on the export selection: the family a fontWeight token is used with is looked up in every enabled collection. Before, exporting one collection wrote, for example, Semi Bold, a full export wrote Semibold, and the two runs kept rewriting each other's value.
  • Local Workspace: a command during a disk reload waits instead of failing: when a file on disk has just changed, an export or another write waits for the workspace reload (up to 20 seconds) instead of the "write synchronization is not active" error.
  • Transitions: key trigger (on-key Enter), mouse-enter / mouse-leave, trigger delay, actions url, set-variable, set-variable-mode and several actions per reaction. An unknown word in transitions stops Apply with an error instead of silently becoming on-click / smart-animate; cubic-bezier(…) with spaces works in the shorthand.
  • New style keys: textWrap, listSpacing, hangingPunctuation, hangingList, strokeMiterLimit; stroke cap, join and dashes removed from the JSON reset on Apply.
  • ref.expose exposes a nested instance on the parent component; the drift audit warns about native slot limit violations.
  • Renaming an axis value keeps instances: tone: b → beta at the same position renames the variants in place, ids and instances stay; when a value is removed, instances move on their own to the variant with the same other axes and the default value. A rename used to delete the variants and leave instances on a deleted component.
  • Properties of an instance in a nested instance's slot: ref.nested.*.slots with an INSTANCE_SWAP property by name no longer fails with "did not take effect".
  • Saving the diff-id in a fraction of a second: saving composition tracking no longer depends on how many variables the ledger holds (about a second per megabyte before).
  • Variants reach any depth: a ref block in a $prop=value section is an overlay on the structural ref: component need not be repeated, properties merge by key, nested, slots and overrides by entry. A block without component and a variant ref.nested were silently not applied before.
  • Style properties without effect are visible: a key that does nothing for that kind of layer (for example fill on a FRAME) produces a warning naming the layer, the selector and the matching property.
  • Library index: the Index library components command (the Local Workspace window, the Workspace tools section) in a library file writes the names and keys of its components to the workspace; after that an icon or a library component is inserted by name even when the document has no instance of it. Details: Composition.
  • Colour with opacity from variables: a "colour + opacity" cell is written in Figma's public { color, opacity } form (Plugin API update 139, 17 September 2026). Figma stopped accepting the earlier internal form, so every such cell received a baked colour and a warning. The earlier form stays a fallback for older editor versions, both are read; a form refused for every cell is reported once per export.
  • nested.path through a native slot: a path reaches slot content by the layer name from the master's JSON. Figma names a slot's default instance after its component, so the path stopped at "segment … was not found". The rule applies only to a native slot that holds a single instance; every other segment is still matched exactly and no layer is renamed.
  • One token file in two collections: a library file enabled in its own collection and mounted as source in another no longer produces "alias type is ambiguous" for a third collection that references it. Definitions that agree on type, alias and value count as one answer; real conflicts remain an error.
  • The reason of an unresolved reference is visible in the notification: the line with the reason and the search coverage (instances and pages read) is shown as a warning instead of a hidden info entry.
  • Bulk generation by dependencies: bulk_generate_compositions generates a master before the compositions that reference it; the order of other files is unchanged. A clean workspace generation no longer needs repeated passes because of alphabetical order.
  • Local Workspace with delayed responses: an unanswered event request no longer ends the session after four attempts. Such a request loses nothing — the next one repeats the same cursor — so the plugin keeps polling for up to two dozen attempts, for example while the Figma tab is in the background; other network errors are handled as before.
  • Fast save after Generate and Apply in Local Workspace: the time to write Diff-ID after a composition no longer grows with the number of variables and styles in the file. On the first save in 2.9.6 the composition sections of the Diff-ID file move to the end of the file: the content is the same, and Git shows it as one large move. Version 2.9.5 reads such a file as usual.
  • Deletion list and confirmation on export: an export that is going to delete something first analyses the file without changes and shows a list in the notification grouped as "Removed from JSON (tracked)", "Foreign — not created by SXL", "Disabled in config" and "Kept" with the reason, with delete and cancel buttons. Cancel changes nothing, nothing outside the confirmed list is deleted; the auto-export after Pull never deletes and never asks. Details: Export variables and styles.
  • New rules for Delete and Force update all: with both settings off the export only adds and updates, returning hand edits of names and values in Figma to the JSON with the same identifiers. Delete orphaned variables & styles deletes only what SXL exported earlier and what no longer exists in JSON, inside the selected collections and types; hand-made objects and whatever is switched off in the configuration stay untouched. Force update all brings the file to exactly the JSON without resetting identifiers: identical values are not rewritten (on a synchronized file 0 created, 0 updated, 0 deleted), and everything the enabled JSON does not define is deleted — leftovers of earlier exports, hand-made objects, switched-off collections and modes. With part of the collections selected, cleanup happens inside them only; in a file without diff-id hand-made objects are not deleted; styles used by compositions, library objects and switched-off types are never touched.
  • Reset Diff-ID without duplicates: the next export reconnects existing variables by name and type, and styles by name and kind, and records their identifiers.
  • Strict numbers and units: decimal comma (1,5px = 1.5), pt, pc, in, cm, mm, Q are converted to pixels (10pt = 13.33), units are case-insensitive, and the same works in formulas (10pt + 2px, {a} * 1,5; inside the parentheses of a function a comma separates arguments). Units without a pixel value (vw, vh, ch, fr and others) and notations like 12abc or 1,234,567 are no longer read as the number in front of the tail: the token is skipped with the reason, neighbours are exported. See Dimension.
  • Colours outside sRGB without a hue shift: lch(), oklch(), color(display-p3 …) literals and results of lighten, darken, mix in lch and oklch are brought into sRGB by reducing chroma while keeping lightness and hue (CSS Color 4) instead of clipping channels. lighten by 100 % gives exact white, darken by 100 % gives exact black in every space.
  • Colour function names in any case: RGB(…), OKLCH(…) are accepted; the oklch() lightness may be a percentage, for example oklch(70% 0.15 250).
  • Formulas in style fields: numeric shadow, blur, effects, grid and typography fields accept formulas such as "{dim.px} / 3"; the value is computed and written as a number with a notice that a formula cannot be bound — to keep the link, reference a token that holds the formula. Literal numbers in styles accept the same units; em in lineHeight and letterSpacing is relative to the font size (1.5em = 150 %). A style connected by name is reported as updated, not created.
  • Fractions in glass and noise: a reference to an opacity token in the glass lightIntensity, refraction, dispersion and the noise opacity, density keeps its fraction: 0.48 stays 0.48 instead of turning into the maximum.
  • Bridge 1.11: preview_export_variables returns the same deletion list without writing, and an export_variables call that needs to delete something requires confirmDestructive: true; without it nothing changes.
  • rem base in the export settings: the base size for rem, em and percentages is set in the export window as a number or a token reference; the field left Collection Settings, the value is still stored in config.json. Formulas and numbers in style fields use this base instead of 16. A reference that cannot be resolved stops the export before any change.
  • Local Workspace and bursts of saves: when files change on disk while the plugin is re-reading the workspace (several files saved at once, git checkout), the read is repeated automatically; a manual Reload was required before.
  • variantMigration no longer blocks Generate: the block may stay in the JSON forever; when there is no ComponentSet or its matrix already equals the JSON it is ignored, and Generate recreates the set without editing the JSON.

2.9.5

  • Compact Diff-ID: a red action at the bottom of the Tokens tree when the ledger is above 28 MiB, and the compact_diff_id agent command, rewrite the ledger in the compact schema without an export or an Apply, keeping every id; when the ledger grows past the Bridge limit and the workspace cannot open, the same button appears in the error message (Bridge 1.10.2 or newer).

  • Compact composition tracking in diff-id (schema 3): layer keys are written once per root and variants store only ids, the legacy compositions section is no longer stored, and a root whose node is gone is retired once its replacement is proven; a real design-system ledger shrinks several times while Generate and Apply work on the same in-memory maps. A ledger written by 2.9.5 needs 2.9.5 or newer to apply compositions; variables and styles export is unchanged.

  • 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.

  • Nested slots when the host switches variant: content a composition placed into a nested instance's native slot stays authored when the same ref.nested block switches the instance's VARIANT property (for example size: md): Figma rebuilds the instance's layers with new ids and ownership transfers instead of the "copied slot ownership…" error. A manually copied instance with the same content is still not adopted.

  • Native slot in a variant set on Generate: in a library file generation could stop with "Slot … could not be attached" because a fresh slot's property reference came back empty right after the variants were combined. The plugin reads the references at creation and around the combine and re-verifies the binding; a refusal notice shows the keys and the slot creation trace.

  • Replacing slot content without a native binding: when the host component's slot layer stayed a plain FRAME (a component created before native slots), ref.slots with op: "replace" swaps the single instance inside it in place instead of hiding the old one and inserting a new one, which Figma refuses inside an instance; on refusal the previous content stays visible and the result carries an error.

  • 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