Skip to content
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

Multiple values - Array type #239

Open
jorenbroekema opened this issue Jul 29, 2024 · 3 comments
Open

Multiple values - Array type #239

jorenbroekema opened this issue Jul 29, 2024 · 3 comments

Comments

@jorenbroekema
Copy link

Raising this issue to discuss multi-value design tokens.

Relevant because I saw this idea pop up first for Shadow tokens, as it's quite common to layer shadows on top of another:
#100

Another example is dimension tokens e.g. when defining the padding of an element, say a button. You may want to specify a vertical and horizontal padding (or even all 4 sides explicitly), just like you may want to specify multiple shadow values as a single shadow. I think in both scenarios they can be viewed as a single design decision, thus is makes sense for it to be a single design token.
There's probably other examples we can think of, e.g. multiple gradient tokens being stacked at different coords to create gradient meshes/blobs. Transitions is also a good one, since those can be stacked as well to create a multi-step or multi-layered animation.

This brings up the broader question, should all tokens allow you to use an Array as value, where each item must adhere to the type specification? Is "multi-value" valid for every token? Is it only valid for some tokens, and if so, for which ones is it not and why not?
This could obviously be misused to squish many design decisions into a single token, which is why I'm not completely confident to have a strong opinion on the answer to this and why I think it warrants discussion.

I am leaning towards saying "yes, it's valid for all tokens, and the spec should guide users on what would be considered misuse of the feature"

@nclsndr
Copy link

nclsndr commented Aug 22, 2024

That's a topic we discussed a lot while building the Specify format.

My 2 cents: Array based values are necessary to express specific decisions, best is to use specific names for that matter, otherwise aliasing becomes a nightmare and users get lost.

I think, the best way to host array based value is by creating semantically meaningful types like: gradients, shadows, spacings, colorList (as proposed in #228)...
Doing so, we make sure we give users a type they can read about, and we can provide them with a clear documentation on how to use it.

On the aliasing side, let's make a simple thought experiment: we have a color token with an array of 2 values. This color token is referenced within the color property of a border token. Which color is the border going to use? So simple (and singular) types should host one value only.

As a starting point I would propose the following types:

color

type ColorList = Array<Color>

dimension

type Spacings = 
  | [Dimension]
  | [Dimension, Dimension] 
  | [Dimension, Dimension, Dimension] 
  | [Dimension, Dimension, Dimension, Dimension]

number

type NumberRange = [Number, Number, Number] // min, max, step
type NumberList = Array<Number>

border

type Borders = 
  | [Border]
  | [Border, Border] 
  | [Border, Border, Border] 
  | [Border, Border, Border, Border]

shadow
Related to #100

type Shadows = Array<Shadow>

gradient

type Gradients = Array<Gradient>

I can't think of related types for: fontFamily, fontWeight, duration, cubicBezier, strokeStyle, transition, typography.

Here how the aliasing might work:

{
  "simpleBorder": {
    "$type": "border",
    "$value": {
      "color": "#000000",
      "width": "1px",
      "style": "solid"
    }
  },
  "multiBorder": {
    "$type": "borders",
    "$value": [
      "{simpleBorder}",
      {
        "color": "#FF0000",
        "width": "2px",
        "style": "dashed"
      }
    ]
  },
  "cardBorder": {
    "$type": "borders",
    "$value": "{multiBorder}"
  }
}

Leveraging both nested and semantic aliasing while keeping clear the role of each token.

@jorenbroekema
Copy link
Author

@nclsndr My only addition to your comment is that I wouldn't restrict the proposed Array types to 1, 2, 3, 4 items for borders/dimensions or 3 values for color ranges. While for most color spaces there are 3 channels and the (CSS) box model uses 4 sides, who's to say this will always be the case? Maybe in other platforms there's more parameters and they don't share the same box model. Imo easier to simplify by just allowing any number of items

@nclsndr
Copy link

nclsndr commented Aug 26, 2024

I wouldn't restrict the proposed Array types to 1, 2, 3, 4 items for borders/dimensions

Agreed! Maybe we can have:

  • Plural: Dimension -> Dimensions
    The plural gives a simple rule and an intel on the array-based value.
type Dimensions = Array<Dimension>
type Borders = Array<Border>
...
  • Usage: Paddings, Margins...
    Usage-based tokens would convey more context to speed up the UI integration and code generation.
    Yet it's definitely more challenging to land on specs that would fit most, if not all, the platforms. Probably discussions for later versions of the spec.
type Paddings = [Dimension] | [Dimension, Dimension] 
type SquareBorders = [Border] | [Border, Border] 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants