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

[material-ui] Merge CssVarsProvider into ThemeProvider #43115

Merged
merged 59 commits into from
Aug 6, 2024

Conversation

siriwatknp
Copy link
Member

@siriwatknp siriwatknp commented Jul 30, 2024

closes #43033

Summary of the change

Demo

The sandbox below demonstrates use cases for using the new ThemeProvider.

https://codesandbox.io/p/sandbox/material-ui-cra-ts-forked-6tjzq2?file=%2Fsrc%2Fdemos%2FDarkApp.tsx

Improvements

  • Some features in CssVarsProvider are independent of CSS variables.
    For example, disableTransitionOnChange, useColorScheme hook, and system preference.
    This is a demo for using these features without generating CSS variables.

@siriwatknp siriwatknp added package: material-ui Specific to @mui/material customization: theme Centered around the theming features labels Jul 30, 2024
@mui-bot
Copy link

mui-bot commented Jul 30, 2024

Netlify deploy preview

https://deploy-preview-43115--material-ui.netlify.app/

TabList: parsed: +20.17% , gzip: +15.83%
StepButton: parsed: +22.08% , gzip: +17.12%
SpeedDial: parsed: +20.48% , gzip: +15.89%
AccordionSummary: parsed: +24.57% , gzip: +18.60%
BottomNavigationAction: parsed: +24.82% , gzip: +18.66%
Masonry: parsed: +30.98% , gzip: +22.53%
Hidden: parsed: +31.42% , gzip: +22.76%
Fab: parsed: +24.41% , gzip: +18.42%
OutlinedInput: parsed: +24.33% , gzip: +18.49%
NativeSelect: parsed: +23.29% , gzip: +17.78%
CardActionArea: parsed: +24.98% , gzip: +18.74%
ButtonBase: parsed: +25.44% , gzip: +18.94%
TableSortLabel: parsed: +23.95% , gzip: +18.03%
TabScrollButton: parsed: +23.54% , gzip: +17.69%
InputBase: parsed: +26.25% , gzip: +19.28%
TimelineOppositeContent: parsed: +31.03% , gzip: +22.59%
TimelineContent: parsed: +31.09% , gzip: +22.60%
FilledInput: parsed: +24.31% , gzip: +18.39%
DialogContentText: parsed: +31.57% , gzip: +22.79%
StepContent: parsed: +27.92% , gzip: +20.59%
and 107 more changes

Bundle size report

Details of bundle changes (Toolpad)
Details of bundle changes

Generated by 🚫 dangerJS against 9c35d23

Copy link
Member

@mnajdova mnajdova left a comment

Choose a reason for hiding this comment

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

The implementation looks good, left some initial feedback.

@@ -2,20 +2,18 @@
import * as React from 'react';
import { unstable_createCssVarsProvider as createCssVarsProvider, SxProps } from '@mui/system';
import styleFunctionSx from '@mui/system/styleFunctionSx';
import extendTheme, { SupportedColorScheme, CssVarsTheme } from './extendTheme';
import createThemeWithVars, { SupportedColorScheme, CssVarsTheme } from './createThemeWithVars';
Copy link
Member

Choose a reason for hiding this comment

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

We should use the public API as much as possible, e.g. createTheme({ cssVariables: true }), as this is how users would use it.

const {
CssVarsProvider,
useColorScheme,
getInitColorSchemeScript: deprecatedGetInitColorSchemeScript,
} = createCssVarsProvider<SupportedColorScheme, typeof THEME_ID>({
themeId: THEME_ID,
theme: defaultTheme,
theme: createThemeWithVars,
Copy link
Member

Choose a reason for hiding this comment

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

What's the motivation from changing from defaultTheme to a create theme function usage? Do we plan to have two default themes, one with vars and one without?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is performance improvement. The previous behavior will create a default theme when you import the component but with this change, it will be called when the component is rendered.

Also, the previous behavior will always create a default theme even if the user passes in a custom theme. With this change, the default theme won't be created if the user provides a custom theme.

packages/mui-material/src/styles/createTheme.test.js Outdated Show resolved Hide resolved
Comment on lines +30 to +34
const theme = createTheme({
cssVariables: false,
colorSchemes: { light: true },
palette: { mode: 'dark' },
});
Copy link
Member

Choose a reason for hiding this comment

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

What should this generate, I am a bit confused. Is this even a valid input?

Copy link
Member Author

Choose a reason for hiding this comment

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

This case test a default dark app with light mode.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's similar to:

createTheme({
  cssVariables: false,
  colorSchemes: { dark: true },
  palette: { mode: 'light' },
});

Copy link
Member Author

@siriwatknp siriwatknp Aug 1, 2024

Choose a reason for hiding this comment

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

What should this generate, I am a bit confused. Is this even a valid input?

Yes, you can think of having the provided palette as the default color scheme. The reason I go with this path is to support the existing palette customization so we don't have to change much docs.

Copy link
Member

Choose a reason for hiding this comment

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

What I understand:

The palette values will continue working the same way as before, but the values will also be copied into colorSchemes

Is that correct?

If it's correct, what's the use of copying the palette values into the color schemes? In other words, how is theme.colorSchemes going to be used in our codebase or in users codebases when cssVariables: false?

Is the idea to use colorSchemes from now on and eventually stop using palette?

Copy link
Member Author

@siriwatknp siriwatknp Aug 2, 2024

Choose a reason for hiding this comment

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

The palette values will continue working the same way as before, but the values will also be copied into colorSchemes Is that correct?

Yes, that's my purpose. My intention is that the colorSchemes is a new feature to create a second and more color schemes. palette is considered a default color scheme and will continue to work at least in v6.

If it's correct, what's the use of copying the palette values into the color schemes? In other words, how is theme.colorSchemes going to be used in our codebase or in users codebases when cssVariables: false?

Got it. The ThemeProvider contains a state that store a user selected mode, a part of the theme is calculated from theme.colorSchemes[selectedMode]. For example, when user is in dark mode, the theme that passed through context will be:

{
  …theme.colorSchemes.dark,
  typography: ,
  spacing: ,
  breakpoints: ,
}

We have to do this so that it still work with apps that use values from theme.palette.* when switching between modes.

Is the idea to use colorSchemes from now on and eventually stop using palette?

"use colorSchemes from now on" Yes, but "eventually stop using palette" could be, it will be clearer in v6 when people start using it.

Copy link
Member

Choose a reason for hiding this comment

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

This makes sense to me 👌🏼

When we discuss the v7 theme structure, we can discuss the plan for theme.palette.

@@ -23,6 +56,60 @@ describe('createTheme', () => {
expect(theme.palette.secondary.main).to.equal(green.A400);
});

describe('CSS variables', () => {
it('should have a light as a default colorScheme if only `palette` is provided', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Ah nice, this means we can use the old theme structure and still have vars generated. This is great!

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that's one of the goal.

packages/mui-material/src/styles/createThemeWithVars.d.ts Outdated Show resolved Hide resolved
@mnajdova
Copy link
Member

mnajdova commented Aug 1, 2024

https://deploy-preview-43130--material-ui.netlify.app/material-ui/customization/css-theme-variables/configuration/

By the end of the guide, can we have an example we can share that has everything set up. There are quite a few things that needs to be generated as expected, e.g. setting both light and dark color schemes etc. I feel like the guide is not complete and hard to follow.

@mnajdova
Copy link
Member

mnajdova commented Aug 1, 2024

https://deploy-preview-43130--material-ui.netlify.app/material-ui/customization/css-theme-variables/overview/#colors

We are referencing some old APIs/ways to do things. Should we update this page reflecting the latest changes?

@mnajdova
Copy link
Member

mnajdova commented Aug 1, 2024

https://deploy-preview-43130--material-ui.netlify.app/material-ui/migration/migration-css-theme-variables/

Still uses the old CssVarsProvider and extendTheme in the guide

@siriwatknp
Copy link
Member Author

https://deploy-preview-43130--material-ui.netlify.app/material-ui/migration/migration-css-theme-variables/

Still uses the old CssVarsProvider and extendTheme in the guide

I am removing this page. It's considered a new feature, so I don't think migration is accurate.

@siriwatknp
Copy link
Member Author

siriwatknp commented Aug 2, 2024

https://deploy-preview-43130--material-ui.netlify.app/material-ui/customization/css-theme-variables/configuration/

By the end of the guide, can we have an example we can share that has everything set up. There are quite a few things that needs to be generated as expected, e.g. setting both light and dark color schemes etc. I feel like the guide is not complete and hard to follow.

That page is about configuring the feature. To see light and dark color schemes, I think it should be in the usage guide, I will add some example to https://deploy-preview-43130--material-ui.netlify.app/material-ui/customization/css-theme-variables/usage/.

Copy link
Member

@DiegoAndai DiegoAndai left a comment

Choose a reason for hiding this comment

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

Hey Jun! Good work, it looks like a headache-inducing task to merge these 😅 but it's looking great overall 😊

My main question about the logic is here: #43115 (comment)

packages/mui-material/src/styles/createTheme.test.js Outdated Show resolved Hide resolved
packages/mui-material/src/styles/ThemeProvider.test.tsx Outdated Show resolved Hide resolved
packages/mui-material/src/styles/createThemeWithVars.js Outdated Show resolved Hide resolved
@siriwatknp
Copy link
Member Author

@DiegoAndai My idea is to merge this PR first to release this week to test that everything is working as expected and then let the DevEx team review the docs PR, is that okay with you?

Copy link
Member

@DiegoAndai DiegoAndai left a comment

Choose a reason for hiding this comment

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

@siriwatknp that makes sense to me, I have two more questions:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
customization: theme Centered around the theming features package: material-ui Specific to @mui/material v6.x
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[material-ui] Move CssVarsProvider to ThemeProvider
4 participants