This blog post explains how to add Material UI to Docusaurus, use the MUI components, and how to combine the themes so that switching between dark and light themes affect both Docusaurus and MUI.
This post assumes you already have Docusaurus installed and started up using your favorite development environment.
Install Material UI
Install the MUI core.
npm install @mui/material @emotion/react @emotion/styled
Using Material UI Components
Once installed you can use the MUI components and other tools like normal. Import them, and use them in your .jsx
and .mdx
code. I used them to style the homepage.
import Container from "@mui/system/Container";
import Card from "@mui/material/Card";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
<Grid container justifyContent="center" sx={{ paddingBottom: 8 }}>
<Grid item xs={12}>
<Card
variant="outlined"
sx={{
textAlign: "center",
boxShadow: 3,
}}
>
<Typography variant="h4">This is an example</Typography>
</Card>
</Grid>
</Grid>;
Material UI CSS Theme Variables
For integrating MUI theme with Docusaurus, I opted for using the MUI experimental CSS Theme Variables. It allows you to create both your light and dark colors in the same theme, and switch between them using MUIs setMode
from useColorScheme
.
Create MUI Color Theme
I first created my color scheme in a file I named index.jsx
at /src/components/MuiTheme/index.jsx
. Like MUIs createTheme
, you only need to specify the variables you wish to change from default. A simplified theme is below.
import { experimental_extendTheme as extendTheme } from "@mui/material/styles";
// General MUI theme
const extTheme = extendTheme({
colorSchemes: {
light: {
palette: {
primary: {
main: "hsl(240, 48%, 47%)",
},
background: {
paper: "hsl(240, 15%, 95%)",
},
},
},
dark: {
palette: {
primary: {
main: "hsl(240, 90%, 70%)",
},
background: {
paper: "hsl(210, 3%, 15%)",
},
},
},
},
});
export default extTheme;
Applying MUI Theme to Site
We need to import the MUI theme, and wrap it around the entire website. This can be done by swizzing the <Root>
. For this, we simply create a file Root.js
at /src/theme/Root.js
. Then place the below code in that file.
import React from "react";
import { getInitColorSchemeScript } from "@mui/material/styles";
import { Experimental_CssVarsProvider as CssVarsProvider } from "@mui/material/styles";
import theme from "@site/src/components/MuiTheme";
export default function Root({ children }) {
return (
<>
{getInitColorSchemeScript()}
<CssVarsProvider theme={theme}>{children}</CssVarsProvider>
</>
);
}
Matching Docusaurus and MUI Theme
Now we need to be able to determine what color mode Docusaurus is in, and sync that with our MUI theme.
Swizzling ColorModeToggle
In order to match the color schemes, I made use of Docusaurus' swizzling feature again, to wrap their ColorModeToggle
and add my own functionality. This component is labeled "Safe" to swizzle, and wrapping is the best option. See the Docusaurus docs on Swizzling if you want more information about this functionality.
In short, the command I ran was:
npm run swizzle @docusaurus/theme-classic ColorModeToggle -- --wrap
This creates the ColorModeToggle wrapper at /src/theme/ColorModeToggle/index.js
.
Syncing the Themes
Then inside the ColorModeToggle index.js
you can add the mode switching functionality.
import React, { useEffect } from "react";
import ColorModeToggle from "@theme-original/ColorModeToggle";
import { useColorScheme } from "@mui/material/styles";
export default function ColorModeToggleWrapper(props) {
// MUI color mode setting
const { setMode } = useColorScheme();
// "value" holds the color theme. Either "light" or "dark"
const { value } = props;
// change mode based on "value" prop
// "dark" or "light" are also used for MUI
useEffect(() => {
setMode(value);
}, [value]);
return (
<>
<ColorModeToggle {...props} />
</>
);
}
Using MUI Them Elsewhere
Now that the themes sync, we can use that synced theme anywhere on the site! Including this docs and blog section. Since the entire site is wrapped in Root.js
, no extra steps are needed. You can even reference your theme variables from within the components. Below I added using the primary.main
color for the text (which changes between dark and light mode).
import Container from "@mui/system/Container";
import Card from "@mui/material/Card";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { Experimental_CssVarsProvider as CssVarsProvider } from "@mui/material/styles";
import theme from "@site/src/components/MuiTheme";
<Grid container justifyContent="center" sx={{ paddingBottom: 4 }}>
<Grid item xs={12}>
<Card
variant="outlined"
sx={{
textAlign: "center",
boxShadow: 3,
}}
>
<Typography variant="h4" sx={{ color: "primary.main" }}>
This is an example
</Typography>
</Card>
</Grid>
</Grid>;
This is an example
Try changing the color theme using the Docusaurus button. Notice how the above example changes color depending on which color theme is chosen?
Further Documentation
For further details on MUIs CSS theme variables, see their documentation.