Re: [csswg-drafts] Proposal: CSS Variable Groups (as a solution to several design systems pain points) (#9992)

> Though does that mean the wildcard could be preceded by anything? Would people be able to do --foo*: {s: ...} and reference it as --foos?

I suspect we don't want to allow that, just because that means we have to be a lot more literal with the nested bits. Like, we'd have to allow `--foo*: {s: ...; }`, which means we're closing off the ability to do any of the base/etc stuff. Whereas if we require a dash, we can require it on *both* ends, like `--foo-* { --bar: ...; }` and keep the namespaces nicely separated.  (Also, requiring a `--` on the nested bits keeps the parsing working nice even when the bits are just numbers, like `--gray-* { --500: ...; }` works right now while `--gray-* { 500: ...; }` doesn't.)

> Did you see the entire table of popular design systems that I included in my proposal?

Yes, but that's not what I was asking for. I'd want to see *worked-out examples* of how such design systems would use this, and how it would make their usage of their own design systems easier and more reliable. Ideally every reader of the proposal doesn't have to do the working out themselves. ^_^


> It's not just about verbosity. I have no idea how you'd offer something where the design system specifies the ends and the midpoint, and the other tints are automatically computed BUT you can also add hand-tweaked variants to influence how the interpolation works. Though perhaps that is better addressed in mix()/color-mix().

Can you give an example?

> Groups are analogous to objects/dicts, not functions. Dynamic groups do encroach into function territory, but they are more analogous to JS proxies than functions.
> 
> You could argue that everything can be implemented via functions (and Lisp even argues that everything can be implemented via lists) but typically languages offer data structures as well, because implementing data structures as functions is painful AF.

My argument isn't that we should treat data structures and functions as equivalent. It's that your proposal spans *the full gamut* from "obvious data structure" (variable groups) to "obvious function" (variables with continuous variation), and we should be careful about how we handle this.

CSS is already going to grow functions in some way.  Do we want two distinct function syntaxes - one defining globally using at-rules, and one defining locally using properties? If so, how much can they differ in power/expressiveness? How much flexibility do we even *have* in declaration syntax? How much will this cost us in terms of future syntax flexibility?

Currently, I'm *very* hesitant in trying to define a separate, second function syntax, and *extra* hesitant about doing so *within the bounds of declaration syntax*. I would need an *extremely* compelling argument that it's both necessary, and the only way to do so, before I'd be willing to go for it. (I'm *super extra* hesitant about doing any of this *before we have even actually defined the first type of functions*.)

Because we still have to answer the question: how much *must* we do? Can we do a fairly small feature (variable groups) that solves 90% of the problem, and just skip the last 10%, thus avoiding having to define a massive new feature (declaration-syntax cascading functions masquerading as custom properties)?  If that 10% *does* need to be solved, are there other ways to do it that aren't as heavyweight of a feature?

Maybe the split is actually that the small, easy feature can only handle 50%. Maybe the remaining issues, while unsolved, are fine to just leave as something that's a little awkward to write.

In the absence of answers to those questions (reasonable, because this is a very early exploration into the space!), I'm trying to push on the boundaries a bit. How much *can* we solve using existing (or planned) features instead? If we do have to introduce new features, what other possibilities exist that might be lighterweight in syntax and/or functionality?

> I think possibly the biggest issue is around encapsulation. Whether the palette is defined as continuous or not, or somewhere in between should be an implementation detail, not drive how you refer to design tokens. The final user of the design system should not have to care about whether --color-red-200 is specified manually, or the result of interpolation between e.g. --color-red-100 and --color-red-400.

Generally speaking, I disagree with this! What you expose *and how you expose it* are important considerations in API design. If, in JS, I hand my user an object and they're expected to access properties on it, that *implies* that there's a finite, predetermined number of values I can access. If I hand them a function that takes a continuously-varying argument, that *implies* that there's a continuously-varying output value. If I swap either of these, I'm somewhat violating expectations, and better have a really good reason for doing so.

Of course, in a *full* programming language, you can somewhat mask the difference. If I hand the user an object with a few values in it, they don't need to know whether it was constructed from an object literal, computed completely dynamically, or some combination of the two. We can't do this in CSS, and the current planned approaches do indeed require you to commit to one or the other.

> And it should be possible to change between the two, without uses having to be updated. E.g. you notice that your generated --color-yellow-800 is crap and want to insert a stop in terms of how the interpolation happens, that should be possible without users of the design system having to update their code (and other shades near it should also benefit from the adjustment).

As an example of a different possible approach, perhaps the use-case here can solved in a more narrowly-targeted fashion. For example, maybe we can define a "value ramp" (a few types - numeric, color, others) that represents a range of interpolated values, can be passed around in custom properties, queried for particular values on the ramp, and extended by others. Like:

```css
/* any number of colors can be given */
--color-primary: color-ramp(in oklch,
                            100 oklch(95% 13% 135),
                            900 oklch(25% 20% 135));

/* you can ask the ramp for any value in the range */
background: get-ramp(var(--color-primary), 400);

/* you can create a ramp from an existing one 
   by adding or overriding stops */
--better-primary: color-ramp(from var(--color-primary),
                             800 forestgreen);
```

Or maybe the ramp is defined by an at-rule, with the ability to reference custom properties from point-of-use; that might give us a richer syntax to play with, especially for overriding. Like:

```css
@color-ramp --primary {
 stops: 100 oklch(95% 13% 135),
           900 oklch(25% 20% 135);
    interpolation: oklch;
}
@color-ramp --better {
 extends: --primary;
 stops: 800 forestgreen;
}

.foo { background: color-ramp(--primary 400); }
```

This could sprout more abilities, too, like the ability to round the input to some precision (only every 100, or 50, or whatever), define whether it extends past the first/last stops, etc.

This sort of approach would also suffer from the "everyone has to use this method" problem you outline, but it's also vastly simpler than "inline functions defined in the declaration grammar", much more extensible, can be specialized to the problem space in important ways, etc.

Are all the design-system cases that want generative/continuous values doable with something like this? Are they all just sizes and colors, or other things that might similar fit into this framework? We'd need to see. Maybe they *would* all just switch to this sort of value, were it provided, so you wouldn't need to worry about some using "a whole bunch of values stored in individual properties" that required a lot of manual renaming.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9992#issuecomment-1979797500 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 5 March 2024 23:15:03 UTC