-
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
Suggestion: colorList type for DataViz #228
Comments
I don't have any feedback on the dataviz scenarios themselves, but JavaScript does explicitly define iteration order now and it's supported everywhere. Strings that contain integers in numerical order, then all other strings in insertion order, then Symbols. |
I'm partial to the simplicity of the current specification, however, this made me consider something beyond what you are asking. Why not just allow the {
"dataviz": {
"$type": "color",
"$value": [ ... ]
},
"typography-scale": {
"$type": "dimension",
"$value": [ ... ]
},
} A difficulty here is that there's often a separation between token author and token user. While the token author knows that this kind of token is expected as a list (accessible by index), the token user might not know as they usually only apply tokens by name. Having an additional accessor past the dot-notation for some tokens may be easily missed in practice for these "special" tokens. Thereby not applying a value at all. I know the purpose of these tokens isn't for someone to apply individually, but programmatically. However, I don't know if that's enough of a case for them to be different from the rest of the spec. Also requiring to know how many items exist is a challenge, since some lists could have different lengths. This is especially in the case of the D3 example. In a CSS rendered world, where tokens are often finally written as I think the reasons above make it challenging for any list type to exist.1 In the system we use today, we've explicitly set out for 30 colors across each theme which must all be defined. If they need to loop (meaning one theme only has 6 colors, they are applied 5 times), then so be it. Not listed as an array but as separate names (like all other tokens) such as Fundamentally, each token is meant to represent the eventuality of a single value. It's why the I'll mention that this family of colors is not only helpful for charting, but any place where color is meant as a differentiator between elements of the same group (like avatar defaults). I've called them "figure" colors in the past, meant to color shapes. This is the most challenging set to name because it's not possible to give them semantic meaning past their group. These are effectively base colors that expect to be applied directly in the UI. I've experimented with going so far as coloring illustrations this way (ie., color-by-number) which takes an extra amount of focus and coordination between themes to get right. Footnotes
|
Interesting discussion. I can certainly see the value in being able to describe a list of colors. Furthermore, if we were to go down that route I do like the idea of generalizing it so that you could have lists of any kind of token. However, a problem with @ddamato's suggestion of just allowing any So, how would a tool reliably differentiate between an ordered set of individual font family names, versus a single font stack? Perhaps not a very real-life example, but hopefully you get the idea. At first, I was thinking an alternative might be to introduce a new {
"color": {
"category10": {
"$type": "color",
"$list": [
"#1f77b4",
"#ff7f0e",
"#2ca02c",
"#d62728",
"#9467bd",
"#8c564b",
"#e377c2",
"{reference.to.some.other.color.token.why.not}",
"#bcbd22",
"#17becf"
]
}
}
} But, an immediate issue with that is that it quickly breaks down when you consider what happens if this list token is (accidentally?) referenced from another token which is expecting a singular value. {
"color": {
"category10": {
"$type": "color",
"$list": [
"#1f77b4",
"#ff7f0e",
"#2ca02c",
"#d62728",
"#9467bd",
"#8c564b",
"#e377c2",
"{reference.to.some.other.color.token.why.not}",
"#bcbd22",
"#17becf"
]
}
},
"gradient": {
"rainbow": {
"$type": "gradient",
"$value": [
{
"position": 0,
"color": "#000000"
},
{
"position": 1,
"color": "{color.category10}" // It's a color token, Jim, but not as we know it
}
]
}
}
} Is that an error? Is there some convention like tools should just pluck out the first value from the array? Neither of those feels particularly intuitive. Maybe I'm overthinking things and we should just add a new |
For clarity, my post isn't a suggestion but a thought experiment that eventually lands on the reason why I don't think these should be arrays; the accessor to get to these items would be variable making them difficult to target, especially across themes which might have different lists. In my mind, it's easy to ensure the same token names exists across files, thereby ensuring that a token name can be used always. It'll be much harder when the accessor is potentially varied across files. // theme1.json
tokens.colors.red = #ff0000
tokens.colors.dataviz[5] = #271f24
// theme2.json
tokens.colors.red = #550000
tokens.colors.dataviz[5] = undefined |
After chewing on the question “should any value accept an array” I originally wanted the answer to be “yes” but now I’m not convinced it’s possible. In some tokens, order is significant (font family fallbacks, color ramps); in other tokens it wouldn’t be (shadow arrays likely could be combined in any order). Further, some tokens wouldn’t have a clear use (what would an array of cubic béziers even be used for)? Different concerns from how different token types are used wildly differently would probably warrant new token types altogether with add’l metadata on how each is used. The design of groups is flexible enough that most of the time a group is just fine + a short description on the group on how it’s organized. Maybe even |
Big +1 to having this use case be solved by token groups, not by a new type. And agreed with the suggestion to avoid arrays where we can; I think in some token types it's going to be useful to allow arrays, but generally key/value pairs are going to be much much better. |
Proposal
I’d love to see a new composite type that essentially groups an array of colors that can be useful for categorical data visualization, e.g.:
Example: all of D3’s categorical schemes are
colorList
sDefinition
The defining factors for a
$type: "colorList"
are:$type: "gradient"
tokens)The main usecase is for categorical data visualization such as colors for bar graphs, line charts, pie charts, sankey diagrams, and the dozens of other chart types that rely on categorical coloring.
I believe data visualization palettes should be part of a design system and therefore be tokenized. The New York Times, FiveThirtyEight, the Washington Post, and others all have well-established principles of dataviz that are central to their design system. It makes sense that this should be preserved in a token specification for this.
Naming
I do not care about the name
colorList
. I was only trying to avoid using the term “group” as that has other meanings in this spec. “Palette” is also too generic, and could refer to any arbitrary grouping. “List,” however, is a generic computing term for an ordered collection of items. “Array” would work, but I feel that’s less natural to say, and often doesn’t mean anything to non-programmers.Open to suggestions / alternate names here.
Distinction
This is probably not a good fit for color ramps as those colors are usually pulled individually, and follow specific naming patterns unique to that design system (e.g. you’d want to refer to
color.blue.900
and not “the seventh color in this array list”).This should also not be used for gradient-like color lists. Whereas gradients allow implicit interpolation between the stops, a
colorList
allows NO interpolation between adjacent colors. Each color is specifically designed to be unique, and does not bear a clear relationship with its sibling colors (other than being visually distinct).Alternative Approaches
A “hack” that is workable today is having recommended way to set groups as arrays, e.g.:
However I would not be a fan of this approach because:
❌ It does not restrict all tokens be of the same type
❌ It does not prevent subgroups
❌ Objects are not meant to preserve ordering
(in JavaScript-land,0
appearing before1
is never guaranteed, and it would have to be on the tool itself to manually sort each time, which isn’t clear from the spec it should do).Edit: it seems this isn’t always true—modern JS does allow for deterministic ordering with number-like keys. But I’d still argue that key–value maps aren’t designed for specific ordering, and this holds true for other non-JS languages which may parse this JSON
❌ No way to guard against missing values (is
"5", "10", "15", "20"
meant to be interpreted as a length of4
, or is it an array length of20
with transparent colors in-between)?Obligatory Caveat
Apologies if this discussion has happened in another thread, or if someone has suggested something different / conflicting. Open to feedback / combining with another ongoing discussion I may have missed
The text was updated successfully, but these errors were encountered: