Skip to content
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

[ui] Use CSS vars for theming #21200

Merged
merged 1 commit into from
Apr 18, 2024
Merged

[ui] Use CSS vars for theming #21200

merged 1 commit into from
Apr 18, 2024

Conversation

hellendag
Copy link
Member

@hellendag hellendag commented Apr 12, 2024

Summary & Motivation

Use CSS vars instead of JS strings to set themed values.

The main benefit of this is that it will no longer require reloading the page to see the theme update: when you change the theme in User Settings, it will update immediately. Additionally, if the user's OS is set to change from light to dark (and vice versa) based on time of day, and they are using the "System" theme, the theme change should now occur automatically, without a browser reload.

I have addressed a couple of items with inline comments.

Screen.Recording.2024-04-15.at.13.14.03.mov

How I Tested These Changes

Load app, change theme. Verify that it updates right away. Click around the app, verify that everything looks correct.

Copy link
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @hellendag and the rest of your teammates on Graphite Graphite

Copy link

github-actions bot commented Apr 12, 2024

Deploy preview for dagit-storybook ready!

✅ Preview
https://dagit-storybook-pn0juh6sz-elementl.vercel.app
https://dish-theme-vars.components-storybook.dagster-docs.io

Built with commit 32d9686.
This pull request is being automatically deployed with vercel-action

Copy link

github-actions bot commented Apr 12, 2024

Deploy preview for dagit-core-storybook ready!

✅ Preview
https://dagit-core-storybook-nanzb71j0-elementl.vercel.app
https://dish-theme-vars.core-storybook.dagster-docs.io

Built with commit 32d9686.
This pull request is being automatically deployed with vercel-action

<GlobalPopoverStyle />
<GlobalDialogStyle />
<GlobalCustomAlertPortalStyle />
<GlobalSuggestStyle />
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved all of this out to StyleProvider.

@@ -633,7 +633,7 @@ const SVGViewportStyles: React.CSSProperties = {
overflow: 'hidden',
userSelect: 'none',
outline: 'none',
background: `url("data:image/svg+xml;utf8,<svg width='30px' height='30px' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'><circle fill='${Colors.lineageDots()}' cx='5' cy='5' r='5' /></svg>") repeat`,
background: `url("data:image/svg+xml;utf8,<svg width='30px' height='30px' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'><circle fill='rgba(103, 116, 138, 0.20)' cx='5' cy='5' r='5' /></svg>") repeat`,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a CSS var on the inline SVG doesn't work, and it seemed like overkill to expose the rgba values in JS. It's simplest to just put an rgba value here, and this color looks fine in both modes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a bummer, hopefully we don't run into more cases of this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see any others, but yeah, kind of sucks. We might just have to take a different approach to rendering this pattern if it does need theming after all.

@hellendag hellendag requested review from salazarm and bengotow April 15, 2024 19:12
@hellendag hellendag marked this pull request as ready for review April 15, 2024 19:12
@hellendag hellendag requested a review from braunjj April 15, 2024 19:12
Comment on lines +9 to +29
const ThemeRoot = createGlobalStyle`
@media (prefers-color-scheme: light) {
:root, .themeSystem {
${lightThemeColors}
}
}

@media (prefers-color-scheme: dark) {
:root, .themeSystem {
${darkThemeColors}
}
}

.themeLight {
${lightThemeColors}
}

.themeDark {
${darkThemeColors}
}
`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A shame this will end up a giant string including the same vars twice.
Style queries could help here https://developer.chrome.com/docs/css-ui/style-queries but the support is limited.

@@ -633,7 +633,7 @@ const SVGViewportStyles: React.CSSProperties = {
overflow: 'hidden',
userSelect: 'none',
outline: 'none',
background: `url("data:image/svg+xml;utf8,<svg width='30px' height='30px' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'><circle fill='${Colors.lineageDots()}' cx='5' cy='5' r='5' /></svg>") repeat`,
background: `url("data:image/svg+xml;utf8,<svg width='30px' height='30px' viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'><circle fill='rgba(103, 116, 138, 0.20)' cx='5' cy='5' r='5' /></svg>") repeat`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats a bummer, hopefully we don't run into more cases of this.

@hellendag
Copy link
Member Author

Pushed up a change to enable theme switching within Storybook.

image

@@ -31,35 +32,35 @@ export const Default = () => {
export const Fill = () => {
return (
<Group direction="column" spacing={8}>
<BaseButton label="Button" fillColor={CoreColors.Gray900} textColor={CoreColors.White} />
<BaseButton label="Button" fillColor={Colors.accentGray()} textColor={Colors.alwaysWhite()} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this alwaysWhite?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're currently using white in all cases for the text on toasters and filled buttons, regardless of theme, but we were previously using CoreColors.White directly to accomplish this. I added alwaysWhite() within this PR to make it a "themable" color function like the others, though we could come up with a more appropriate semantic name for it.

@hellendag hellendag force-pushed the dish/theme-vars branch 2 times, most recently from 073cdb5 to adf5737 Compare April 15, 2024 22:01
Copy link
Collaborator

@bengotow bengotow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow this is so cool. Using variables to do this is much more elegant than what I thought this would require... and it's doubly cool that this doesn't block us from imperatively using the colors in random places like style values.

Only two things I can think to check

  • the "Download SVG" button in the asset graph should copy the CSS containing the variable declarations into the SVG, but I'm not 100% sure.

  • The library we use for asset "plots" sometimes uses canvas I think? I imagine the browser still resolves the variables in the canvas context but maybe worth opening that page to verify 👀

@@ -160,7 +159,7 @@ export const intentToTextAndIconColor = (intent: BlueprintIntent) => {
if (intent === 'primary') {
return Colors.accentReversed();
}
return CoreColors.White;
return Colors.alwaysWhite();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this naming, was actually wondering just the other day whether white and black were static. 🙌

@hellendag hellendag force-pushed the dish/theme-vars branch 3 times, most recently from fc83974 to 6ad7ee8 Compare April 16, 2024 17:19
@hellendag
Copy link
Member Author

Thanks for calling those out, @bengotow! I've put fixes in places for both of those:

  • When generating the SVG for download, if the style value is a var, use the computed style instead (since we've already got it available).
  • For Chart.js, we (sadly) need the RGB values. So I created a hook (useRGBColorsForTheme) which uses the computed style on document.body to provide a mapping from var string to RGB value. It's an escape hatch that I hope we won't need to use often -- since it's pretty gross to compute back from the body style for this -- but it does the job.

[INTERNAL_BRANCH=dish/stripe-theming]
@hellendag hellendag merged commit 64ba7b8 into master Apr 18, 2024
2 of 3 checks passed
@hellendag hellendag deleted the dish/theme-vars branch April 18, 2024 16:15
nikomancy pushed a commit to nikomancy/dagster that referenced this pull request May 1, 2024
## Summary & Motivation

Use CSS vars instead of JS strings to set themed values.

The main benefit of this is that it will no longer require reloading the
page to see the theme update: when you change the theme in User
Settings, it will update immediately. Additionally, if the user's OS is
set to change from light to dark (and vice versa) based on time of day,
and they are using the "System" theme, the theme change should now occur
automatically, without a browser reload.

I have addressed a couple of items with inline comments.


https://github.com/dagster-io/dagster/assets/2823852/8e51bbce-6675-470b-b052-db7c51773bc4

## How I Tested These Changes

Load app, change theme. Verify that it updates right away. Click around
the app, verify that everything looks correct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants