Skip to content

Commit

Permalink
[material-ui] Refine extendTheme and CssVarsProvider API (mui#42839)
Browse files Browse the repository at this point in the history
  • Loading branch information
siriwatknp authored and joserodolfofreitas committed Jul 29, 2024
1 parent 779bc36 commit 229168a
Show file tree
Hide file tree
Showing 66 changed files with 1,572 additions and 1,161 deletions.
43 changes: 0 additions & 43 deletions docs/data/joy/customization/dark-mode/DarkModeByDefault.js

This file was deleted.

43 changes: 0 additions & 43 deletions docs/data/joy/customization/dark-mode/DarkModeByDefault.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ function Identifier() {
export default function IdentifySystemMode() {
return (
<CssVarsProvider
defaultMode="system"
// The props below are specific to this demo,
// you might not need them in your app.
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ function Identifier() {
export default function IdentifySystemMode() {
return (
<CssVarsProvider
defaultMode="system"
// The props below are specific to this demo,
// you might not need them in your app.
//
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<CssVarsProvider
defaultMode="system"
// The props below are specific to this demo,
// you might not need them in your app.
//
Expand Down
57 changes: 22 additions & 35 deletions docs/data/joy/customization/dark-mode/ModeToggle.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import * as React from 'react';
import { CssVarsProvider, useColorScheme } from '@mui/joy/styles';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';

const useEnhancedEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
import { CssVarsProvider, useColorScheme, extendTheme } from '@mui/joy/styles';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

function ModeSwitcher() {
const { mode, setMode } = useColorScheme();
Expand All @@ -18,50 +15,40 @@ function ModeSwitcher() {
return null;
}
return (
<Button
<Select
variant="soft"
color="neutral"
onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}
value={mode}
onChange={(event, newMode) => {
setMode(newMode);
}}
>
{mode === 'dark' ? 'Turn light' : 'Turn dark'}
</Button>
<Option value="system">System</Option>
<Option value="light">Light</Option>
<Option value="dark">Dark</Option>
</Select>
);
}

export default function ModeToggle() {
// the `node` is used for attaching CSS variables to this demo,
// you might not need it in your application.
const [node, setNode] = React.useState(null);
useEnhancedEffect(() => {
setNode(document.getElementById('mode-toggle'));
}, []);
const theme = extendTheme({
cssVarPrefix: 'mode-toggle',
colorSchemeSelector: '.demo_mode-toggle-%s',
});

export default function ModeToggle() {
return (
<CssVarsProvider
// the props below are specific to this demo,
// you might not need them in your app.
//
// the element to apply [data-joy-color-scheme] attribute.
colorSchemeNode={node || null}
//
// the selector to apply the CSS theme variables stylesheet.
colorSchemeSelector="#mode-toggle"
theme={theme}
//
// the local storage key to use.
modeStorageKey="mode-toggle-demo"
//
// set as root provider
disableNestedContext
>
<Box
id="mode-toggle"
sx={{
textAlign: 'center',
flexGrow: 1,
p: 2,
m: -3,
borderRadius: [0, 'sm'],
}}
>
<ModeSwitcher />
</Box>
<ModeSwitcher />
</CssVarsProvider>
);
}
57 changes: 22 additions & 35 deletions docs/data/joy/customization/dark-mode/ModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import * as React from 'react';
import { CssVarsProvider, useColorScheme } from '@mui/joy/styles';
import Box from '@mui/joy/Box';
import Button from '@mui/joy/Button';

const useEnhancedEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
import { CssVarsProvider, useColorScheme, extendTheme } from '@mui/joy/styles';
import Select from '@mui/joy/Select';
import Option from '@mui/joy/Option';

function ModeSwitcher() {
const { mode, setMode } = useColorScheme();
Expand All @@ -18,50 +15,40 @@ function ModeSwitcher() {
return null;
}
return (
<Button
<Select
variant="soft"
color="neutral"
onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}
value={mode}
onChange={(event, newMode) => {
setMode(newMode);
}}
>
{mode === 'dark' ? 'Turn light' : 'Turn dark'}
</Button>
<Option value="system">System</Option>
<Option value="light">Light</Option>
<Option value="dark">Dark</Option>
</Select>
);
}

export default function ModeToggle() {
// the `node` is used for attaching CSS variables to this demo,
// you might not need it in your application.
const [node, setNode] = React.useState<HTMLElement | null>(null);
useEnhancedEffect(() => {
setNode(document.getElementById('mode-toggle'));
}, []);
const theme = extendTheme({
cssVarPrefix: 'mode-toggle',
colorSchemeSelector: '.demo_mode-toggle-%s',
});

export default function ModeToggle() {
return (
<CssVarsProvider
// the props below are specific to this demo,
// you might not need them in your app.
//
// the element to apply [data-joy-color-scheme] attribute.
colorSchemeNode={node || null}
//
// the selector to apply the CSS theme variables stylesheet.
colorSchemeSelector="#mode-toggle"
theme={theme}
//
// the local storage key to use.
modeStorageKey="mode-toggle-demo"
//
// set as root provider
disableNestedContext
>
<Box
id="mode-toggle"
sx={{
textAlign: 'center',
flexGrow: 1,
p: 2,
m: -3,
borderRadius: [0, 'sm'],
}}
>
<ModeSwitcher />
</Box>
<ModeSwitcher />
</CssVarsProvider>
);
}
14 changes: 14 additions & 0 deletions docs/data/joy/customization/dark-mode/ModeToggle.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<CssVarsProvider
// the props below are specific to this demo,
// you might not need them in your app.
//
theme={theme}
//
// the local storage key to use.
modeStorageKey="mode-toggle-demo"
//
// set as root provider
disableNestedContext
>
<ModeSwitcher />
</CssVarsProvider>
56 changes: 11 additions & 45 deletions docs/data/joy/customization/dark-mode/dark-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,23 @@

<p class="description">Learn about the different methods for applying dark mode to a Joy UI app.</p>

## Set as default
## Media prefers-color-scheme

To set dark mode as the default for your app, add `defaultMode: 'dark'` to your `<CssVarsProvider>` wrapper component:

:::warning
When you change the `defaultMode` to another value, you must clear the local storage for it to take effect.
:::

{{"demo": "DarkModeByDefault.js"}}

For server-side applications, check out the framework setup in [the section below](#server-side-rendering) and provide the same value to the `InitColorSchemeScript` component:
Create a theme with `colorSchemeSelector: 'media'` to use `@media (prefers-color-scheme)` instead of the default `data-joy-color-scheme` attribute.

```js
<InitColorSchemeScript defaultMode="dark" />
```
import { extendTheme } from '@mui/joy/styles';

## Matching device's preference

Use `defaultMode: 'system'` to set your app's default mode to match the user's chosen preference on their device.

```jsx
import { CssVarsProvider } from '@mui/joy/styles';

<CssVarsProvider defaultMode="system">...</CssVarsProvider>;
```
const theme = extendTheme({
colorSchemeSelector: 'media',
});

For server-side applications, check out the framework setup in [the section below](#server-side-rendering) and provide the same value to the `InitColorSchemeScript` component:

```js
<InitColorSchemeScript defaultMode="system" />
function App() {
return <CssVarsProvider theme={theme}>...</CssVarsProvider>;
}
```

### Identify the system mode
## Identify the system mode

Use the `useColorScheme` React hook to check if the user's preference is in light or dark mode:

Expand All @@ -58,25 +42,7 @@ The `useColorScheme()` hook only works with components nested inside of `<CssVar

You can create a toggle component to give users the option to select between modes.

In the example below, we're using a `Button` component that calls `setMode` from the `useColorSchemes()` hook to handle the mode toggling.

```js
import { useColorScheme } from '@mui/joy/styles';
import Button from '@mui/joy/Button';

function ModeToggle() {
const { mode, setMode } = useColorScheme();
return (
<Button
variant="outlined"
color="neutral"
onClick={() => setMode(mode === 'dark' ? 'light' : 'dark')}
>
{mode === 'dark' ? 'Turn light' : 'Turn dark'}
</Button>
);
}
```
In the example below, we're using a `Select` component that calls `setMode` from the `useColorSchemes()` hook to handle the mode switching.

{{"demo": "ModeToggle.js"}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,7 @@ export default function BootstrapVariantTokens() {
}, []);

return (
<CssVarsProvider
theme={bootstrapTheme}
colorSchemeNode={node || null}
colorSchemeSelector="#bootstrap-buttons-demo"
>
<CssVarsProvider theme={bootstrapTheme} colorSchemeNode={node || null}>
<Box
id="bootstrap-buttons-demo"
sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ export default function RemoveActiveTokens() {
}, []);

return (
<CssVarsProvider
theme={theme}
colorSchemeNode={node || null}
colorSchemeSelector="#remove-active-tokens-demo"
>
<CssVarsProvider theme={theme} colorSchemeNode={node || null}>
<Box
id="remove-active-tokens-demo"
sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}
Expand Down
Loading

0 comments on commit 229168a

Please sign in to comment.