community-group
community-group copied to clipboard
Clarification needed for custom properties in tokens
In the specs document some additional properties are mentioned. However it is not state if custom properties are allowed or not.
From our perspective it would be very beneficial if custom properties would be allowed.
For example we have a lot of case were we reference a base color {color.base.red}
but need to add transparency to it. For this we use a custom alpha
property. The resulting token looks like this:
{
"textHighlightError": {
"$value": "{color.base.red}",
"$type": "color",
"alpha": 0.5
}
}
I know that alpha and other transformations are mentioned in issue #137 and others. But even if this gets added to the specs I feel there may always be needs for custom cases.
Having a clear way to implement those would be very helpful.
Either by allowing properties without $
or by defining an additional prefix for custom properties. Or simply by stating that tools may ignore any non-standard properties but per spec they may be added.
Hi Lukas—is it possible you missed the section about the $extensions
node? That's where we're planning on adding all of the properties that we need that aren't covered by the spec, including for cases like that specific one.
In a case like your example, my current thinking is that we would probably do something like this:
{
"textHighlightError": {
"$value": "#ff000080",
"$type": "color",
"$extensions": {
"proprietarystuff.calculatedtoken": {
"base": "{color.base.red}",
"opacity": 0.5
}
}
}
}
Then spec-compliant tools would at least still know that it's red at 50% opacity, but tools that understand proprietarystuff.calculatedtoken
know how to recalculate the color if anything changes.
Hey, I did see this, but this is horribly cumbersome for hand-defined tokens.
This makes a lot of sense for tools an I am using it for my figma plugin. But if I hand-build tokens and I want to have the $value be a reference not an already calculated output.
If this is the only recommended way that makes sense.
But would a token like the one I suggested be invalid? In css unknown properties are simply ignored. Would that be the case for tokens as well?
This would allow people to use custom props but tools would just ignore it, which would be fine.
One could argue that could be allowed now since all of the spec's properties now begin with a $
. Right now, when parsing a token file from the root, we know that any node that has a (direct child) property called $value
is a token, and otherwise it's a group. To support extension properties without putting them in a specific $extensions
node, parsers would need to make the group parsing a little more complex: they wouldn't know if any given child is a group or an extension property until searching that entire subtree for a property on any descendant with a name starting with $
.
In addition to being annoying for parsers, I think that kind of openness would also limit what JSON Schema-based tooling could do with the files. But it does seem like something that could be allowed now that the spec properties all start with $
.
Using a different prefix to denote "this is neither a token nor a group nor a property defined in the spec," like say ~
, would have roughly the same benefits with a lot less complexity.
While the spec wording is not currently clear (and we ought to update it so that it is), I've always taken the view that if it's not explicitly included in the spec, then it is not allowed. My assumption has therefore been that custom properties are not allowed.
As @TravisSpomer pointed out, this is exactly the kind of thing $extensions
is intended for (Btw, while the current draft only allows them on tokens, we intend to update the spec to allow them on groups too, as proposed in #106).
While I accept that the $extensions
syntax is more clunky than adding custom properties, I'd argue there are a few benefits to that:
- Extensions are explicitly namespaced, so there's less risk of clashes. If we allowed custom properties and tools A & B each added a
~foobar
custom property but used it for different things, that might cause issues for anyone who happens to be using both of those tools - The spec recommends reverse domain notation as the key for an extension. Where people use that, it provides a bit of a clue as to who made that extension. So if the spec editors or other tool makers want to understand it, they've got a better chance of finding out who to speak to.
- If paired with something like the proposal in #144 folks who use extensions could even provide an explicit URL to visit for more info
- While I think there are some valuable use-cases for
$extensions
(mainly as a means for people to prototype new features which can later be standardised as "proper" format properties in future versions of the spec), they are nonetheless proprietary and IMHO should be the exception rather than the rule. Consequently, introducing a bit more friction to authoring them could be a good thing as it will make people think twice.
My preference would therefore be to keep things as they are but update the wording of the spec to make it clear that. custom properties are not allowed.
What do you think?
The problem with disallowing custom properties on JSON objects is that you break the entire spec, because any JSON object property that doesn't begin with $
is thus invalid. This means that any token you define would be ignored and any named groups or subgroups would be ignored.
Personally, I don't think there's any harm in adding extra properties, because the only ones that tools should care about are:
- props beginning with
$
- props corresponding to groups/subgroups
- props corresponding to tokens.
Every other property is irrelevant.
The only other way to achieve the above would be to have explicit $groups
and $tokens
props, to define our groups, subgroups and tokens.
FYI: For the tool that I'm building to parse Token JSON documents, I normalize group and token configs by excluding any property that doesn't begin with $
.
I think that we're getting confused here as people might be using the word "property" to refer to somewhat-different things: (1) a general word describing an aspect of a token or group, and (2) any child item in the JSON structure using the JavaScript definition of "property."
Using the JavaScript definition of "property" very technically, @CITguy is correct—the spec no longer makes any sense if all "custom properties" are disallowed. But I don't think anyone is proposing that. I think we're exclusively discussing the more general question of "can something that has a property named $value
also have another property with a name not starting with $
, and use that to store nonstandard data?"
Indeed. That's how I've been thinking about this.
To elaborate a bit further:
Conceptually, there are 2 kinds of entities in DTCG files: Groups and design tokens. The spec defines various properties that each of those can have (e.g. type, description, etc.). For edge-cases where tools or teams want to append some proprietary metadata to a token or group, they have the special extensions property.
In terms of syntax, both groups and tokens are expressed as JSON objects. Since both the names of a group's items (tokens or nested groups) and DTCG properties of that group are expressed as JSON keys on that object, we introduced the $
prefix as a way of differentiating between them. All DTCG properties now and in the future willl begin with $
, so names of items in the group are forbidden from beginning with that character (but anything else is allowed).
In order to keep the syntax of design tokens consistent, we chose to also use the $
prefix there too. Even though, unlike groups, tokens (conceptually) can't have properties other than the ones the spec defines.
Note the JSON syntax of a design token's $value
is strictly defined for each of the spec's available types. For some types those values are themselves JSON objects. We don't use the $
prefix for keys within those objects.
As I understood it, the OP was asking whether JSON keys in a design token object that do not have the $
prefix are allowed or not.
While you could argue that extraneous properties on tokens do no harm, assuming that DTCG parsers will just ignore them (unless they have some special, proprietary support for them), I'd prefer for the spec to forbid them as:
- We already have
$extensions
as a place for putting any extra stuff and, as explained above, I think it has some advantages over random, extra properties directly on the token object too. - Admittedly this is a subjective thing, but for a human reading DTCG files, I think never having non
$
-prefixed properties on tokens might make them easier to distinguish from groups which necessarily do have extra keys.