Support resolving type of the token being referenced

Hi there :waving_hand:

I’ve checked this Community space content and the GitHub issues, but I haven’t found anything about this topic. I hope this is not a duplicate :folded_hands:

Context

I’m currently exporting our Design System’s tokens defined with the Design Tokens Format (aka DTCG) to Penpot (JSON files) in order to use them for a library of components.

The way we defined the types of our tokens is based on this part of the “Type” specifications:

If the token’s value is a reference, then its type is the resolved type of the token being referenced.

With a reproducible example, we can consider this simple use case:

{
  "spacing": {
    "xs": {
      "$type": "dimension",
      "$value": "8px"
    }
  },
  "icon": {
    "xsmall": {
      "size": {
        "$value": "{spacing.xs}"
      }
    }
  }
}

The type of icon.xsmall is not explicitly defined, because the specs say that this type can be inferred by following the reference to find the “dimension” type of this token.

When uploaded to Penpot (version 2.13), only the spacing.xs token is imported, the other one is ignored; possibly because it doesn’t have any explicit type defined.

When the type is explicitly defined (duplicated) for icon.xsmall:

{
  "spacing": {
    "xs": {
      "$type": "dimension",
      "$value": "8px"
    }
  },
  "icon": {
    "xsmall": {
      "size": {
        "$type": "dimension",
        "$value": "{spacing.xs}"
      }
    }
  }
}

then, it works in Penpot.

More precise context

The previous section showed a simple reproducible example, but in reality our source of truth (DTCG tokens) defines spacing.xs with the “dimension” type. In our pipeline, however, the transformers that generate the Penpot files specialize that type into the “spacing” type, more precise, and recognized by Penpot.

So, to make the referenced token work in Penpot we therefore have to assign that specialized “spacing” type to the reference as well, which is more complex: we must infer not the original DTCG type (“dimension”) but the transformed, specialized type (“spacing”) produced by our transformer.

Hope I’ve succeeded to make it understandable :laughing:

Expected

As a summary, it would be a nice improvement if Penpot would be able to handle all the extra-rules defined in the specs:

If the $type property is not set on a token, then the token’s type MUST be determined as follows:

  • If the token’s value is a reference, then its type is the resolved type of the token being referenced.
  • Otherwise, if any of the token’s parent groups have a $type property, then the token’s type is inherited from the closest parent group with a $type property.
  • Otherwise, if none of the parent groups have a $type property, the token’s type cannot be determined and the token MUST be considered invalid.

[…]

The $type property can be set on different levels:

  • at the group level
  • at the token level

On our side, two advantages:

  • It would remove some extra-code to handle this use case
  • The JSON files would also be lighter to process without these kind of duplicates definition of types.