Open o-t-w opened 2 years ago
Yep! I’m all for whatever gets it done. And maybe @DominikDeak ’s suggestion of colorProfile
is the least ambiguous for that portion.
I'm using Oklch as a primary space in our design system mainly used in web apps. We also need another spaces for Figma, MS Office etc. We don't use Design Tokes Format Module yet, just plain JS object. This is how it would looked like:
{
"$name": "amber-30",
"$humanName": "Amber 30",
"$css": "--amber-30",
"$modifier": "30",
"$bgInteractionMode": "darken",
"$type": "color",
"$value": "oklch(0.84 0.1 82)",
"$colorSpaces": {
"oklch": "oklch(0.84 0.1 82)",
"hex": "#ebc57d",
"rgb": "rgb(240 200 130)",
"hsl": "hsl(39 74% 71%)"
}
}
What I would improve is that if $type: color
has multiple values, the name of the key could represents name of color space. I don't think there is a need for hex
to be split into channels. It is so widely used as is, so there is no need to complicate its definition.
{
"$type": "color",
"$value": {
"oklch": {
"channels": [0.84, 0.1, 82],
"alpha": 0.5
},
"hex": "#ebc57d80",
"rgb": {
"channels": [240, 200, 130],
"alpha": 0.5
},
"hsl": {
"channels": [39, 0.74, 0.71],
"alpha": 0.5
},
}
}
What I would improve is that if
$type: color
has multiple values, the name of the key could represents name of color space. I don't think there is a need forhex
to be split into channels. It is so widely used as is, so there is no need to complicate its definition.
We considered that, but have decided to just have 1 token = 1 color (1 colorSpace) for now. It would be overly complex for tooling to look at a color and have to sift through which colorSpaces are / aren’t available for a given token, and “rank” what it wants to pull as the color (because, for example, many OKLCH colors have no parallel in HSL, and so it’s opinionated how you’d even go about converting one to the other).
hex
is just a fallback for sRGB
, not a competing colorSpace, meant to encourage wider support for older hardware where only sRGB
is supported. For that reason it’s optional and can be omitted if you don’t need it. But many platforms will, and again, gamut clipping is opinionated and there’s no absolute way to do it.
Lastly, taking gamut clipping out of the equation, if you’re converting from one colorSpace to another, it’s trivial to do with libraries available like culori, so in a sense, declaring multiple colorSpaces on one token is redundant and unnecessary work. No matter what form your color tokens are in, you’ll still have to transform them anyway when delivering code to any platform (web, Android, iOS, etc), and make per-platform decisions on how to do so. A design goal of the DTCG spec is to have platform-agnostic tokens that you can apply platform-specific decisions to later; not to have to solve all your platform problems in one place (even assuming that’s possible).
Also, a few notes amended to @kaelig’s updated proposal:
It’s been raised “what are the channel values and how are they defined?” For example, is "colorSpace": "srgb", "channels": [64, 0, 128]
valid? For clarity, we’ll use the same definitions as CSS Color Module 4’s color()
function, which defines colorspaces and values in §10, such as srgb
channels being red
, blue
, green
in that order, and accepting only [0, 1]
values.
The only clarification we’d make is that percentages wouldn’t be supported, since there is no percentage type (yet). Just normalize to 1
(0%
= 0
, 100%
= 1
).
Also a question of “what is aliasable” is inevitable, and we’d like to propose Any sub-value is aliasable if it resolves to a valid $type.. For example:
$value
This is supported today, of course
{
"action": {
"$value": "{color.blue.500}"
}
}
This is consistent with current docs for $type:
If the token’s value is a reference, then its type is the resolved type of the token being referenced.
In other words, this seems allowed by current usage of spec.
Further, referencing within "channels"
should be allowed because even though there is no array of number types, individual values are all $type: number as well. Just as though gradient tokens’ stops aren’t a $type in and of themselves, they are allowed to alias color and number tokens.
{
"action": {
"$type": "color",
"$value": {
"colorSpace": "oklch",
"channels": ["{lightness.70}", 0.153, 246.18],
"alpha": "{alpha.100}",
"hex": "#3ca5f7"
}
}
}
Since there is no valid types that "colorSpace"
or "channels"
could resolve to, they’re invalid. Further, since string types are not supported, and colors are now objects, technically "hex"
could not resolve to a valid $type, either.
{
"action": {
"$type": "color",
"$value": {
"colorSpace": "{colorSpace.oklch}",
"channels": "{channels.color.blue.500}",
"alpha": 1,
"hex": "{color.blue.500}"
}
}
}
This is another proposal entirely: https://github.com/design-tokens/community-group/issues/148
{
"action": {
"$type": "color",
"$value": {
"colorSpace": "oklch",
"channels": [0.7, 0.153, 246.18],
"alpha": 1,
"hex": "{color.blue.500.$value.hex}"
}
}
}
Update: I just edited the comment below to mention we'd be only supporting HEX 6 as a hex
fallback (not HEX 3, 4, 8), because the alpha is controlled by the alpha
property.
https://github.com/design-tokens/community-group/issues/137#issuecomment-2116168184
I'd like to propose adding support for the CMYK color model to the specification. This enhancement aligns with our goal of making the specification more flexible and future-proof by accommodating various color spaces.
Proposal Details:
colorSpace
as "cmyk"
.channels
to accept an array of four values representing the Cyan, Magenta, Yellow, and Key (black) components.{
"$type": "color",
"$value": {
"colorSpace": "cmyk",
"channels": [0.0, 1.0, 1.0, 0.0],
"alpha": 1.0,
"hex": "#ff0000"
}
}
Or using percentages between 0 and 100:
{
"$type": "color",
"$value": {
"colorSpace": "cmyk",
"channels": [0, 100, 100, 0],
"alpha": 1.0,
"hex": "#ff0000"
}
}
Benefits:
colorSpace
and channels
properties.Important to then be able to specify which cmyk profile.
Very much in favor of supporting CMYK but yes would have to specify the profile as @romainmenke said. We wouldn’t have cmyk
on its own, but following the other colorspace syntax, it would be cmyk-swop
or cmyk-fogra32
, etc. Would love for someone who works more regularly with printing to propose what a reasonable set of all those would be.
Uh, before going off and inventing a new syntax, perhaps look at 5.4. CSS and Print: Using Calibrated CMYK and Other Printed Color Spaces in CSS Color 5, which already does calibrated CMYK?
Introduce the ability to specify colorSpace as "cmyk".
That doesn't mean anything, without saying which cmyk colorsdpace (what inks, what paper, what printing conditions, what level of GCR, maximum coverage, etc). All fo which is defined in an ICC profile.
{
"my-token": {
"$type": "color",
"$value": {
"hex": "#xxxxxx", // Only HEX 6 supported (no HEX 3, 4, or 8)
"colorSpace": "dci-p3",
"channels": [0.1, 0.2, 0.3],
"alpha": 0.6
}
}
}
Is the sRGB hex a fallback, or the main color?
Is DCI-P3 (a projector space for digital cinema, to be viewed in an entirely dark room) really, means, or display P3?
Ah sorry @svgeesus this issue is out-of-date. We’re currently working on updating this PR after some internal discussion, but TL;DR we’re going to align around CSS Color Module 4 (and potentially Module 5). So we’re aligning with display-p3
over dci-p3
, e.g.
Is the sRGB hex a fallback, or the main color?
Optional fallback for support on more devices (since color clamping is opinionated)
From the part of the spec about color types: “Represents a 24bit RGB or 24+8bit RGBA color in the sRGB color space. The $type property MUST be set to the string color. The value MUST be a string containing a hex triplet/quartet including the preceding # character. To support other color spaces, such as HSL, export tools SHOULD convert color tokens to the equivalent value as needed.”
Chrome is currently working in implementing LCH, LAB, OKLCH and OKLAB color. Safari already supports them. Although support is currently rarer among design tools it still seems sad and backwards-looking to standardise and require a legacy color format.
It is impossible to transform a hex color into a modern color. It is overwhelmingly likely that the modern color formats will become ubiquitous on the web within the next year or two. I'm sure design tools will quickly follow along.
My suggestion would be to standardize on OKLCH already and have design tools that don't yet support modern color transform the color into hex.
I'm already using LAB and LCH on a large web application with hex fallbacks. Standardizing on hex would make design tokens unusable for me.