Skip to content

[docs][material-ui] Improve theme.applyStyles() docs #44658

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

Merged
merged 12 commits into from
Dec 20, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ For SSR (server-side rendering) applications, Material UI can not detected user

To prevent the issue, you need to ensure that there is no usage of `theme.palette.mode === 'dark'` in your code base.

If you have such a condition, replace it with the [`theme.applyStyles()`](#appling-dark-styles) function:
If you have such a condition, replace it with the [`theme.applyStyles()` function](/material-ui/customization/dark-mode/#styling-in-dark-mode):

```diff
import Card from '@mui/material/Card';
Expand Down
17 changes: 3 additions & 14 deletions docs/data/material/customization/css-theme-variables/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ If you want to be able to manually toggle modes, see the guide to [toggling dark

## Applying dark styles

To customize styles for dark mode, use `theme.applyStyles()` function.
This utility function will return the right selector.
To customize styles for dark mode, use the [`theme.applyStyles()` function](/material-ui/customization/dark-mode/#styling-in-dark-mode).

The example below shows how to customize the Card component for dark mode:

Expand All @@ -60,24 +59,14 @@ import Card from '@mui/material/Card';
sx={(theme) => ({
backgroundColor: theme.vars.palette.background.default,
...theme.applyStyles('dark', {
boxShadow: 'none', // remove the box shadow in dark mode
backgroundColor: theme.vars.palette.grey[50],
}),
})}
/>;
```

:::warning
Do not use `theme.palette.mode` to switch between light and dark styles—this produces an [unwanted flickering effect](/material-ui/customization/dark-mode/#dark-mode-flicker).

```js
<Card
sx={{
// 🚫 this will cause flickering
backgroundColor: theme.palette.mode === 'dark' ? '…' : '…',
}}
/>
```

Do not use `theme.palette.mode` to switch between light and dark styles—this produces an [unwanted flickering effect](/material-ui/customization/css-theme-variables/configuration/#preventing-ssr-flickering).
:::

## Using theme variables
Expand Down
72 changes: 63 additions & 9 deletions docs/data/material/customization/dark-mode/dark-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,29 @@
</Button>;
```

### Codemod
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 section wasn't removed, it was just moved below

:::warning
When `cssVariables: true`, styles applied with `theme.applyStyles()` have higher specificity than those defined outside of it.
So if you need to override styles, you must also use `theme.applyStyles()` as shown below:

We provide codemods to migrate your codebase from using `theme.palette.mode` to use `theme.applyStyles()`.
You can run each codemod below or all of them at once.
```jsx
const BaseButton = styled('button')(({ theme }) =>
theme.applyStyles('dark', {
backgroundColor: 'white',
}),
);

```bash
npx @mui/codemod@latest v6.0.0/styled <path/to/folder-or-file>
npx @mui/codemod@latest v6.0.0/sx-prop <path/to/folder-or-file>
npx @mui/codemod@latest v6.0.0/theme-v6 <path/to/theme-file>
const AliceblueButton = styled(BaseButton)({
backgroundColor: 'aliceblue', // In dark mode, backgroundColor will be white as theme.applyStyles() has higher specificity
});

const PinkButton = styled(BaseButton)(({ theme }) =>
theme.applyStyles('dark', {
backgroundColor: 'pink', // In dark mode, backgroundColor will be pink
}),
);
```

> Run `v6.0.0/theme-v6` against the file that contains the custom `styleOverrides`. Ignore this codemod if you don't have a custom theme.
:::

### API

Expand All @@ -251,7 +262,50 @@
#### Arguments

- `mode` (`'light' | 'dark'`) - The mode for which the styles should be applied.
- `styles` (`CSSObject`) - An object which contains the styles to be applied for the specified mode.
- `styles` (`CSSObject`) - An object that contains the styles to be applied for the specified mode.

#### Overriding applyStyles

You can override `theme.applyStyles()` with a custom function to have complete control over it.
Please review the [source code](https://github.com/mui/material-ui/blob/HEAD/packages/mui-system/src/createTheme/applyStyles.ts) to understand how the default implementation works before overriding it.
For instance, if you need the function to return a string instead of an object so it can be used inside template literals:

```js
const theme = createTheme({
cssVariables: {
colorSchemeSelector: '.mode-%s',
},
colorSchemes: {
dark: {},
light: {},
},
applyStyles: function (key: string, styles: any) {
// return a string instead of an object
return `*:where(.mode-${key}) & {${styles}}`;
},
});

const StyledButton = styled('button')`
${theme.applyStyles(
'dark', `
background: white;
`
)}
`;
```

### Codemod

We provide codemods to migrate your codebase from using `theme.palette.mode` to use `theme.applyStyles()`.

Check warning on line 299 in docs/data/material/customization/dark-mode/dark-mode.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Google.We] Try to avoid using first-person plural like 'We'. Raw Output: {"message": "[Google.We] Try to avoid using first-person plural like 'We'.", "location": {"path": "docs/data/material/customization/dark-mode/dark-mode.md", "range": {"start": {"line": 299, "column": 1}}}, "severity": "WARNING"}
You can run each codemod below or all of them at once.

```bash
npx @mui/codemod@latest v6.0.0/styled <path/to/folder-or-file>
npx @mui/codemod@latest v6.0.0/sx-prop <path/to/folder-or-file>
npx @mui/codemod@latest v6.0.0/theme-v6 <path/to/theme-file>
```

> Run `v6.0.0/theme-v6` against the file that contains the custom `styleOverrides`. Ignore this codemod if you don't have a custom theme.

## Dark mode flicker

Expand Down
10 changes: 7 additions & 3 deletions packages/mui-system/src/createTheme/applyStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ export interface ApplyStyles<K extends string> {
*
* Tips: Use an array over object spread and place `theme.applyStyles()` last.
*
* With the styled function:
* ✅ [{ background: '#e5e5e5' }, theme.applyStyles('dark', { background: '#1c1c1c' })]
*
* 🚫 { background: '#e5e5e5', ...theme.applyStyles('dark', { background: '#1c1c1c' })}
*
* With the sx prop:
* ✅ [{ background: '#e5e5e5' }, theme => theme.applyStyles('dark', { background: '#1c1c1c' })]
* 🚫 { background: '#e5e5e5', ...theme => theme.applyStyles('dark', { background: '#1c1c1c' })}
*
* @example
* 1. using with `styled`:
* ```jsx
Expand All @@ -32,9 +36,9 @@ export interface ApplyStyles<K extends string> {
* @example
* 2. using with `sx` prop:
* ```jsx
* <Box sx={theme => [
Copy link
Member Author

@DiegoAndai DiegoAndai Dec 5, 2024

Choose a reason for hiding this comment

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

This doesn't work, sx prop doesn't accept (theme) => array as styled does.

* <Box sx={[
* { background: '#e5e5e5' },
* theme.applyStyles('dark', {
* theme => theme.applyStyles('dark', {
* background: '#1c1c1c',
* color: '#fff',
* }),
Expand Down
Loading