-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Discussion]: How to transform composite tokens #226
Comments
I've thought about it in relation to the work I'm doing with Token Operations. From my perspective we could have a setup like the following: {
"shadow1": {
"_color": {
"$value": "#00000088"
},
"_offset-x": {
"$value": "0.5rem"
},
...
"css": {
"$operations": [...] // concat all parts together into single CSS value
},
"android": {
"$operations": [...] // concat all parts together into single android appropriate value
}
}
} So a final resolution for CSS would be available at |
I've been digging into these different options for managing composite design tokens, and here are my two cents. Option 1, which decomposes each token into individual variables, offers granular control. This allows for fine-tuned customization but could lead to management complexities, especially when it comes to ensuring the proper combination of these decomposed tokens. Option 2 encapsulates all attributes into a single object and provides a cohesive approach. It makes it clear which attributes are meant to be used together but may not offer the same level of granularity that might be required in some scenarios. However, the 3rd approach suggested by @ddamato provides a balanced solution. It still allows for granular customization via sub-properties while providing a consolidated output tailored for specific platforms like CSS or Android through token operations. This modular approach not only streamlines the application of design tokens but also enables more efficient cross-platform compatibility. Given the flexibility and scalability inherent in the third approach, it is a compelling solution for managing composite design tokens effectively. |
Does the spec need to have an explicit view on this at all? In my mind composite tokens are a bit like "styles" in Figma (or equivalents in other design tools). They're a structured set of values that, in design tools, are usually selected and applied as a single unit. I think they still make sense as "design tokens" though, as they're still named design decisions and likely to be part of a design system team's vocabulary. When it comes to translating them to code, there are several ways they might be represented. On some technology platforms, there might be an analogous "group" construct that lets you apply them all at once, in others there may not. And sometimes both ways might be possible. The 2 options in the OP demonstrate this exactly. I'd argue which one you choose (why not both?) is up to your team. The same can be true in other programming languages. For example, the shadow token from the OP in CSS could be expressed as a single CSS var: :root {
--shadow-token: 0.5rem 0.5rem 1.5rem 0rem #00000088;
}
/* application */
.foobar {
box-shadow: var(--shadow-token);
} But it could just as well be "exploded" into its individual sub-values: :root {
--shadow-token-offset-x: 0.5rem;
--shadow-token-offset-y: 0.5rem;
--shadow-token-blur: 1.5rem;
--shadow-token-spread: 0rem;
--shadow-token-color: #00000088;
}
/* application */
.foobar {
box-shadow:
var(--shadow-token-offset-x)
var(--shadow-token-offset-y)
var(--shadow-token-blur)
var(--shadow-token-spread)
var(--shadow-token-color);
} Neither is right or wrong. It just comes down to individual teams' preferences and requirements. While I'll admit that exploding the parts of the shadow token is something folks are unlikely to do as shadow values in CSS always seem to be applied as a unit, the same isn't necessarily true for something like a border which might be applied all at once as a shorthand value or individually using the long hand properties: .shorthand {
border: var(--border-token);
}
.longhand {
border-color: var(--border-token-color);
border-width: var(--border-token-width);
border-style: var(--border-token-style);
} Or indeed a typography token which, at least in CSS, would have to be exploded into individual values because there's no shorthand property that covers them all: :root {
--typography-token-font-size: 1rem;
--typography-token-font-family: Comic Sans MS;
--typography-token-font-weight: bold;
--typography-token-line-height: 1.4;
--typography-token-line-height: 1.4;
}
.heading {
font-size: var(--typography-token-font-size);
font-family: var(--typography-token-font-family);
/* and so on */
} For that particular type, you could event export the whole token as a CSS class (or a Sass mixin): .typography-token {
font-size: 1rem;
font-family: Comic Sans MS;
/* and so on */
} I suppose a DS team might even export grouped and exploded versions to give downstream product teams the freedom to choose which one(s) they want to use. My point is, there are potentially many, valid ways to express the DTCG composite types in different programming languages. I don't believe the spec should mandate a particular way. I'd therefore argue it's fine to let that be a choice or a configuration option for tools. |
nit:
There is, the
My concern for the spec would be that any point some new property that requires composite tokens to appear, would require the definition of that composite to exist and then distributed across tools in varying amounts of support. It is fairly clear the reason why shadow has been given a special composite status is because it is not a shorthand in CSS, making many of the values required and therefore standardized. In the font example, while none of those values are required, I would say it is common for them to be used together. As an example defining a typographic style commonly expects a family and size together at least. In fact, the I'd also be concerned about misunderstanding of use, where the shadow token is applied to the CSS |
I have a very strong preference for keeping all of the values of a composite token together. This is faithful to the nature of a design token as being a design decision; there are some places where you have to make multiple decisions to get to the lowest level of fidelity, eg shadows or type. You can't just decide what a shadow's color is, you also have to decide what it's blur radius, x, and y offset are. Likewise you can't just decide what at piece of text's font family is, you also have to decide it's size, etc. However, like @c1rrus said, I think that the decision as to how to transform the token is up to the transformer, and the spec shouldn't take a stance. As for @ddamato's follow-up, I put some thoughts in #100 on the issue of platforms having multiple incompatible syntaxes for the same type of token (tl;dr, I think that's another translator concern that the spec shouldn't weigh in on). |
Description
The latest editor's draft (as of August 2023) states that composite design token is "a design token whose value is made up of multiple, named child values."
Given the following example in the editor's draft, is there currently a recommendation on how to transform the token?
It seems like there are two options here:
value
property name is appended to the top-level token name to create a new token, and all of those tokens must be appliedvalue
refers to all sub-values that must be appliedIf we take a look at those two possibilities in action, here's what they might look like if we transformed them into JavaScript variables:
Tradeoffs
Option 1
Pros:
SHADOW_TOKEN_COLOR
, but don't applySHADOW_TOKEN_OFFSET_X
).Cons:
SHADOW_TOKEN
). This would require token users to be extra careful in order to ensure that all generated tokens coming from the one composite token are applied.Option 2
Pros:
Cons:
The text was updated successfully, but these errors were encountered: