Skip to content

Commit

Permalink
[docs][material-ui] Improve theme.applyStyles() docs (#44658)
Browse files Browse the repository at this point in the history
  • Loading branch information
DiegoAndai authored Dec 20, 2024
1 parent 2dacfe6 commit 4ffeaeb
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,30 +128,35 @@ 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';

function App() {
return (
<Card
sx={(theme) => ({
- sx={(theme) => ({
- backgroundColor: theme.palette.mode === 'dark' ? '#000' : '#fff',
- '&:hover': {
- backgroundColor: theme.palette.mode === 'dark' ? '#333' : '#f5f5f5',
- },
+ backgroundColor: '#fff',
+ '&:hover': {
+ backgroundColor: '#f5f5f5',
+ ...theme.applyStyles('dark', {
+ backgroundColor: '#333',
+ }),
- })}
+ sx={[
+ {
+ backgroundColor: '#fff',
+ '&:hover': {
+ backgroundColor: '#f5f5f5',
+ },
+ },
+ ...theme.applyStyles('dark', {
+ backgroundColor: '#000',
+ }),
})}
+ (theme) =>
+ theme.applyStyles('dark', {
+ backgroundColor: '#000',
+ '&:hover': {
+ backgroundColor: '#333',
+ },
+ }),
+ ]}
/>
);
}
Expand Down
28 changes: 10 additions & 18 deletions docs/data/material/customization/css-theme-variables/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,36 +48,28 @@ 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:

```js
import Card from '@mui/material/Card';

<Card
sx={(theme) => ({
backgroundColor: theme.vars.palette.background.default,
...theme.applyStyles('dark', {
boxShadow: 'none', // remove the box shadow in dark mode
sx={[
(theme) => ({
backgroundColor: theme.vars.palette.background.default,
}),
})}
(theme) =>
theme.applyStyles('dark', {
backgroundColor: theme.vars.palette.grey[900],
}),
]}
/>;
```

:::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
111 changes: 84 additions & 27 deletions docs/data/material/customization/dark-mode/dark-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,20 +186,22 @@ With the `styled` function:
```jsx
import { styled } from '@mui/material/styles';

const MyComponent = styled('div')(({ theme }) => ({
color: '#fff',
backgroundColor: theme.palette.primary.main,
...theme.applyStyles('dark', {
const MyComponent = styled('div')(({ theme }) => [
{
color: '#fff',
backgroundColor: theme.palette.primary.main,
'&:hover': {
boxShadow: theme.shadows[3],
backgroundColor: theme.palette.primary.dark,
},
},
theme.applyStyles('dark', {
backgroundColor: theme.palette.secondary.main,
}),
'&:hover': {
boxShadow: theme.shadows[3],
backgroundColor: theme.palette.primary.dark,
...theme.applyStyles('dark', {
'&:hover': {
backgroundColor: theme.palette.secondary.dark,
}),
},
}));
},
}),
]);
```

With the `sx` prop:
Expand All @@ -212,35 +214,47 @@ import Button from '@mui/material/Button';
(theme) => ({
color: '#fff',
backgroundColor: theme.palette.primary.main,
...theme.applyStyles('dark', {
backgroundColor: theme.palette.secondary.main,
}),
'&:hover': {
boxShadow: theme.shadows[3],
backgroundColor: theme.palette.primary.dark,
...theme.applyStyles('dark', {
backgroundColor: theme.palette.secondary.dark,
}),
},
}),
(theme) =>
theme.applyStyles('dark', {
backgroundColor: theme.palette.secondary.main,
'&:hover': {
backgroundColor: theme.palette.secondary.dark,
},
}),
]}
>
Submit
</Button>;
```

### Codemod
:::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 +265,50 @@ Apply styles for a specific mode.
#### 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 gain complete control over the values it returns.
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()`.
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 => [
* <Box sx={[
* { background: '#e5e5e5' },
* theme.applyStyles('dark', {
* theme => theme.applyStyles('dark', {
* background: '#1c1c1c',
* color: '#fff',
* }),
Expand Down

0 comments on commit 4ffeaeb

Please sign in to comment.