design-tokens / community-group

This is the official DTCG repository for the design tokens specification.
https://tr.designtokens.org
Other
1.53k stars 62 forks source link

Gradient type feedback #101

Open c1rrus opened 2 years ago

c1rrus commented 2 years ago

Is the gradient composite type fit for purpose? Does it need to also specify the type of gradient (.e.g linear, radial, concial, etc.)?

Please share your feedback, thoughts and ideas in this issue.

drwpow commented 2 years ago

Does it need to also specify the type of gradient (.e.g linear, radial, concial, etc.)?

I do really like the proposal here, and I like the simplicity of having the gradient stops be universal, where you decide linear, radial, conical when generating code for a specific component (which in one part makes sense because a rotated gradient is still the same gradient).

But there also seems like an opportunity here to make linear-gradient, radial-gradient, and conic-gradient their own types to fill in the missing data (which exist as a concept both in CSS and Figma). Overall I fear that people may just abuse metadata on gradients here and put all the missing parts in there, at which point distinct types would be more useful. I could go either way—one gradient type with stops only, or distinct gradient types with complete properties.

TravisSpomer commented 2 years ago

Omitting details like the type of gradient doesn't make much sense to me. A reasonable expectation is that for any given token, a design tool has everything it needs to display that gradient (like a Figma style), and a dev tool has everything it needs to turn that token definition into code. The current gradient spec doesn't work for either case. As it stands, I'm not really sure how I could use a gradient token for anything at all, without encoding all of the missing information as extensions.

At absolute minimum, I think that a gradient token needs to also include:

It would also be unfortunate if gradient stops were limited to specifying stops as a number 0-1. Other systems also allow stops to be defined as absolute units. For example, you might specify a gradient as going from black at 0, to transparent at 10px, to transparent at 1—that would get you a "poor man's shadow" that was always 10px wide no matter the size of the object you paint with it. That's admittedly a less common case, but it's something that I'm using today to support web and WinUI, and to continue supporting it I'd need to add an extension property like "actuallyTheseAreTheRealGradientStops": [ 0, "10px", 1 ].

solemone commented 2 years ago

Hello everyone,

I have a question about the number of gradients. How about multiple gradients? Is the value then an array with arrays? Like like this:

{
  "blue-to-red": {
    "$type": "gradient",
    "$value": [
      [
        {
          "color": "rgba(0, 0, 255, 0.5)",
          "position": 0
        },
        {
          "color": "rgba(0, 0, 255, 1)",
          "position": 1
        }
      ],
      [
        {
          "color": "rgba(255, 0, 0, 1)",
          "position": 0
        },
        {
          "color": "rgba(255, 0, 0, 0.5)",
          "position": 1
        }
      ]
    ]
  }
}

Or is this a different type like »multifill«? And what about when gradients are to be mixed with solid color? Could this be something like this:

{
  "blue-and-red": {
    "$type": "multifill",
    "$value": [
      {
        "$type": "color",
        "$value": "rgba(0, 0, 255, 0.5)",
      },
      {
        "$type": "gradient",
        "$value": [
          {
            "color": "rgba(255, 0, 0, 0.5)",
            "position": 0
          },
          {
            "color": "rgba(255, 0, 0, 1)",
            "position": 1
          }
        ]
      }
    ]
  }
}

Thanks for all the work!

NateBaldwinDesign commented 2 years ago

I agree supporting other gradient types is necessary, but I am of the opinion it doesn't need to be a different token type itself.

I would like a few things here: First, it would be nice to have a default inferred from a list of values. Ie, values: [#ff0000, #0000ff] will automatically infer placement to be [0,1]. Reason being, it may be unnecessary, bloat, or redundant based on certain use cases. My next ask will shed more light.

Secondly, I would like the option to just pass an array of values. I go at great lengths to make perceptually balanced gradients, and given technological restrictions, most of the time an array of many values (spaced equidistant in the range) is the best way to replicate the gradient. For instance, if I have a gradient with 20 unique colors, it would be tedious to write all the intervals in the proposed format.

Thirdly, it would be great to include an option for interpolation color space. Technology is working to catch up on this notion and certain design tools support it. For instance, defaulting to rgb interpolation is ok, however I may want to use OKLCH for a multi hue gradient. Interpolation color space options can reduce the number of individual color values needed to replicate a perceptually balanced gradient (within these examples)

kitgrose commented 2 years ago

It's a shame to see that there's no spec support for opacity stops being defined independently of colour stops. I recognise that many modern design tools don't make this easy (or even possible) either, but it's something I'd expect to be able to specify in an interchange format.

As a simplified example, if I have a gradient that blends across some number of stops (e.g. black → white), and simultaneously an alpha blend with a different number of stops (e.g. from 100% → 0% → 100% opacity), or with stops at different locations, the final result requires all intermediate stops (in this example case middle grey) be computed at export time. That prevents these gradients from being properly round-tripped back into design software that separates these two concepts (e.g. Photoshop), and also prevents the use of colour aliases for the individual stop values.

Ideally computing all the individual distinct stop values would be a transformation step performed afterwards based on the technical capabilities of the output format (so that if some output language supported the distinction between opacity and colour stops, that could be supported by the same design token file).

Here's an example of an online tool that attempts to support computing interpolated colour stops based on independent alpha and colour stops to give you a sense of what I mean (although in practice, CSS has issues properly representing colour stops that have zero opacity, effectively ignoring their colour—the "correct" output can be obtained using SVG, though).

putchom commented 1 year ago

I think $value needs an angle property because Figma, CSS, etc. allow angles to be specified for gradients.

like this:

{
  "blue-to-red": {
    "$type": "gradient",
    "$value": {
      "angle": 45,
      "colors": [
        {
          "color": "#0000ff",
          "position": 0
        },
        {
          "color": "#ff0000",
          "position": 1
        }
      ]
    }
  }
}
PavelLaptev commented 1 year ago

Agreed with @drwpow gradient tokens is a very abstract entity. So there should be a definition:

GradientToken {
  $type: "gradient";
  $value: {
    type: "linear" | "radial" | "angular" | "conic";
    angle: number;
    stops: {
      position: number;
      color: ColorToken | string;
    }[];
  };
}
PavelLaptev commented 1 year ago

For "radial" gradients, there also should be a size property, e.g.:

GradientToken {
  $type: "gradient";
  $value: {
    type: "linear" | "radial" | "angular" | "conic";
    angle: number;
    size: "30% 50%"
    stops: {
      position: number;
      color: ColorToken | string;
    }[];
  };
}
pcjmfranken commented 1 year ago

Colour stop easing functions could very well end up making it into the CSS Images Module Level 4 spec. It is actively being discussed here: https://github.com/w3c/csswg-drafts/issues/1332. Additionally, use of this technique seems surprisingly common amongst designers, but I've only seen it done by means of third party plugins (design tools lacking native support, I assume).

The eased transition between two colours will be different when those are interpolated to different colour spaces. Preserving the actual function type and parameter values as a token value is therefore essential.

Additional resources:

jorenbroekema commented 4 months ago

I wanted to add to this discussion that the gradient types I've heard here are mostly static by nature, even though the shapes can be defined as "linear", "conicol", "angular", "radial", "diamond", whatever, the color stops are a single dimensional array and the shape of the gradient can be defined "statically" with a string enum.

There are also types of gradient which I see used more and more in modern designs, which cannot be defined by a string enum to describe statically what the shape of the gradient looks like:

I think it would be smart to at least distinguish between these two types of gradients, once that have a standardized "shape" and those that do not. And at least not jam those two into the same token type 😅 .

For the standardized shapes gradients, the main thing I'm missing: