$extensions support from DTCG Tokens

Hello everyone,

I started working on migrating my SCSS variables to DTCG tokens for agnosticity purposes. I embraced the DTCG tokens format because it will be the tomorrow standard, and its approach is cross-environmental.

I was amazed by the $extensions properties that support color modes, alternative naming, and more.

This seems not to be working after importing them.

Take this small example:

{
  "penpot": {
    "color": {
      "accent": {
        "default": {
          "$type": "color",
          "$value": "#eef0f2",
          "$extensions": {
            "mode": {
              "penpot-light": "#eef0f2",
              "penpot-dark": "#2e3434"
            }
          }
        },
        "primary": {
          "$type": "color",
          "$value": "#6911d4",
          "$extensions": {
            "mode": {
              "penpot-light": "#6911d4",
              "penpot-dark": "#7efff5"
            }
          },
          "muted": {
            "$type": "color",
            "$value": "#e1d2f5",
            "$extensions": {
              "mode": {
                "penpot-light": "#e1d2f5",
                "penpot-dark": "#426158"
              }
            }
          }
        },
        "secondary": {
          "$type": "color",
          "$value": "#1345aa",
          "$extensions": {
            "mode": {
              "penpot-light": "#1345aa",
              "penpot-dark": "#bb97d8"
            }
          }
        },
        "tertiary": {
          "$type": "color",
          "$value": "#8c33eb",
          "$extensions": {
            "mode": {
              "penpot-light": "#8c33eb",
              "penpot-dark": "#00d1b8"
            }
          }
        },
        ...
      }
    }
  }
}

This results on Penpot:

The results are similar on Tokens Studio as they participated in bringing the native tokens to life on Penpot :laughing:

The default value is considered, but not those in $extensions.

This approach is quite cutting-edge, but it’s particularly interesting to maintain better control over the token architecture, as every token can be populated with an alternative value that can be interpreted by consuming systems. I took it from Terrazzo, which is an open-source tool that transforms DTCG tokens into styles, created by DTCG members: Modes + Theming ⛋ Terrazzo

How can the $extensions values be managed? Would it create other sets that can be attached to a theme?

For now, I envision using the future API REST (or plugin API) to sync tokens with a Node script, so I’m eager to get started!

Bye!

2 Likes

Hey, @a-ng-d, thanks for the question! DTCG Extensions is a great addition to design tokens. It adds an extra layer of customization, flexibility and logic that’s super valuable!

Our plan is to handle extensions as specified in the standard. That means:

  • We will preserve any extensions data when importing, exporting, or syncing tokens

  • We won’t interpret or apply the content of those extensions ourselves, since they’re meant for custom, tool specific metadata. That kind of customization should happen outside Penpot, in custom pipelines that fit each system’s needs. According to the DTCG specification, extension data should be used only for optional metadata that isn’t essential to interpreting a token’s value

  • This way, any metadata added by other tools (like Tokens Studio, Style Dictionary, or systems like Terrazzo) stays compatible and travels safely through Penpot

As the DTCG spec evolves and common extension appear, we’ll revisit this and see how deeper support could look like in the future.

The example you shared, however, seems to be an adaptation of figma variables and its modes. This is already handled in Penpot and other tools through sets/themes. As I see it, there should be a script that transforms those extensions into a standard sets or theme structure.

An jsut so you know, we’re working on some utilities that will let you sync figma variables or design tokens created with external tools, as long as you can convert those tokens into the standard DTCG format.

I hope that helps!

2 Likes

Hi @natacha!

Thank you for your clear explanation.

As you said, the specs are evolving and Kaelig Deloumeau-Prigent has announced the v1 of DTCG tokens format :raising_hands:
May we get a standard in making themes and modes.

Concerning the tokens I’ve used as examples, they are drawn from the Terrazzo approach to handling modes, which is led by Drew Powers, a member of the DTCG. Since the standard is still in flux, each tool tends to operate in a specific manner to manage the modes. Tokens Studio and Penpot achieve this by associating sets with a theme, while Terrazzo manages them using the $extensions properties to maintain a single file instead of managing multiple files.

Such a good news to sync the tokens from a single source of truth! Can’t wait for this!

:waving_hand: Hi! Creator/maintainer of Terrazzo here. Yes $extensions.mode were a custom extension that were a stopgap for DTCG v1 to land. Terrazzo is currently working on a major release which will support resolvers and all the new features of DTCG v1.

Is there a way I could help support export from PenPot to Terrazzo, or vice-versa? This should all be standard DTCG format (i.e. all the “Terrazzo-unique” quirks should go away with DTCG v1), but I think there may be a missing piece here with PenPot supporting resolvers, maybe. Anyway, happy to help anyway I can!

3 Likes

Glad to see you there @drwpow, such a surprise as you have posted your first response on this topic!

I recently figured out that $extensions.mode is a custom track for handling modes, whereas the resolvers were still in progress.

As Penpot shares with Tokens Studio the support for theme metadata, I wonder if the resolvers would replace it in the near future. However, I think both have the same purpose: to manage themes and modes.

For a personal note, I prefer the old Terrazzo way of structuring themes and modes, because you can avoid multiplying sets of tokens to handle multi-modes and multi-brands :slight_smile:

1 Like