Skip to content

Commit

Permalink
[docs] Update CSS theme variables related content (#43130)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored Aug 20, 2024
1 parent 8ab2137 commit 3208bfe
Show file tree
Hide file tree
Showing 20 changed files with 512 additions and 803 deletions.
2 changes: 0 additions & 2 deletions docs/.link-check-errors.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
Broken links found by `pnpm docs:link-check` that exist:

- https://mui.com/material-ui/customization/css-theme-variables/configuration/#advanced-configuration
- https://mui.com/material-ui/customization/css-theme-variables/configuration/#changing-variable-prefixes
- https://mui.com/material-ui/customization/theme-components/#creating-new-component-variants
- https://mui.com/material-ui/customization/theme-components/#overrides-based-on-props
- https://mui.com/material-ui/react-grid2/#whats-changed
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as React from 'react';
import { createTheme, ThemeProvider, useColorScheme } from '@mui/material/styles';
import Stack from '@mui/material/Stack';
import MenuItem from '@mui/material/MenuItem';
import Switch from '@mui/material/Switch';
import Select from '@mui/material/Select';
import FormControlLabel from '@mui/material/FormControlLabel';

const theme = createTheme({
cssVariables: {
colorSchemeSelector: '.demo-disable-transition-%s',
},
colorSchemes: { dark: true },
});

function ModeSwitcher() {
const { mode, setMode } = useColorScheme();
if (!mode) {
return null;
}
return (
<Select
value={mode}
onChange={(event) => setMode(event.target.value)}
sx={{ minWidth: 120 }}
>
<MenuItem value="system">System</MenuItem>
<MenuItem value="light">Light</MenuItem>
<MenuItem value="dark">Dark</MenuItem>
</Select>
);
}

export default function DisableTransitionOnChange() {
const [disableTransition, setDisableTransition] = React.useState(false);
return (
<ThemeProvider
theme={theme}
disableNestedContext
disableTransitionOnChange={disableTransition}
>
<Stack
sx={{
width: '100%',
borderRadius: '4px',
p: 2,
gap: 2,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
bgcolor: 'background.default',
color: 'text.primary',
transition: '1s',
}}
>
<ModeSwitcher />
<FormControlLabel
control={
<Switch
checked={disableTransition}
onChange={(event) => setDisableTransition(event.target.checked)}
/>
}
label="Disable transition"
/>
</Stack>
</ThemeProvider>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import * as React from 'react';
import { createTheme, ThemeProvider, useColorScheme } from '@mui/material/styles';
import Stack from '@mui/material/Stack';
import MenuItem from '@mui/material/MenuItem';
import Switch from '@mui/material/Switch';
import Select from '@mui/material/Select';
import FormControlLabel from '@mui/material/FormControlLabel';

const theme = createTheme({
cssVariables: {
colorSchemeSelector: '.demo-disable-transition-%s',
},
colorSchemes: { dark: true },
});

function ModeSwitcher() {
const { mode, setMode } = useColorScheme();
if (!mode) {
return null;
}
return (
<Select
value={mode}
onChange={(event) =>
setMode(event.target.value as 'system' | 'light' | 'dark')
}
sx={{ minWidth: 120 }}
>
<MenuItem value="system">System</MenuItem>
<MenuItem value="light">Light</MenuItem>
<MenuItem value="dark">Dark</MenuItem>
</Select>
);
}

export default function DisableTransitionOnChange() {
const [disableTransition, setDisableTransition] = React.useState(false);
return (
<ThemeProvider
theme={theme}
disableNestedContext
disableTransitionOnChange={disableTransition}
>
<Stack
sx={{
width: '100%',
borderRadius: '4px',
p: 2,
gap: 2,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
bgcolor: 'background.default',
color: 'text.primary',
transition: '1s',
}}
>
<ModeSwitcher />
<FormControlLabel
control={
<Switch
checked={disableTransition}
onChange={(event) => setDisableTransition(event.target.checked)}
/>
}
label="Disable transition"
/>
</Stack>
</ThemeProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
To change the default variable prefix (`--mui`), provide a string to `cssVarPrefix` property, as shown below:

```js
extendTheme({ cssVarPrefix: 'any' });
createTheme({ cssVariables: { cssVarPrefix: 'any' } });

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

```js
extendTheme({ cssVarPrefix: '' });
createTheme({ cssVariables: { cssVarPrefix: '' } });

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

```js class
extendTheme({
createTheme({
colorSchemes: { light: true, dark: true },
colorSchemeSelector: 'class'
cssVariables: {
colorSchemeSelector: 'class'
}
});

// CSS Result
Expand All @@ -40,9 +42,11 @@ extendTheme({
```

```js data
extendTheme({
createTheme({
colorSchemes: { light: true, dark: true },
colorSchemeSelector: 'data'
cssVariables: {
colorSchemeSelector: 'data'
}
});

// CSS Result
Expand All @@ -52,9 +56,11 @@ extendTheme({

```js string
// The value must start with dot (.) for class or square brackets ([]) for data
extendTheme({
createTheme({
colorSchemes: { light: true, dark: true },
colorSchemeSelector: '.theme-%s'
cssVariables: {
colorSchemeSelector: '.theme-%s'
}
});

// CSS Result
Expand All @@ -66,44 +72,13 @@ extendTheme({

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

<codeblock>

```jsx client-side-app
import { useColorScheme } from '@mui/material/styles';

function ModeSwitcher() {
const { mode, setMode } = useColorScheme();

return (
<select
value={mode}
onChange={(event) => {
setMode(event.target.value);
// For TypeScript, cast `event.target.value as 'light' | 'dark' | 'system'`:
}}
>
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
);
}
```

```jsx server-side-app
```jsx
import { useColorScheme } from '@mui/material/styles';

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

React.useEffect(() => {
setMounted(true);
}, []);

if (!mounted) {
// for server-side rendering
// learn more at https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch
if (!mode) {
return null;
}

Expand All @@ -123,10 +98,8 @@ function ModeSwitcher() {
}
```

</codeblock>

:::success
The mode will be `system` by default to follow the user's preference.
After React hydrates the tree, the mode is set to `system` to follow the user's preference.
:::

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

```js
<InitColorSchemeScript attribute=".mode-%s" />
createTheme({
cssVariables: {
colorSchemeSelector: 'class'
}
})

<InitColorSchemeScript attribute="class" />
```

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

export default function RootLayout(props) {
return (
<html lang="en">
<html lang="en" suppressHydrationWarning>
<body>
{/* must come before the <main> element */}
<InitColorSchemeScript attribute=".mode-%s" />
<main>{props.children}</main>
<InitColorSchemeScript attribute="class" />
<main>{children}</main>
</body>
</html>
);
}
```

:::warning
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.
:::

### Next.js Pages Router

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

export function onRenderBody({ setPreBodyComponents }) {
setPreBodyComponents([<InitColorSchemeScript attribute=".mode-%s" />]);
setPreBodyComponents([<InitColorSchemeScript attribute="class" />]);
}
```

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

## Disabling CSS color scheme

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`:
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.
You can disable this by setting `disableCssColorScheme` to `true`:

```js
extendTheme({
colorSchemes: { light: true, dark: true },
disableCssColorScheme: true,
createTheme({
cssVariables: { disableCssColorScheme: true },
});
```

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

## Instant transition between color schemes

To disable CSS transition when switching between modes, use `disableTransitionOnChange` prop:
To disable CSS transitions when switching between modes, apply the `disableTransitionOnChange` prop:

```js
<CssVarsProvider disableTransitionOnChange />
<ThemeProvider disableTransitionOnChange />
```

{{"demo": "DisableTransitionOnChange.js"}}
Loading

0 comments on commit 3208bfe

Please sign in to comment.