Skip to content

Figma Integration

There are plenty of options to get DTCG design tokens out of Figma.

Import Figma Variables

Cobalt supports importing Figma variables directly:

Figma TypeDTCG TypeNotes
colorcolorCoverts to sRGB Hex by default.
numberdimensionUses px by default.
stringIgnored if no type specified.
booleanIgnored if no type specified.

Note: typography variables have been announced, but aren’t released yet. Cobalt will add support when they arrive.

Setup

Note

Using the Figma Variables API requires an Enterprise plan in Figma.

In your tokens.config.js file, add the Figma share URL as a token source:

ts
/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: ["https://www.figma.com/file/OkPWSU0cusQTumCNno7dm8/Design-System?…"],
};

Next, you’ll need to create a Figma Access Token with the file:read and file_variables:read scopes and expose it as FIGMA_ACCESS_TOKEN in your .zshrc or .bashrc file (or in CI you can add this to GitHub Actions Secrets)

sh
export FIGMA_API_TOKEN=abc123…

Then run co build as you would normally, and Cobalt will operate as if the Variables pulled from Figma existed in a local tokens.json file.

Overrides

Figma Variables can be a Color, Number, String, or Boolean. Color translates directly to the DTCG Color type, so those will work automatically. But for everything else, you’ll need to set up overrides to specify what token type each Figma Variable should be. To do so, specify selectors in a mapping in figma.overrides where the key is a glob pattern (or specific ID), and the value is an object with your desired DTCG type:

ts
/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: ["https://www.figma.com/file/OkPWSU0cusQTumCNno7dm8/Design-System?…"],
  figma: {
    overrides: {
      "size/*": { $type: "dimension" },
      "timing/*": { $type: "duration" },
    },
  },
};

TIP

If both a glob pattern and specific ID are provided, the specific ID takes priority.

Advanced Overrides

figma.overrides also accepts 2 callback utilities to provide futher control over transforming Variables:

rename()

By default, tokens will keep the same name as your Figma Variables, but with / converted into ., e.g. color/base/blue/500color.base.blue.500. But to rename certain tokens, you can provide a transformID() utility:

ts
/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: ["https://www.figma.com/file/OkPWSU0cusQTumCNno7dm8/Design-System?…"],
  figma: {
    overrides: {
      "color/*": {
        // rename color/base/purple → color/base/violet
        rename(id) {
          return id.replace("color/base/purple", "color/base/violet");
        },
      },
    },
  },
};

You can choose to keep the /s from Figma, or convert to . separators like DTCG requires; up to you. They both work the same way.

TIP

If you return undefined or an empty string, it’ll keep its original name.

transform()

This is useful when either $type isn’t enough, or you want to provide additional conversions. Here, for example, is how you’d take px-based number Variables and convert to rems:

ts
/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: ["https://www.figma.com/file/OkPWSU0cusQTumCNno7dm8/Design-System?…"],
  figma: {
    overrides: {
      "size/*": {
        $type: "dimension",
        // convert px → rem
        transform({ variable, collection, mode }) {
          const rawValue = variable.valuesByMode[mode.modeId];
          if (typeof rawValue === "number") {
            return `${rawValue / 16}rem`;
          }
          // remember rawValue may be an alias of another Variable!
          // in that case, `typeof rawValue === "object" && rawValue.type === "VARIABLE_ALIAS"`
        },
      },
    },
  },
};

INFO

transform() will only run a maximum of 1× per variable (you can’t do multiple runs with multiple matching globs).

TIP

You can even create aliases on-the-fly by either returning a DTCG alias string "{color.base.blue}", or a Figma Variable alias type ({ type: "VARIABLE_ALIAS", id: "xxxxxxx…" }).

Tokens Studio

If using Tokens Studio, you can export JSON using any of the approved sync methods. Once exported to a tokens.json file, Cobalt can translate the format to DTCG:

js
import pluginCSS from "@cobalt-ui/plugin-css";

/** @type {import("@cobalt-ui/core").Config} */
export default {
  tokens: "./tokens.json",
  outDir: "./tokens/",
  plugins: [pluginCSS()],
};

Once your sync method is set up, it should be a snap to re-export that tokens.json file every time something updates.

Support

Tokens Studio TypeSupportedNotes
SizingConverted to Dimension.
SpacingConverted to Dimension.
ColorFlat colors are kept as Color while gradients are converted to Gradient. Modifiers aren’t supported.
Border radiusConverted to Dimension. Multiple values are expanded into 4 tokens (*TopLeft, *TopRight, *BottomLeft, *BottomRight).
Border widthConverted to Dimension.
ShadowBasically equivalent to Shadow.
OpacityConverted to Number
TypographyBasically equivalent to Typography. Text decoration and Text Case must be flattened as there is no DTCG spec equivalent.
AssetTODO. Cobalt supports Link, which should be an equivalent.
CompositionUnsupported because this is a paid feature.
DimensionDirect equivalent to Dimension.
BorderDirect equivalent to Border.

Notes

  • Duration and Cubic Bézier types aren’t supported by Tokens Studio (because Figma currently doesn’t support animations). So to use those types you’ll need to convert your tokens into DTCG.
  • Though Cobalt preserves your Token Sets, which means most aliases will work, Token Studio’s Advanced Themes is a paid feature and is therefore not supported. Though you could manually upconvert Token Studio themes to modes.

TokensBrücke Figma Plugin

TokensBrücke

The TokensBrücke plugin for Figma exports Figma Variables to DTCG JSON, and is fully-compatible with Cobalt.