-
Notifications
You must be signed in to change notification settings - Fork 675
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
[css-values-5] What is the MVP for inline conditionals on custom properties? #10064
Comments
when i first discovered style queries, i admit i had intuitively tried to do something like this: @container style(--variant: large) {
& {
/* style the container itself */
}
} it seems a way to select the container that or maybe enabling style queries as part of the @scope style(--variant: large) {
:scope {}
} |
I had a chat with @andruud a few days ago, and he said that this proposed design would be fairly easy to implement. Edit: updated first post |
Yeah, at least if we choose the path forwards carefully, it should be easy. That carefully chosen path could be something like:
Of course we'll need to deal with cycles. e.g.:
But we should be well equipped to handle that. So if the CSSWG determines that this is worthwhile, it should be quite doable overall. I suppose it's worth thinking about custom functions here as well, since they also kind of provide "inline" conditionals. It might not be ergonomic to use for the use-cases you have in mind, though. |
It would seem a bit strange to me if |
I’m fine to make it invalid at parse time, but it seems like a lot of work for an edge case. Especially given there might be multiple conditionals for a single property value, so it's a combinatorial explosion to tell if any of them would result in a valid value. |
Yup. How hard would it be to support other queries beyond |
I don't see why we couldn't do |
Fair. So we’ll need a distinct token and not |
A few more workarounds authors can use right now:
I recommend going to the linked articles and codepens to witness the hacky CSS that is currently required to achieve those conditionals. Given how often authors reach out to things like space toggles or come up with more and more convoluted ways to achieve conditions for different use cases (Is a custom property defined? Is value A is smaller than B? Are those two conditions true? Etc.), we really need at least some way to have these kinds of conditions. Ideally, I'd want to have both inline conditions, but also an at-rule-level ones, but even if we will resolve only on inline conditions it will improve the lives of authors tremendously. |
Unfortunately not, you gotta just write out the full grammar. It's mostly copy-pasting tho. |
Ah, I was thinking of a |
This comment was marked as resolved.
This comment was marked as resolved.
The CSS Working Group just discussed RESOLVED: Add if() to css-values-5 The full IRC log of that discussion<astearns> zakim, open queue<Zakim> ok, astearns, the speaker queue is open <fantasai> leaverou: Motivating use cases <fantasai> leaverou: right now web components libraries introduce tons of presentational attributes <fantasai> leaverou: because custom properties include parts of values <fantasai> leaverou: you can transform numeric values using calc() but keywords not possible <fantasai> leaverou: Canonical example is changing background-color based on a `--variant` property <fantasai> leaverou: These are examples for why I started shoelace library now called WebAwesome <fantasai> leaverou: [lists many examples of utility classes] <fantasai> leaverou: Style queries get us a lot of the way there, but because they only work on descendants <fantasai> leaverou: that doesn't let us get all the way there <fantasai> leaverou: so these remain presentational attributes <fantasai> leaverou: but needing to branch on a condition is very common in CSS <fantasai> leaverou: several issues last few years about how can we do this <fantasai> leaverou: either as a block conditional <fantasai> leaverou: or inline <fantasai> leaverou: there are some extremely hacky workarounds that authors use <fantasai> leaverou: e.g. stting custom property to an empty token string so it gets a value or falls back. Very very hacky things <fantasai> leaverou: Despite huge demand there's no progress <fantasai> leaverou: I opened this issue to explore what is still useful, but still easy for implementers <fantasai> leaverou: Anders said if we re-use the conditional from container queries, that let's you compare values <fantasai> leaverou: and even media and supports queries <fantasai> leaverou: re-use that part and then declaration values chosen based on conditional <fantasai> leaverou: said it was pretty easy <fantasai> leaverou: For many of these use cases, instead of having one or two values, you could have a series of subsequent conditionals <fantasai> leaverou: that's nice to hvae <fantasai> leaverou: but main thing is single test, can always nest <fantasai> leaverou: ideally we want a block conditional that applies when matches <fantasai> leaverou: but that seems to be hard, so let's do inline first <fantasai> leaverou: because we need it anyway <fantasai> leaverou: if it can be implemented quickly, would be an easy win <TabAtkins> q+ <kizu> q+ <fantasai> TabAtkins: This sounds good. <astearns> ack TabAtkins <TabAtkins> https://github.com//issues/5009#issuecomment-626072319 <fantasai> TabAtkins: going back to previous thread, this comments lists out 3 variants of conditionals <fantasai> TabAtkins: This is a variant of item 3 <fantasai> TabAtkins: one important part is these shouldn't be a boolean (true/false), it should be multi-valued so you can provide more than one test <fantasai> TabAtkins: in simplest case that's true or false, just omit last test <leaverou2> q+ <leaverou2> q++ <fantasai> TabAtkins: but I want to make sure you can sequence tests <leaverou2> qq+ <leaverou2> q- <fantasai> leaverou: it's the second grammar <emilio> q- + <fantasai> TabAtkins: sgtm <astearns> ack fantasai <astearns> ack leaverou <TabAtkins> fantasai: I think that the IACVT behavior is not amazing <TabAtkins> fantasai: so i dont' want us to have authors rely on it all the time bc there's no alt <leaverou2> q+ <TabAtkins> fantasai: to the extent taht people want to switch on a custom prop, can't we do that with some sort of conditional... <TabAtkins> fantasai: if you just switch basics based on conditionals you can avoid cycles easily that way <fantasai> leaverou: Would be useful, but this is orthogonal <TabAtkins> leaverou: a block conditional *would* be useful, but it's orthogonal <TabAtkins> leaverou2: same as in JS <TabAtkins> fantasai: not orthogonal from ux perspective. whether someone uses block or inline conditional is somewhat based on availability <TabAtkins> fantasai: if you have both you'll use both, but if you have only one you'll shoehorn <TabAtkins> fantasai: i think we should do both if we can <fantasai> TabAtkins: isnt' the block version just style queries and media queries? <fantasai> leaverou: Style queries only work on descendants <TabAtkins> TabAtkins: getting a style query block *on the element* *requires* IACVT <andruud> q+ <fantasai> fantasai: Shouldn't be a problem if you have standard properties set based on custom properties <fantasai> TabAtkins: If you restrit it only to standard properties, that's substantially restrictive <fantasai> TabAtkins: a lot of cases will want to set more variables <miriam> q+ <fantasai> TabAtkins: Those will then need to use inline version, because that's a requirement of inline <fantasai> s/because/which uses IACVT because/ <fantasai> TabAtkins: IACVT triggers if you write something wrong <astearns> ack kizu <fantasai> kizu: Wanted to show some worse things <fantasai> kizu: In October 2016, I was using custom properties to switch between values using calculations <fantasai> kizu: today you can use comparisons with calculations, if length is bigger or smaller use different value -- only for lengths <fantasai> kizu: ?? made it possible to use values with custom properties <fantasai> kizu: using type griding <fantasai> kizu: a very long chain of fallbacks to registered custom property <fantasai> kizu: and that let's you get any value back <miriam> s/??/Jane Ori/ <kizu> https://github.com//issues/10064#issuecomment-2161742249 <fantasai> kizu: The code is very complicated <fantasai> kizu: authors can now do this <astearns> q? <fantasai> kizu: recent article where using layers and [missed] <fantasai> kizu: taking advantage of revert-layer <fantasai> kizu: The need for this from authors is very high <leaverou2> fantasai note that all the workarounds involve var(). So all workarounds ALREADY invoke IACVT. This is just about making the API and ergonomics infinitely nicer <fantasai> kizu: Also wanted to mention, how could we use registered custom properties to avoid some issues with IACVT <fantasai> kizu: For those we know what types they can accept, what they can return, might make it more simple <astearns> ack leaverou2 <astearns> ack leaverou <fantasai> leaverou2, Yeah. My point is I don't want authors to need to use this MORE because it'll be so much easier, simply because don't have a better alternative <fantasai> fantasai: I don't think we should be trying to encourage authors to use a bad behavior, rather than trying to make something that works better with the cascade <fantasai> fantasai: Like we should try to make it work the right way rather than settling for IACVT <astearns> ack andruud <fantasai> kizu: Using animations to do this is worse <fantasai> andruud: For block version, if your conditional contains a registered custom property and you try to style the font size with em units, you'll get a cycle <astearns> ack miriam <fantasai> andruud: so we'll still run into cycle problems with block version <fantasai> miriam: Do those cycles make th whole thing impossible, or do they just mean font-size is invalid and we do the condition <leaverou2> ;? <fantasai> andruud: for the block conditional? <leaverou2> q? <leaverou2> q+ <fantasai> andruud: I guess we could handle those cases 1 by 1 <fantasai> TabAtkins: dependencies will crop up over time, so hard to block ad-hoc <astearns> ack leaverou <fantasai> leaverou2: The block version will be inherently limited, because some values will only make sense on a single property <fantasai> leaverou2: e.g. em/auto/normal <fantasai> leaverou2: even if we have block version, still need inline version <fantasai> leaverou2: Also you can assign conditions to a variable and then use that variable in a function, including media test <fantasai> leaverou2: so handle breakpoints more easily <fantasai> astearns: Lots of acknowledgement that this is important to work on <fantasai> astearns: but also some concern about increasing the IACVT behavior on the web <fantasai> TabAtkins: I don't believe we can solve anything in this space without IACVT <fantasai> TabAtkins: so unless we can avoid cycles with some new idea, then we need to move forward with IACVT <TabAtkins> fantasai: i don't object <TabAtkins> fantasai: lea, can you outline the proposed syntax? <leaverou2> border-radius: if(style(--button-shape: pill), infinity); <ydaniv> Is this something that could later be speced to replace IACVT into a proper behavior? <leaverou2> Longer example: background-color: if( <leaverou2> style(--variant: success), var(--color-success-60), <leaverou2> style(--variant: warning), var(--color-warning-60), <leaverou2> style(--variant: danger), var(--color-danger-60), <leaverou2> style(--variant: primary), var(--color-primary) <leaverou2> ); <fantasai> fantasai: I think it would be better if the comma wasn't used both to separate conditional and value, as well as separate sets of conditionals <TabAtkins> use a colon! <florian> q+ <fantasai> leaverou2: seems reasonable. Could maybe use a slash <bkardell_> +1 TabAtkins <astearns> ack florian <fantasai> leaverou2: could even use a ? and be more like JS <lwarlow> q+ <TabAtkins> suggest we take that syntax question to the issue <fantasai> florian: suggest using switch() for multiple cases, like JS <fantasai> leaverou2: The conditionals here chain like else-if <fantasai> leaverou2: but this expands to ranges, etc. <TabAtkins> yeah, this is an if/elif/elif/else chain <astearns> ack lwarlow <fantasai> s/chain like else-if/chain like else-if, you have to provide the conditional each time/ <fantasai> lwarlow: agree with not using comma for both places <fantasai> lwarlow: slash would read better <leaverou2> Just noticed all examples above have no else value. This is another example: `border-radius: if(style(--button-shape: pill), infinity, .2em);` <fantasai> PROPOSED: Add this to css-values-5 <lwarlow> +1 <fantasai> astearns: any objections? <leaverou2> +1 <bkardell_> https://www.irccloud.com/pastebin/nrStwApc/ <fantasai> RESOVLED: Add if() to css-values-5 |
The syntax as described makes it slightly impossible to say "else be IACVT" in some cases. (For these examples, I'm gonna assume we use
(This ambiguity doesn't occur if there are multiple chained conditions. So I think we'll need an explicit syntax for saying "no default condition". You don't usually need it, but occasionally you will, and it might make some cases clear even when it's not strictly required. Like, |
@tabatkins Why not simply make the last argument mandatory and allow empty values (just like Compare: Option 1 (mandatory last argument that can be empty): border-radius: if(style(--button-shape: pill), infinity, ); Option 2 ( border-radius: if(style(--button-shape: pill), infinity / default: ); One advantage of having a special value (e.g. If that’s not an option, I'd rather introduce a different separator than a whole keyword. I’m generally all for prioritizing readability, but readability is a balance: too concise and it doesn't make sense, too wordy and you have to wade through the clutter to understand it. With something that I expect will be used all over the place, conciseness matters quite a lot. |
That's possible, I just find it less clear to read. I don't really like how
I'm not trying to solve any feature lack, just a syntax lack around the existing features.
We can't invent infinite separators. ^_^ But also, this is something that is rarely needed - like I said, the only case that requires it is when you want to supply a single test, with a positive value containing a comma, and no negative value. If you do want to use it for clarity in other cases, I think it's perfectly readable. For example: background-color: if(
style(--variant: success): var(--color-success-60),
style(--variant: warning): var(--color-warning-60),
style(--variant: danger): var(--color-danger-60),
style(--variant: primary): var(--color-primary),
no-value
); |
Actually, let me state this better: this isn't about the separator. The issue is just that the grammar doesn't allow an empty option (and I don't think it should), so there's one particular case you can't express. |
@tabatkins Actually, if we don’t use a custom character for separating the condition from the values like the original proposal, this becomes a non-problem. By the time you get to the first value, you know what your separator is, so there’s no ambiguity in @fantasai you raised the issue of using a distinct character for separating the condition from the value(s), and I agree this would be nice. However, given the ambiguity this introduces, are you ok with going with a comma/semicolon for both to avoid having to introduce weird new keywords like |
Trying to work my way through this and make separate issues for the independent design choices. @tabatkins could you please confirm if this summarizes the design space well?
|
I don't think we need or want separate issues for these; they're not independent design decisions. We should make all the choices at once in a single resolution. But yes, those are the questions at hand. |
I said make separate issues for the independent choices. If no choices are independent, then we only need one issue. |
Right, I don't think any of them are independent. Syntax design is holistic; I have different opinions on several things depending on what options are chosen to fit together. Summarizing the questions is absolutely a good idea. |
I’m happy to do the work of listing the pros and cons, but I’ve lost track of what the distinct proposals are. Is it:
Are all of these still considered? Are there any others? |
Discussed it f2f with @tabatkins and @LeaVerou, they both are supporting required |
This is missing some important detail. The gist from our discussion with @tabatkins was that we were both ok with:
This largely alleviates my concern about verbosity, since the
Well, the fact that @tabatkins and I are in agreement doesn’t mean we don’t still need group consensus 😁
I would say there are several syntax-level questions:
|
Yeah, so, proposal:
The function resolves to the If nothing matches, it resolves to nothing (an empty token stream). (No built-in way to make the function itself trigger IACVT, don't think that's particularly needed. There are ways to trigger that if you want it, like referring to a non-existent variable.) The resolution of #9539 will have a small impact on this; if we resolve to go with {} wrappers, then this is all fine; if we stick with upgradeable commas, then we'll want to allow a final trailing comma/semicolon. I think this proposal is satisfactory to Lea, from our earlier conversation? The only thing I believe she still has a mild disagreement with is that she prefers using |
Yup, that’s a great summary @tabatkins, thank you. So basically all we need in terms of F2F time is a resolution and perhaps a straw poll for the character to separate the condition from the value. That should be pretty quick (famous last words 😅). |
I will likely miss that due to TZ difference. I started this by writing I have a preference for We currently use We also use These inline conditions are neither.
/* examples are purely to help me visualize the difference between `:` and `?` */
.foo {
color: rgb(
245
if(
style(max-width: 400px) ? 100,
style(max-width: 500px) ? 110,
style(max-width: 600px) ? 120,
else ? 140
)
10
)
} vs. .foo {
color: rgb(
245
if(
style(max-width: 400px): 100,
style(max-width: 500px): 110,
style(max-width: 600px): 120,
else: 140
)
10
)
} Not a strong preference but was interesting that trying to describe why I favored |
Random thought: if we decide on Because then when I look at the code with it, I immediately reminded of the rest of CSS: .foo {
color: rgb(
245
if(
style(max-width: 400px) { 100 }
style(max-width: 500px) { 110 }
style(max-width: 600px) { 120 }
else { 140 }
)
10
)
}
This allows us to use commas and almost any complex logic in the .foo {
font-family: if(
style(--type: prose), style(--type: book) {
'Iowan Old Style', 'Palatino Linotype', serif
}
style(--type: code) and not (--placement: inline) {
'Nimbus Mono PS', 'Courier New', monospace
}
else {
system-ui, sans-serif
}
);
} This does not introduce new characters, and builds on the existing concepts in CSS. Overall, I do not have a strong preference over a specific syntax, but just wanted to throw in another possibility :) |
The CSS Working Group just discussed
The full IRC log of that discussion<emeyer> lea: In June, we resolving to work on inline conditionals<emeyer> …There were syntax disagreements, but we seem to be converging on a specific option <lea> https://github.com//issues/10064#issuecomment-2372578597 <emeyer> …There were disagreements about else being optional or mandatory <emeyer> …How does it resolve, what should separators be <emeyer> …Converging on an else clause that it spelled out <emeyer> …If the else is omitted and nothing matches, it decomposes to a token stream <emeyer> …Right now, we need a resolution for that and for waht the separator should be <emeyer> …We think there’s value in having a different separator for the condition and the values <kbabbitt> q+ <emeyer> …Tab suggests colons, I suggest question marks <kizu> q+ <emeyer> kbabbitt: I think as written, it allows multiple elses <emeyer> …There’s also a proposal in the thread to drop separators and I like it, I think it looks cleaner <emeyer> TabAtkins: This does allow an else to be put anywhere; it’s sometimes useful when debugging <astearns> ack kbabbitt <emeyer> …I think it’s valuable to have the ability to do that <lea> essentially else is just another way to say true, right? <fantasai> the only way? :) <emeyer> …For Roman’s proposal, he’s using curly braces, which aren’t required <lea> we should have true and false constants for <boolean>... <emeyer> …There is no grammatical reason for the separator <emeyer> …They’re meant to guide the eye to separators <emeyer> …Oh wait no, not true <emeyer> …If you have max-width and something, it could get greedy <emeyer> …So we do need something <lea> not to mention in the future <decl-value> could include <boolean> too <astearns> ack kizu <emeyer> …to be a separator <emeyer> kizu: If we’re settled on curly braces, making them necessary so we can use colon and question mark <emeyer> …If choosing between colon and question mark, I would choose colon <emeyer> …My proposal looks more like CSS in my opinion <keithamus> q? <oriol> q+ <emeyer> TabAtkins: We’d like a resolution on this grammar looking good with a quick poll on the separator value <astearns> ack fantasai <kbabbitt> q+ <emeyer> fantasai: Can we go through the questions you were debating? <lea> https://github.com//issues/10064#issuecomment-2368914947 <emeyer> lea: I think we need to consider both short and long ifs <fantasai> Separator between condition and values (? vs :) <fantasai> Separator between value if true and value if false (; vs ,/; vs :) <fantasai> Trailing separator allowed? (mainly with ; syntaxes) <fantasai> Mandatory or optional else? <fantasai> If optional: what happens if nothing matches? Empty token or IACVT? <lea> s/I think we need to consider both short and long ifs/in considering syntax options, one should think of *both* very short conditionals (possibly with a single value consisting of many of them)/ <emeyer> TabAtkins: The problem with not requiring `else` when there’s an else, you could get parsing problem <emeyer> …Lea and I decided it was okay to require the else because it’s unambiguous <keithamus> q+ <emeyer> …The subissue is whether a missing fallback else leads to empty token or IACVT <flackr> q+ <lea> lea: What is the use case for triggering IACVT intentionally? Remember if your whole value is if() you get that anyway <emeyer> astearns: We should go to the queue and then try to get resolutions for remaining questions <lea> lea: Whereas there are many use cases for getting an empty token stream <emeyer> fantasai: I would like an explkicit resolution on each of the raised questions <emeyer> astearns: If you have concerns on any of the decisions, they should be raised as separate issues <emeyer> oriol: I like the proposal of using curly braces <emeyer> …As I understand it, the curly braces would be required and we would comma-separate cases <fantasai> -> https://github.com//issues/10064#issuecomment-2373483709 <emeyer> kizu: This is correct <emeyer> TabAtkins: I’m uncomfortable with not separating cases <fantasai> s/cases/arguments in a list of arguments with a comma/ <emeyer> astearns: I suggest that become a separate issue <astearns> ack keithamus <astearns> ack oriol <astearns> ack kbabbitt <emeyer> kbabbitt: I advocated for the curly braces but I like the comma syntax looking like a declaration block <emeyer> …I lean toward comma between values, semicolon between blocks <emeyer> …I think the else should be optional <emeyer> s/optional/mandatory/ <lea> My position was: As long as else is optional, I don't think it's a big imposition to label it explicitly. <emeyer> keithamus: The question token looks strange if else is mandatory <kbabbitt> s/comma between values/colon between condition and value/ <emeyer> …The colon fits well with the grammar as I understand it <kbabbitt> s/else should be optional/else should be mandatory/ <emeyer> …Empty token vs IACVT; is the token something we can reason about? <emeyer> …If you have a custom property that evaluates to an empty token, you could reason about it with another custom property to provide a fallback <emeyer> TabAtkins: I don’t think that works, but it depends on what conditions are allowed <emeyer> keithamus: I think that should be considered <emeyer> TabAtkins: I would love to see that as an issue with a simple use case <astearns> ack flackr <emeyer> flackr: Is there an easy way to get the value that’s in the cascade before the property? <emeyer> …I can see that would be useful <emeyer> TabAtkins: I suspect the answer is, whatever style queries can do <emeyer> …SO I think not right now <emeyer> …I don’t know how much I want to divert from other queries right now <emeyer> flackr: If you didn’t specify else, and no conditions matched, we could use the value that would have been used without the custom <emeyer> TabAtkins: That runs into a proposal by Lea <emeyer> fantasai: Want to point out that colon and semicolon that follows an existing pattern we have a lot of <kizu> +1 to `if(cond(): foo; else: bar)`, this was in my other earlier comment in the issue (require mandatory `;` as a separator, not an upgradable one) <emeyer> …If we want to use commas, it probably makes more sense to use question marks <lea> https://www.irccloud.com/pastebin/4Zx0VWlX/ <lea> Option 1: ? <lea> Option 2: : <ethanjv> 2 <vmpstr> 2 <emeyer> astearns: Straw polling on separators <alisonmaher> 2 <kizu> 2 <TabAtkins> 2 <romain> 1 <lea> 1 <flackr> 2 <ydaniv> 2 <kbabbitt> 2 <fantasai> 1 <moonira> 2 <miriam> 2 <astearns> 2 <chrishtr> 2 <Penny> 2 <keithamus> 2 <jarhar> 2 <matthieud> abstain <oriol> 2. Wouldn't mind {} either <futhark> 2 <dholbert> abstain <emeyer> abstain <masonf> abstain <andreubotella> abstain <fantasai> I would be OK with `:` if we were using `;` as a separator, but `:` and `,` is weird. <dbaron> abstain <emeyer> astearns: We can decide on colon for now; are we also going to straw poll the separator? <emeyer> TabAtkins: We can <ydaniv> +1 for fantasai <ntim> I like `:` and `,` personally <emeyer> fantasai: I think commas as a separator makes sense, but pairing them with colons is weird because of the way the rest of CSS works <emeyer> …So I think they should be considered as a set <lea> Option 1: if(test? v1, v2) <lea> Option 2: if(test: v1, v2) <emeyer> …That’s what’s reading weird to me <emeyer> …In isolation, any combination is fine, but in context it’s weird to invert the precedence of these <kizu> +1 to fantasai <futhark> +1 to fantasai <emeyer> astearns: Anyone who voted 2 and is convinced by Elika’s argument? <vmpstr> +1 <emeyer> flackr: What are the options? <lea> Option 1: if(test? v1, v2) <lea> Option 2: if(test: v1, v2) <lea> 1 <TabAtkins> 1) if(cond()? foo, else? bar) <TabAtkins> 2) if(cond(): foo, else: bar) <TabAtkins> 3) if(cond(): foo; else: bar) <kizu> 3 <flackr> 3 <futhark> 3 <fantasai> 1 or 3 <TabAtkins> 2 <kbabbitt> 3 <moonira> 3 <vmpstr> 3 <astearns> 3 <keithamus> 3 <romain> 1 or 3 <ydaniv> 3 <ethanjv> 3 <dbaron> 3 <chrishtr> 3 <masonf> 3 <emeyer> astearns: Votes are according to Tab’s options <alisonmaher> 3 <miriam> 1 or 3 equally <emilio> 2 or 3 <ntim> 2 > 3 <oriol> 2 or 3 <kschmi> 3 <emeyer> 3 <emeyer> astearns: The 3’s have it <TabAtkins> winner: if(cond(): foo; else: bar) <emeyer> …We will use colons and semicolons; any objections? <emeyer> RESOLVED: We will use if(cond(): foo; else: bar) <keithamus> (regarding the decision of empty vs IACTV https://github.com//issues/10956) <emeyer> fantasai: We could resolve on mandatory else <emeyer> TabAtkins: We have to do that <emeyer> fantasai: We could resolve that if you have an else clause, you must say else explicitly <emeyer> astearns: Any objections? <emeyer> (silence) <emeyer> RESOLVED: If you have an else clause, you must say `else` explicitly <oriol> q+ <astearns> ack fantasai <emeyer> keithamus: I don’t know which one of the two options I stated in the issue should be available syntax <astearns> ack oriol <lea> IACVT if nothing matches means you cannot do things like background: if(test, yellow) if(test, linear-gradient(...) top); <emeyer> oriol: If we are going with semicolon separator between cases, are we requiring that inside curly braces?? <emeyer> fantasai: I think that’s no longer needed <lea> so you sacrifice composability, but get absolutely no advantage <emeyer> TabAtkins: I’m not sure if it’s a requirement now or not, I’ll have to think about it <emeyer> astearns: I think we’re done with this issue for today <emeyer> …Break time needed; will resume at the top of the hour |
I am happy with the After the discussion, for the remaining questions, I agree with @LeaVerou that in the One thing that was not resolved, but should be non-contentious — that the trailing |
That doesn’t make sense, since we are now not using semicolons in there at all. |
??? The resolution was indeed to go with colon-and-semicolon. |
@tabatkins Oh right, my bad! I thought we had resolved to go with regular argument separators. Hmm. So we’ll have some functions where arguments are separated by commas, some where they are separated by semicolons, and some where they use the pattern we resolved to in #9539 ? That’s …pretty weird 😕 |
No, we have |
Edits are in, please open follow-up issues for anything that still needs adjustment! Thanks! |
Edit: Resolved to pursue this! 🎉
There are several issues across this repo proposing some kind of inline conditional function. Here is a sample:
Yet, this is another case where progress has stalled because we’re trying to flesh out a much more general and powerful feature, which involves a significant amount of design & implementation effort. Meanwhile, this major author pain point remains unsolved, and authors have to resort to HTML attributes instead (as explained in #5624).
The current workarounds are:
calc(var(--test) * var(--if-true) + (1 - var(--test)) * var(--if-false))
var(--test, var(--if-false))
However, there is no workaround for transforming arbitrary keywords to arbitrary values, even simple values. E.g. custom properties like these are impossible to implement (examples inspired from the presentational attributes found in Shoelace, one of the most popular web component libraries, but similar use cases can be found in almost any design system and/or WC library):
--variant: auto | primary | success | neutral | warning | danger
--effect: none | pulse
--button-style: fill | outline
--shape: rect | pill
--avatar-shape: square | rounded | circle
--size: small | medium | large
--suffix: none | caret
`--popup-placement: [top | right | bottom | left] [start | end]?
--popup-arrow-placement: center | start | end
What if we could come up with an MVP that could be implemented fast and extended later?
We could scope it down quite a lot and still have something that addresses the most pressing author pain points.
Some example restrictions we could start with:
style( <style-query> )
conditionalsEdit (June 10th, 2024):
I had a chat with @andruud a few days ago, and he said that this proposed design would be fairly easy to implement.
Grammar:
<container-query>
<declaration-value>
I did not discuss this but a nice DX improvement could be this grammar instead:
which would allow for multiple conditions more easily. Compare:
Grammar 1:
Grammar 2:
Behavior: Any invalid value would make the property IACVT.
Does it cover enough use cases? I think so. Ideally, you'd want a mechanism to fallback to whatever value the declaration would have normally if nothing matches, instead of IACVT, but that’s much harder to implement.
Implementors, would this make it tractable? If not, what would?
The text was updated successfully, but these errors were encountered: