Skip to content

Commit 3208bfe

Browse files
authored
[docs] Update CSS theme variables related content (#43130)
1 parent 8ab2137 commit 3208bfe

File tree

20 files changed

+512
-803
lines changed

20 files changed

+512
-803
lines changed

docs/.link-check-errors.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
Broken links found by `pnpm docs:link-check` that exist:
22

3-
- https://mui.com/material-ui/customization/css-theme-variables/configuration/#advanced-configuration
4-
- https://mui.com/material-ui/customization/css-theme-variables/configuration/#changing-variable-prefixes
53
- https://mui.com/material-ui/customization/theme-components/#creating-new-component-variants
64
- https://mui.com/material-ui/customization/theme-components/#overrides-based-on-props
75
- https://mui.com/material-ui/react-grid2/#whats-changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import * as React from 'react';
2+
import { createTheme, ThemeProvider, useColorScheme } from '@mui/material/styles';
3+
import Stack from '@mui/material/Stack';
4+
import MenuItem from '@mui/material/MenuItem';
5+
import Switch from '@mui/material/Switch';
6+
import Select from '@mui/material/Select';
7+
import FormControlLabel from '@mui/material/FormControlLabel';
8+
9+
const theme = createTheme({
10+
cssVariables: {
11+
colorSchemeSelector: '.demo-disable-transition-%s',
12+
},
13+
colorSchemes: { dark: true },
14+
});
15+
16+
function ModeSwitcher() {
17+
const { mode, setMode } = useColorScheme();
18+
if (!mode) {
19+
return null;
20+
}
21+
return (
22+
<Select
23+
value={mode}
24+
onChange={(event) => setMode(event.target.value)}
25+
sx={{ minWidth: 120 }}
26+
>
27+
<MenuItem value="system">System</MenuItem>
28+
<MenuItem value="light">Light</MenuItem>
29+
<MenuItem value="dark">Dark</MenuItem>
30+
</Select>
31+
);
32+
}
33+
34+
export default function DisableTransitionOnChange() {
35+
const [disableTransition, setDisableTransition] = React.useState(false);
36+
return (
37+
<ThemeProvider
38+
theme={theme}
39+
disableNestedContext
40+
disableTransitionOnChange={disableTransition}
41+
>
42+
<Stack
43+
sx={{
44+
width: '100%',
45+
borderRadius: '4px',
46+
p: 2,
47+
gap: 2,
48+
display: 'flex',
49+
justifyContent: 'center',
50+
alignItems: 'center',
51+
bgcolor: 'background.default',
52+
color: 'text.primary',
53+
transition: '1s',
54+
}}
55+
>
56+
<ModeSwitcher />
57+
<FormControlLabel
58+
control={
59+
<Switch
60+
checked={disableTransition}
61+
onChange={(event) => setDisableTransition(event.target.checked)}
62+
/>
63+
}
64+
label="Disable transition"
65+
/>
66+
</Stack>
67+
</ThemeProvider>
68+
);
69+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import * as React from 'react';
2+
import { createTheme, ThemeProvider, useColorScheme } from '@mui/material/styles';
3+
import Stack from '@mui/material/Stack';
4+
import MenuItem from '@mui/material/MenuItem';
5+
import Switch from '@mui/material/Switch';
6+
import Select from '@mui/material/Select';
7+
import FormControlLabel from '@mui/material/FormControlLabel';
8+
9+
const theme = createTheme({
10+
cssVariables: {
11+
colorSchemeSelector: '.demo-disable-transition-%s',
12+
},
13+
colorSchemes: { dark: true },
14+
});
15+
16+
function ModeSwitcher() {
17+
const { mode, setMode } = useColorScheme();
18+
if (!mode) {
19+
return null;
20+
}
21+
return (
22+
<Select
23+
value={mode}
24+
onChange={(event) =>
25+
setMode(event.target.value as 'system' | 'light' | 'dark')
26+
}
27+
sx={{ minWidth: 120 }}
28+
>
29+
<MenuItem value="system">System</MenuItem>
30+
<MenuItem value="light">Light</MenuItem>
31+
<MenuItem value="dark">Dark</MenuItem>
32+
</Select>
33+
);
34+
}
35+
36+
export default function DisableTransitionOnChange() {
37+
const [disableTransition, setDisableTransition] = React.useState(false);
38+
return (
39+
<ThemeProvider
40+
theme={theme}
41+
disableNestedContext
42+
disableTransitionOnChange={disableTransition}
43+
>
44+
<Stack
45+
sx={{
46+
width: '100%',
47+
borderRadius: '4px',
48+
p: 2,
49+
gap: 2,
50+
display: 'flex',
51+
justifyContent: 'center',
52+
alignItems: 'center',
53+
bgcolor: 'background.default',
54+
color: 'text.primary',
55+
transition: '1s',
56+
}}
57+
>
58+
<ModeSwitcher />
59+
<FormControlLabel
60+
control={
61+
<Switch
62+
checked={disableTransition}
63+
onChange={(event) => setDisableTransition(event.target.checked)}
64+
/>
65+
}
66+
label="Disable transition"
67+
/>
68+
</Stack>
69+
</ThemeProvider>
70+
);
71+
}

docs/data/material/customization/css-theme-variables/configuration.md

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
To change the default variable prefix (`--mui`), provide a string to `cssVarPrefix` property, as shown below:
88

99
```js
10-
extendTheme({ cssVarPrefix: 'any' });
10+
createTheme({ cssVariables: { cssVarPrefix: 'any' } });
1111

1212
// generated stylesheet:
1313
// --any-palette-primary-main: ...;
@@ -16,7 +16,7 @@ extendTheme({ cssVarPrefix: 'any' });
1616
To remove the prefix, use an empty string as a value:
1717

1818
```js
19-
extendTheme({ cssVarPrefix: '' });
19+
createTheme({ cssVariables: { cssVarPrefix: '' } });
2020

2121
// generated stylesheet:
2222
// --palette-primary-main: ...;
@@ -29,9 +29,11 @@ To toggle between modes manually, set the `colorSchemeSelector` with one of the
2929
<codeblock>
3030

3131
```js class
32-
extendTheme({
32+
createTheme({
3333
colorSchemes: { light: true, dark: true },
34-
colorSchemeSelector: 'class'
34+
cssVariables: {
35+
colorSchemeSelector: 'class'
36+
}
3537
});
3638

3739
// CSS Result
@@ -40,9 +42,11 @@ extendTheme({
4042
```
4143

4244
```js data
43-
extendTheme({
45+
createTheme({
4446
colorSchemes: { light: true, dark: true },
45-
colorSchemeSelector: 'data'
47+
cssVariables: {
48+
colorSchemeSelector: 'data'
49+
}
4650
});
4751

4852
// CSS Result
@@ -52,9 +56,11 @@ extendTheme({
5256

5357
```js string
5458
// The value must start with dot (.) for class or square brackets ([]) for data
55-
extendTheme({
59+
createTheme({
5660
colorSchemes: { light: true, dark: true },
57-
colorSchemeSelector: '.theme-%s'
61+
cssVariables: {
62+
colorSchemeSelector: '.theme-%s'
63+
}
5864
});
5965

6066
// CSS Result
@@ -66,44 +72,13 @@ extendTheme({
6672

6773
Then, use `useColorScheme` hook to switch between modes:
6874

69-
<codeblock>
70-
71-
```jsx client-side-app
72-
import { useColorScheme } from '@mui/material/styles';
73-
74-
function ModeSwitcher() {
75-
const { mode, setMode } = useColorScheme();
76-
77-
return (
78-
<select
79-
value={mode}
80-
onChange={(event) => {
81-
setMode(event.target.value);
82-
// For TypeScript, cast `event.target.value as 'light' | 'dark' | 'system'`:
83-
}}
84-
>
85-
<option value="system">System</option>
86-
<option value="light">Light</option>
87-
<option value="dark">Dark</option>
88-
</select>
89-
);
90-
}
91-
```
92-
93-
```jsx server-side-app
75+
```jsx
9476
import { useColorScheme } from '@mui/material/styles';
9577

9678
function ModeSwitcher() {
9779
const { mode, setMode } = useColorScheme();
98-
const [mounted, setMounted] = React.useState(false);
9980

100-
React.useEffect(() => {
101-
setMounted(true);
102-
}, []);
103-
104-
if (!mounted) {
105-
// for server-side rendering
106-
// learn more at https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch
81+
if (!mode) {
10782
return null;
10883
}
10984

@@ -123,10 +98,8 @@ function ModeSwitcher() {
12398
}
12499
```
125100

126-
</codeblock>
127-
128101
:::success
129-
The mode will be `system` by default to follow the user's preference.
102+
After React hydrates the tree, the mode is set to `system` to follow the user's preference.
130103
:::
131104

132105
### Determining the system mode
@@ -190,7 +163,13 @@ Next, if you have a custom selector that is **not** `media`, add the `InitColorS
190163
The `attribute` has to be the same as the one you set in the `colorSchemeSelector` property:
191164

192165
```js
193-
<InitColorSchemeScript attribute=".mode-%s" />
166+
createTheme({
167+
cssVariables: {
168+
colorSchemeSelector: 'class'
169+
}
170+
})
171+
172+
<InitColorSchemeScript attribute="class" />
194173
```
195174

196175
:::
@@ -204,17 +183,21 @@ import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
204183

205184
export default function RootLayout(props) {
206185
return (
207-
<html lang="en">
186+
<html lang="en" suppressHydrationWarning>
208187
<body>
209188
{/* must come before the <main> element */}
210-
<InitColorSchemeScript attribute=".mode-%s" />
211-
<main>{props.children}</main>
189+
<InitColorSchemeScript attribute="class" />
190+
<main>{children}</main>
212191
</body>
213192
</html>
214193
);
215194
}
216195
```
217196

197+
:::warning
198+
If you don't add `suppressHydrationWarning` to your `<html>` tag, you will see warnings about `"Extra attributes from the server"` because `InitColorSchemeScript` updates that element.
199+
:::
200+
218201
### Next.js Pages Router
219202

220203
Add the following code to the custom [`pages/_document.js`](https://nextjs.org/docs/pages/building-your-application/routing/custom-document) file:
@@ -226,11 +209,11 @@ import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
226209
export default class MyDocument extends Document {
227210
render() {
228211
return (
229-
<Html data-color-scheme="light">
212+
<Html>
230213
<Head>...</Head>
231214
<body>
232215
{/* must come before the <Main> element */}
233-
<InitColorSchemeScript attribute=".mode-%s" />
216+
<InitColorSchemeScript attribute="class" />
234217
<Main />
235218
<NextScript />
236219
</body>
@@ -249,7 +232,7 @@ import * as React from 'react';
249232
import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
250233

251234
export function onRenderBody({ setPreBodyComponents }) {
252-
setPreBodyComponents([<InitColorSchemeScript attribute=".mode-%s" />]);
235+
setPreBodyComponents([<InitColorSchemeScript attribute="class" />]);
253236
}
254237
```
255238

@@ -289,12 +272,12 @@ In the example below, all the components inside the `div` will always be dark:
289272

290273
## Disabling CSS color scheme
291274

292-
By default, the `extendTheme` attach [CSS color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) based on the palette mode. If you want to disable it, set `disableCssColorScheme` to `true`:
275+
By default, `createTheme` attaches a [CSS `color-scheme` property](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) based on the palette mode.
276+
You can disable this by setting `disableCssColorScheme` to `true`:
293277

294278
```js
295-
extendTheme({
296-
colorSchemes: { light: true, dark: true },
297-
disableCssColorScheme: true,
279+
createTheme({
280+
cssVariables: { disableCssColorScheme: true },
298281
});
299282
```
300283

@@ -312,8 +295,10 @@ The generated CSS will not include the `color-scheme` property:
312295

313296
## Instant transition between color schemes
314297

315-
To disable CSS transition when switching between modes, use `disableTransitionOnChange` prop:
298+
To disable CSS transitions when switching between modes, apply the `disableTransitionOnChange` prop:
316299

317300
```js
318-
<CssVarsProvider disableTransitionOnChange />
301+
<ThemeProvider disableTransitionOnChange />
319302
```
303+
304+
{{"demo": "DisableTransitionOnChange.js"}}

0 commit comments

Comments
 (0)