Tokens

Scopes & Code Syntax

How to configure variable scopes and code syntax (CSS, Swift, Kotlin) through $extensions in SXL Studio tokens.

Why Scopes and Code Syntax matter

When tokens are exported to Figma as Variables, they are available for binding to any property by default — fill color, stroke, dimension, gap, font. In practice this is inconvenient: a designer looking for a color also sees spacing tokens and font sizes in the picker. Search becomes chaotic.

Scopes solve this by limiting where a variable appears in the Figma UI:

  • Variable color/primary → visible only when picking fills, strokes, and effect colors
  • Variable spacing/md → visible only when adjusting gap
  • Variable borderRadius/lg → visible only in the corner radius field

Code Syntax solves a different problem — binding to code. When a developer opens a design in Dev Mode, they see ready-to-use syntax for their platform instead of an abstract variable name:

  • Web: var(--color-primary) or $color-primary
  • iOS: Color.primary
  • Android: @color/primary

Both mechanisms are configured through the $extensions field in a token's JSON file.

Scopes limit variable visibility in Figma; Code Syntax shows code in Dev Mode

How it works in JSON

Both settings live inside the token's $extensions block:

JSON
{
  "color": {
    "primary": {
      "$type": "color",
      "$value": "#0066FF",
      "$extensions": {
        "figma.scopes": ["ALL_FILLS", "STROKE_COLOR"],
        "figma.codeSyntax": {
          "Web": "var(--color-primary)",
          "Android": "ColorPrimary",
          "iOS": "Color.primary"
        }
      }
    }
  }
}

Important: keys in $extensions are flat strings: "figma.scopes", "figma.codeSyntax", "figma.hide", "figma.modify". This is not a nested figma: { scopes: ... } object.


Scopes — variable visibility

Figma variable types

Figma supports 4 variable types. Each type has its own set of valid scopes:

Figma typeSXL Studio token typesDescription
COLORcolorColors
FLOATdimension, sizing, spacing, borderRadius, borderWidth, opacity, number, fontSize, lineHeight, letterSpacing, paragraphSpacing, paragraphIndent, durationNumeric values
STRINGfontFamily, fontWeight, fontStyle, text, cubicBezier, strokeStyle, textCase, textDecorationString values
BOOLEANbooleanBoolean values

Valid Scopes by type

COLOR

ScopeWhere the variable is visible
ALL_SCOPESEverywhere colors can be applied
ALL_FILLSAll fill types (frame, shape, text)
FRAME_FILLFrame fills only
SHAPE_FILLShape fills only
TEXT_FILLText color only
STROKE_COLORStroke color
EFFECT_COLOREffect colors (shadows, glow)

FLOAT

ScopeWhere the variable is visible
ALL_SCOPESEverywhere numbers can be applied
TEXT_CONTENTText content
CORNER_RADIUSCorner radius
WIDTH_HEIGHTWidth and height
GAPGap between items
STROKE_FLOATStroke width
EFFECT_FLOATNumeric effect parameters
OPACITYOpacity
FONT_SIZEFont size
LINE_HEIGHTLine height
LETTER_SPACINGLetter spacing
PARAGRAPH_SPACINGParagraph spacing
PARAGRAPH_INDENTFirst-line indent
FONT_WEIGHTFont weight (numeric)

STRING

ScopeWhere the variable is visible
ALL_SCOPESEverywhere strings can be applied
TEXT_CONTENTText content
FONT_FAMILYFont family
FONT_STYLEFont style (italic, bold, etc.)
FONT_VARIATIONSFont variations (variable fonts)

BOOLEAN

ScopeWhere the variable is visible
ALL_SCOPESEverywhere (the only available scope)

Default Scopes per token type

When you do not specify figma.scopes explicitly, SXL Studio uses recommended values as a reference in the editor UI. Here is the full mapping:

Token typeDefault Scopes
colorALL_FILLS, STROKE_COLOR, EFFECT_COLOR
dimensionALL_SCOPES
sizingWIDTH_HEIGHT
spacingGAP
borderRadiusCORNER_RADIUS
borderWidthSTROKE_FLOAT
opacityOPACITY
numberALL_SCOPES
fontFamilyFONT_FAMILY
fontWeightFONT_STYLE
fontStyleFONT_STYLE
fontSizeFONT_SIZE
lineHeightLINE_HEIGHT
letterSpacingLETTER_SPACING
paragraphSpacingPARAGRAPH_SPACING
paragraphIndentPARAGRAPH_INDENT
textALL_SCOPES
booleanALL_SCOPES
durationALL_SCOPES
cubicBezierALL_SCOPES
strokeStyleALL_SCOPES
textCaseALL_SCOPES
textDecorationALL_SCOPES

Note: this table is a reference for the plugin's editor UI. During export, if figma.scopes is not specified in JSON, the plugin does not write scopes to the variable — Figma's default behavior is used.

Invalid scope filtering

If you specify a scope that doesn't match the variable type (e.g., CORNER_RADIUS for a color), the plugin silently discards it. Only valid scopes from your list are applied.

JSON
{
  "brand-color": {
    "$type": "color",
    "$value": "#FF5500",
    "$extensions": {
      "figma.scopes": ["ALL_FILLS", "CORNER_RADIUS", "OPACITY"]
    }
  }
}

Result: only ALL_FILLS is applied (the others are invalid for COLOR).


Code Syntax — code bindings

Code Syntax defines how a variable appears in Figma's Dev Mode for developers on different platforms.

Format

JSON
{
  "$extensions": {
    "figma.codeSyntax": {
      "Web": "var(--color-primary)",
      "Android": "ColorPrimary",
      "iOS": "Color.primary"
    }
  }
}
KeyPlatformExample values
WebCSS / SCSS / Lessvar(--color-primary), $color-primary, @color-primary
AndroidKotlin / AndroidColorPrimary, @color/primary, R.color.primary
iOSSwift / SwiftUIColor.primary, .primary, UIColor.primary

All three keys are optional. Specify only the platforms relevant to your team.

Auto-generation templates

Instead of writing a name manually for every token, you can use templates. The plugin automatically generates the value from the token path:

TemplateResult for color.brand.primary
{var(--css-variable)}var(--color-brand-primary)
{$sass-variable}$color-brand-primary
{@less-variable}@color-brand-primary
{UpperCamelCase}ColorBrandPrimary
{lowerCamelCase}colorBrandPrimary
{UPPER_SNAKE_CASE}COLOR_BRAND_PRIMARY
{lower_snake_case}color_brand_primary

Template usage example:

JSON
{
  "color": {
    "primary": {
      "$type": "color",
      "$value": "#0066FF",
      "$extensions": {
        "figma.codeSyntax": {
          "Web": "{var(--css-variable)}",
          "Android": "{UpperCamelCase}",
          "iOS": "{lowerCamelCase}"
        }
      }
    }
  }
}

Result after export for token color.primary:

  • Webvar(--color-primary)
  • AndroidColorPrimary
  • iOScolorPrimary

How path conversion works: separators /, ., _ are replaced with -, then the path is split into words. Each template formats the words in the appropriate style.

Code Syntax is shown in Dev Mode when an element is selected

Group-level inheritance

The most convenient approach is to set $extensions at the group level, so all tokens inside inherit the settings:

JSON
{
  "color": {
    "$extensions": {
      "figma.scopes": ["ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}",
        "Android": "{UpperCamelCase}",
        "iOS": "{lowerCamelCase}"
      }
    },
    "primary": {
      "$type": "color",
      "$value": "#0066FF"
    },
    "secondary": {
      "$type": "color",
      "$value": "#6633CC"
    },
    "danger": {
      "$type": "color",
      "$value": "#FF3B30"
    }
  }
}

In this example all three tokens (primary, secondary, danger) will receive:

  • Scopes: ALL_FILLS, STROKE_COLOR, EFFECT_COLOR
  • Code Syntax via templates

Per-token override

If a specific token needs different settings, specify $extensions directly on it. Child settings completely replace the parent (no merging):

JSON
{
  "color": {
    "$extensions": {
      "figma.scopes": ["ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}",
        "Android": "{UpperCamelCase}",
        "iOS": "{lowerCamelCase}"
      }
    },
    "primary": {
      "$type": "color",
      "$value": "#0066FF"
    },
    "text-only": {
      "$type": "color",
      "$value": "#333333",
      "$extensions": {
        "figma.scopes": ["TEXT_FILL"],
        "figma.codeSyntax": {
          "Web": "var(--text-body)"
        }
      }
    }
  }
}

Token color.text-only:

  • Scopes → only TEXT_FILL (not ALL_FILLS + STROKE_COLOR + EFFECT_COLOR)
  • Code Syntax → only Web: "var(--text-body)" (Android and iOS will not be set because the child object replaces the parent entirely)

Inheritance rule: $extensions on a token completely overrides the group's $extensions. Shallow merge: figma.scopes is replaced as a whole, figma.codeSyntax is replaced as a whole. If you need to keep some parent settings, duplicate them in the child's $extensions.

Inheriting scopes from a group and overriding at the token level

Additional extensions

figma.hide

Hides a variable from publishing. The variable is created in Figma but is not visible in other files when using the library.

JSON
{
  "internal": {
    "base-unit": {
      "$type": "number",
      "$value": 4,
      "$extensions": {
        "figma.hide": true
      }
    }
  }
}

Useful for internal tokens that serve only as a base for calculations or aliases — end users of the library should not see them.

figma.modify

Color modifiers — a chain of transformations for color tokens:

JSON
{
  "color": {
    "primary-light": {
      "$type": "color",
      "$value": "{color.primary}",
      "$extensions": {
        "figma.modify": [
          { "type": "lighten", "value": 0.2, "space": "oklch" },
          { "type": "alpha", "value": 0.8, "space": "srgb" }
        ]
      }
    }
  }
}

Available modifiers: lighten, darken, alpha, mix, and others. Modifications are applied in sequence (first to the base color, then to the result).


When Scopes and Code Syntax are applied

Settings are applied during variable export to Figma, but only if the Apply Code Syntax & Scopes flag is enabled in the export dialog (enabled by default).

What happensWhen
Scopes are written to the variableOn creation and update, if figma.scopes is specified
Code Syntax is written to the variableOn creation and update, if figma.codeSyntax is specified
figma.hide is writtenOn creation and update
Changes are tracked in diffAlways (scopes, codeSyntax, hide are included in the diff-id hash)

More about export in Export Variables & Styles.


Full example: design system

JSON
{
  "color": {
    "$extensions": {
      "figma.scopes": ["ALL_FILLS", "STROKE_COLOR", "EFFECT_COLOR"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}",
        "Android": "{UpperCamelCase}",
        "iOS": "{lowerCamelCase}"
      }
    },
    "brand": {
      "primary": {
        "$type": "color",
        "$value": "#0066FF",
        "$description": "Primary brand color"
      },
      "secondary": {
        "$type": "color",
        "$value": "#6633CC"
      }
    },
    "text": {
      "$extensions": {
        "figma.scopes": ["TEXT_FILL"]
      },
      "body": {
        "$type": "color",
        "$value": "#333333"
      },
      "muted": {
        "$type": "color",
        "$value": "#999999"
      }
    }
  },
  "spacing": {
    "$extensions": {
      "figma.scopes": ["GAP"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}",
        "Android": "{lowerCamelCase}",
        "iOS": "{lowerCamelCase}"
      }
    },
    "xs": { "$type": "spacing", "$value": "4px" },
    "sm": { "$type": "spacing", "$value": "8px" },
    "md": { "$type": "spacing", "$value": "16px" },
    "lg": { "$type": "spacing", "$value": "24px" },
    "xl": { "$type": "spacing", "$value": "32px" }
  },
  "borderRadius": {
    "$extensions": {
      "figma.scopes": ["CORNER_RADIUS"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}"
      }
    },
    "sm": { "$type": "borderRadius", "$value": "4px" },
    "md": { "$type": "borderRadius", "$value": "8px" },
    "lg": { "$type": "borderRadius", "$value": "16px" },
    "full": { "$type": "borderRadius", "$value": "9999px" }
  },
  "fontSize": {
    "$extensions": {
      "figma.scopes": ["FONT_SIZE"],
      "figma.codeSyntax": {
        "Web": "{var(--css-variable)}"
      }
    },
    "sm": { "$type": "fontSize", "$value": "12px" },
    "base": { "$type": "fontSize", "$value": "14px" },
    "lg": { "$type": "fontSize", "$value": "18px" },
    "xl": { "$type": "fontSize", "$value": "24px" }
  }
}

After export:

  • Colors color.brand.* are visible in fills, strokes, and effects
  • Colors color.text.* are visible only in text fills
  • Spacing spacing.* is visible only in the gap field
  • Border radii borderRadius.* are visible only in corner radius
  • Font sizes fontSize.* are visible only in font-size
  • All variables display correct code syntax in Dev Mode
Configuring scopes for an entire design system

Tips

  1. Start with groups — set $extensions at the color, spacing, borderRadius level. This covers 90% of cases.
  2. Use templates{var(--css-variable)} for CSS, {UpperCamelCase} for Android, {lowerCamelCase} for iOS. Don't write names manually.
  3. Hide internal tokens — use figma.hide: true for base values that library consumers should not see.
  4. Don't overuse scopes — avoid ALL_SCOPES everywhere. Specific scopes help designers find the right variable faster.
  5. Check compatibility — a scope must match the variable type. Invalid scopes are silently discarded.