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
| Component | Version | Where to get it |
|---|---|---|
| SXL Studio plugin | 2.9.6 | Figma Community |
| SXL Bridge | 1.11.0 | npm i -g @sxl-studio/bridge, see Bridge utility |
| Transformer | 3.4.1 | npm i -g @sxl-studio/token-transformer, see Transformer |
| Resolver for VS Code | 2.3.4 | VS Code Marketplace, see Resolver |
| Storybook Addon | 2.0.2 | npm, 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.componentwithoutkeyorlibraryfinds 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 toINSTANCEandICONlayers, nested references, icon swaps andINSTANCE_SWAPvalues given by name;preferredlists and property defaults are not searched in the document. The variant is selected from the published default variant bypropertiesand 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 forkey), 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.*.jsonin.prettierignoreif 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_idagent command keeps its name; its result gained aremovedRoots[]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 agentspreview_export_variablesreturns them indeletionPlan.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
variantMigrationblock. 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
anchorNodeIdover 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.stylesandrefStylesno longer rebuilds variants: when the only JSON change is the styles of a referenced instance's root —ref.stylesinstructure,refStylesin styles, orstylesinside a variantref— 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 hasref.slotsorscale, 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
propsgains 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_policyandprotect_file. Bridge 1.11 keeps the plugin connected in several tabs at once and sends each command to the chosen file: every plugin tool acceptstargetFileKey, 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
fontWeighttoken is used with is looked up in every enabled collection. Before, exporting one collection wrote, for example,Semi Bold, a full export wroteSemibold, 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, actionsurl,set-variable,set-variable-modeand several actions per reaction. An unknown word intransitionsstops Apply with an error instead of silently becomingon-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.exposeexposes a nested instance on the parent component; the drift audit warns about native slot limit violations.- Renaming an axis value keeps instances:
tone: b → betaat 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.*.slotswith 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
refblock in a$prop=valuesection is an overlay on the structuralref:componentneed not be repeated,propertiesmerge by key,nested,slotsandoverridesby entry. A block withoutcomponentand a variantref.nestedwere silently not applied before. - Style properties without effect are visible: a key that does nothing for that kind of layer (for example
fillon 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.paththrough 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
sourcein 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_compositionsgenerates 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-idhand-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,Qare 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,frand others) and notations like12abcor1,234,567are 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 oflighten,darken,mixinlchandoklchare brought into sRGB by reducing chroma while keeping lightness and hue (CSS Color 4) instead of clipping channels.lightenby 100 % gives exact white,darkenby 100 % gives exact black in every space. - Colour function names in any case:
RGB(…),OKLCH(…)are accepted; theoklch()lightness may be a percentage, for exampleoklch(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;eminlineHeightandletterSpacingis 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,dispersionand the noiseopacity,densitykeeps its fraction:0.48stays0.48instead of turning into the maximum. - Bridge 1.11:
preview_export_variablesreturns the same deletion list without writing, and anexport_variablescall that needs to delete something requiresconfirmDestructive: true; without it nothing changes. - rem base in the export settings: the base size for
rem,emand percentages is set in the export window as a number or a token reference; the field left Collection Settings, the value is still stored inconfig.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. variantMigrationno 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_idagent 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
compositionssection 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
variantMigrationmap. -
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 (includingrepeat(7, 1fr)), gaps, automatic positioning (gridAutoFlow,gridAutoRows), explicit placement of instances into cells (gridRow,gridColumn, spans, alignment); wrapping withwrapGap: "auto"andspace-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 anaspect-lock-settledwarning; a failing root style no longer leaves a variant empty. Fixed the reset of explicitly enabledconstrainProportionson 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
scalefor explicitly declaredINSTANCEandICONlayers, 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
opacitygets 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 leavesNORMALand 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.nestedblock switches the instance's VARIANT property (for examplesize: 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.slotswithop: "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:
fontSizeretains 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(withdetailsandfixes) andsuggestedAction; newauto_fix_compositionandreload_local_workspacecommands;get_plugin_statusreports 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: arefblock inside a$prop=valuestyle section changes only the properties it names on the nested instance;{token}bindings from the structureref(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.propertieswith 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
componentPropertieswhile keeping the samelayerpreserves 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
keyandlibraryreferences 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,oklchandcolor(...)values can retain an opacity-token reference without requiringfigma.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>.componentswaps 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 resetsvariant=secondary. The drift audit compares the composition hash with the last Generate/Apply, honours per-variantinstancePropertiesoverrides, does not count hand-made prototype reactions as drift and understandscomponent: false;component: falseroots are tracked in diff-id. The Bridgeget_drift_statuscommand 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/layerBlurfrom 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;blendModecan be set on a layer; enum values coming from tokens (textCase,textDecoration) are translated to Figma terms; Apply works forcomponent: 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; arraypaddingmaps to sides like CSS;lineHeightandletterSpacingfrom 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 sizesfr/ px /autoare 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 throughfrom/toin 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 500in the shorthand,matchLayerson 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
fillmade of one colour reference and ablur/backdrop-blurmade of a number reference bind the variable;STRETCH,MIN,MAXandCENTERgrids pass Figma's validation; anoiselayer is written withoutblendMode. -
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 fordurationare evaluated in milliseconds. -
Colour with opacity exports as a composed Figma cell: a colour token with an
alphamodifier 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:
videoandpatternlayers, 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:
durationtokens export as Timing,cubicBezierand the neweasingtype 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
alphamodifier 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
statuscommand 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,logand 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
fontWeightallows onlyFONT_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.*.jsonto.prettierignore.