-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[styles] Fix getLuminance for hsl #14391
Conversation
You need to change the size in |
Does the bundle size increase worth it? Do we have an estimation of the accuracy we win? |
364f065
to
608f339
Compare
@strayiker gave an example in the related issue: #14387 (comment) It can be quite significant by the looks of it, although more relevant for our purposes would be the difference in contrast ratio between a pair of colors represented as either RGB or HSL. If we are going to make the colorManipulator API public in v4, there is another possible path forward (although @strayiker isn't going to like it 😅):
|
That seems reasonable to me. It helps with static analysis and therefore tree shaking. I don't think that it is very common to use dynamic theme colors. Themes are mostly static IMO and therefore I'd rather make use of inversion of control here. Would be nice if someone could share some use cases where color values for the theme switch dynamically between hsl and rgb. In a perfect world we would have dynamic and static solutions and users could choose: Dynamic for experimenting, static for production. |
@mbrookes I love this plan! I would like to double down on @eps1lon point. I wish we could allow our users to provide CSS variables as theme values, unfortunately, we perform some color manipulations with them. Maybe we can imagine a mode where if somebody provides a CSS variable, the color manipulation functions are identity functions? |
@mbrookes, When the
Doesn't it lead to incorrectly looking components? If you perform some color manipulations (e.g. |
|
If this difference in size is significant and worth of losing usability, then I can't argue. |
608f339
to
49c1469
Compare
@material-ui/core: parsed: +0.17% , gzip: +0.27% Details of bundle changes.Comparing: 2dedcc1...d9e99bb
|
if (process.env.NODE_ENV !== 'production') { | ||
if (!color) { | ||
throw new Error( | ||
`Material-UI: hexToRgb(color) is called with an invalid argument. (${color})`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fast feedback for wrong usages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds different behavior in production. dev and prod shouldn't behave differently.
Either throw in dev too or use warning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be fine. It will throw in development and production. The only difference is the error message. It will be explicit in dev, obscure in prod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never change control flow between environments. It is not equivalent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And even if: Why change the pattern? We always used warning
. Why switch to throw
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should answer this question first: What should happen in production when the params are invalid? We have 3 options:
- We implement a defensive logic to concern the method in a no-op.
- We do nothing, the logic breaks with an obscure error message.
- We handle the exception, provide a nice message, with minification or not. React minification logic was implemented by an intern, it's probably overkilling at our scale.
Once we have answered this question, we can consider the development env. I would propose respectively:
- We raise a warning
- / 3 We change the control flow, throw a nice warning
This problem remembers me what happen with a few of our components when none of the required props are provided. It fails with an obscure error message and a warning is print in the console:
Invariant Violation: React.cloneElement(...): The argument must be a React element, but you passed undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For new react devs I agree. But a fundamental part of react debugging is the console. We can't solve any issues devs have here because react is dictating how it should work. The error overlay you cited even includes the solution to the issue:
Open your browser’s developer console to further inspect this error.
Once we have answered this question, we can consider the development env
You always start with a premise which I don't agree with and react does not agree with and I think most other people won't agree with: Thrown errors are different in prod and dev. Why should a program behave differently in production or dev (and please don't move the goalpost to warnings they're bad enough)?
This is my 2nd attempt at focusing your attention on this point. If you insist on not discussing this I'm not willing to have a discussion about the next point either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should a program behave differently in production or dev
I'm gonna state it a 2nd time. The behavior is identical: it throws. Only the error message changes, like it changes with React invariant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The react comparison is invalid. They don't use their invariants for simple types.
The behavior is identical:
Throwing is not always equivalent. This only applies for this scenario but is generally not true for e.g. side-effects.
it throws
Also not true:
hexToRgb(1);
hexToRgb({ substr: () => {}})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'm changing the approach.
} | ||
if (!color) { | ||
warning(false, `Material-UI: missing color argument in hexToRgb(${color}).`); | ||
return color; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point it's not returning a string (unless it's an empty string) which is guaranteed by the documentation. I don't understand the use case for swallowing a TypeError here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm removing all the warnings. The discussion doesn't worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If people want meaningful errors, they can use TypeScript.
@strayiker Thank you. |
In #14391 the Function `convertHexToRGB` was renamed to `hexToRgb`. Unfortunately, the typings were not updated to reflect the above change :( Also, an additional Function was exported, `hslToRgb`, This PR updates the `hexToRgb` typings and adds an export for `hslToRgb`.
Shouldn't this change be documented in the migration guide? It renames |
Closes #14387