-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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 Custom Properties (var(--foo)) in theme secondary colour causes fatal error #6135
Comments
Storybook under hood use polished.js for transforming theme colors: eg set opacity, darken color, etc.
|
CSS Custom Properties have been supported in browsers since 2014. It seems less than ideal to commit "Our CSS-in-JS library doesn't support browser standards" to documentation. |
Of course you are right. I will think about it. Maybe it is not as difficult as it seems. |
If I can help, please let me know. |
Any PR is welcome. You can try to support CSS variables yourself. 🥇 |
@Armanio did your investigations turn up anything helpful? |
@bennypowers honestly, no. Sorry. 😥 Some features can realize by native CSS (with rgba, filters, etc). But not all. It's can be a design problem and @domyen will be unhappy.
Anyway, wait for maintainers thoughts. |
Thanks for investigating @Armanio. Since it's not used much we should be able to switch it out for something more permissive without too much hassle. But I'll defer to @ndelangen and @domyen on theming decisions since they did the work, and will be maintaining our themes |
You can resolve root values of css custom properties like that:
@bennypowers where do you define your custom properties? |
I define them in a css file that's linked in The good-old-fashioned way :D |
On |
apologies, it's manager-head, not preview-head. this is my <link rel="stylesheet" href="./my-theme.css"></link> and here's my-theme.css: html,
body {
padding: 0;
margin: 0;
font-family: var(--ftr-font-family-primary);
}
html {
--ftr-font-family-primary: "proxima-nova", arial, sans-serif;
/* General */
--white: #fff;
--white-rgb: 255, 255, 255;
--black: #000;
--black-rgb: 0, 0, 0;
/* etc*/
} |
OK, if you move it to
The downside is that dynamic updates to custom properties values won't be reflected |
In my case, though, I want to theme the storybook manager. I don't need to dynamically change values later on. |
Ok, then the workaround above should work for you. The variables need to be in |
I'm not tied to polished personally, if we can find a way to make things work without polished that works with css custom properties, that'd be a win for all i think. @Armanio @bennypowers do you know of such a library? |
looks like emotion does |
We use polished to transform user-supplied colors for use in the theme. I'd love to support css-vars as well if we can. I'd be open to jettisoning polished if there was a suitable color transformation alternative or if someone can recommend another method. As far as I can tell emotion does not do color transformation by itself. Edit: More context from this comment from polished issues
|
@bennypowers can you link to docs for that? PS. can I ask what exactly the point is? I'm not asking in a bad way, I'd like to understand what improvement you're trying to get by moving JS variables into CSS? You're defining a global scope CSS variable and then referencing that global variable by name in a JS file. I'm sceptical about that being a good idea.
I'm all in favor of using standards, but JS variables are a standard as well? AFAIK there are no easy ways to read the value of a CSS custom property from JS. If that's possible, we can likely load the value, and keep using polished. Of course CSS custom properties are designed to be mutable & cascading at runtime. |
Well, you could const getCssVarVal = cssVar =>
getComputedStyle(window)
.getPropertyValue(cssVar) That's all built in to the platform, so it seems pretty easy to me, don't think you need any libraries for that.
CSS custom properties are an inherent part of CSS the web platform, so it makes sense that a web-development tool that understands them. Your question is sort of like "switch statements can be done as ternary expressions, so we don't support switch statements". So, from first principles, CSS custom properties should be supported because they are a part of the platform, just like But if you really need the kind of corporate business use case, here's one example of many: Your company's design department defines their style guide in CSS files, using CSS custom properties. You, as the developer, want to use your company's branding both in your components, but also to brand the storybook interface, so you'd like to load up the theme.css file and have it work properly, just like any other web page.
In my case, it's just a CSS value passed as a string, like any other CSS value. Please forgive errors and typos, as I don't have access to my regular machines. |
I ask because if our code is to become significantly more complex to handle CSS custom properties, we better have a good understanding of the reason. Principle aren't enough reason. What I'm trying to avoid is that we add complex code that reaches into the runtime global document namespace, does global (possible ui-thread-blocking) operations to convert 1 value to another. And the storybook maintainer team has to maintain that code forever. I'm worried that the user would be under the assumption they could change the CSS custom property's value at runtime, and those changed would be reflected in storybook's theme. (which would not be the case, we'd read the value just once). I hope you can understand my concerns. I interpret your use-case of a design system using CSS custom properties extensively and having some sort of Would you be interested in providing us with a package/library that turns Thank for your time & passion 🙇 PS. storybook runs in more platforms then the browser, it also runs in Node & React-Native. |
@domyen Which exactly kinds of color transformations do we use? Is there a chance that those usecases can be covered by |
Valid question @Hypnosphi, though I think the options of using the transforming transparency is best done using transforming rgb values to hsl is possible in JS, afaik not in CSS. |
Well you can always put the thing that you want to make half-transparent to a separate element or pseudoelement UPD: Ok that's probably what you meant by "restructuring the html in weird ways". Except for the fact that pseudoelements don't affect markup
where do we do that? BTW you can use https://github.com/postcss/postcss-color-function to transform colors in CSS. But unfortunately, it works only at compile time, so it won't work with dynamic CSS variables |
I've just gone through this document, and AFAICS there are no... https://www.w3.org/TR/css-color-4/#changes-from-3 ...in the CSS spec. There are 12 ways of defining a color, but no ways of converting 1 to another or slightly adjusting a color after it's been defined. This seems to be a staple of why css processors are so useful. That, and JS of course. All code-examples in the document from W3C about the CSS spec, are in JS. @Hypnosphi Those 3 listed above are what we use. import { darken, lighten, transparentize } from 'polished'; We also use (r,g,b,a) => `rgba(${r}, ${g}, ${b}, ${a})`; We might as well just write that, no transformation, just convenience. |
That's why you can't find it in spec And that's how you do darken/lighten using the plugin which still works despite the deprecation |
Ok, so we're actually only transforming the lightness and alpha. This should be pretty easy to achieve using CSS filters. The downside is the same as with opacity: you need a separate (pseudo)element for each color usage that you want to transform |
This comment has been minimized.
This comment has been minimized.
SO we're left with 2 scenarios for a potential fix: 1: possible side-effects and dangers:
2: possible side-effects and dangers:
Personally my vote is to NOT do option 1. I find it too fragile, too hacky for it too work for too long. Filters are also CPU & memory hogs, and sometimes cause odd buggy behavior in browser in my experience. |
Looks like a proper place for a warning |
FWIW I'm comfortable with a fix that just reads the initial value once. Just please make sure user CSS is loaded before reading the values, and documentation should be super clear on why Storybook doesn't yet fully support this built-in feature of the web platform. A later, more comprehensive fix might prefer built-in CSS filters to tooling, as @Hypnosphi suggested. Thanks for your consideration |
Cool, so we come to the consensus that the solution is: Reading the value before creating the theme just once and warning the user somehow that this is a one-off operation. @bennypowers my question still stands, would you be able to provide us with the code to do it? Preferable as an external module. Or point us to an existing solution of course. |
That's just not true. All the web platform fully works in your stories (just because they run in browser). Theming the Storybook UI itself is an additional feature which has its intrinsic limitations. For example, you can't pass gradients as backgrounds. And gradients have been a part of web standarts for quite a while. |
Right, so we agree that this CSS feature isn't supported. No big deal, I just think that should be explicit so developers are informed. @ndelangen You need something fancier than this? const getCssVarVal = cssVar =>
getComputedStyle(document.body)
.getPropertyValue(cssVar) This will return html {
--foo: black;
} |
Ok, I'm able to strip the context as well |
I'm going to bow out of this thread, since it seems to me that the discussion isn't progressing in a particularly productive direction. I really hope this fix gets in soon. Thanks all for your consideration. |
@bennypowers Code looks good to me, if that works for you, my suggestion is to use that code, when you create the theme. Putting that code into the storybook core, feels like unwise. I'll try to explain: The solution makes a lot of assumptions and have a lot of nuanced limitations.
Is this an option for you: import { create } from '@storybook/theming/create';
export default create({
base: 'light',
colorSecondary: getCssVarVal('var(--my-var, red)'),
}); This works best for everyone right? You get the support, we don't have to worry about this global render-blocking function. I'm sorry if you feel the thread was/is unproductive. |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
This is fixed in 5.2! |
Apologies for the bump, just curious to know what was changed in 5.2? Using |
It should be fixed by: |
Is this still the way to get theming working with css custom properties?
I'm using
|
Describe the bug
Using CSS variables in theme breaks storybook.
To Reproduce
Use this theme:
Expected behavior
I expect the styles to be applied.
Code snippets
System:
Additional context
You can try this yourself just by setting the secondary color prop in react dev tools under ThemeProvider
The text was updated successfully, but these errors were encountered: