Material UI Theme Switcher for React
Here's a short post on how to create a Material-UI theme switcher for React - using React.createContext. This is based on Praveen's excellent post here... https://techinscribed.com/building-react-app-using-material-ui-with-sup…
When we're done - you should see the following React app with a simple theme toggle switcher.
First we'll create two themes: normal.js and dark.js, and place them in a themes directory below src.
import { createMuiTheme } from '@material-ui/core/styles'
import { red } from '@material-ui/core/colors'
// Normal or default theme
const theme = createMuiTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#cc4444',
},
error: {
main: red.A400,
},
background: {
default: '#f5f5f5',
},
titleBar: {
main: '#eeeeee',
contrastText: '#222222',
},
},
})
export default theme
import { createMuiTheme } from '@material-ui/core/styles'
import { red } from '@material-ui/core/colors'
// Dark theme
const theme = createMuiTheme({
palette: {
type: 'dark',
primary: {
main: '#26292C',
light: 'rgb(81, 91, 95)',
dark: 'rgb(26, 35, 39)',
contrastText: '#ffffff',
},
secondary: {
main: '#FFB74D',
light: 'rgb(255, 197, 112)',
dark: 'rgb(200, 147, 89)',
contrastText: 'rgba(0, 0, 0, 0.87)',
},
titleBar: {
main: '#555555',
contrastText: '#ffffff',
},
error: {
main: red.A400,
},
},
})
export default theme
And then a simple theme switcher component - base.js also placed in the themes directory.
import normal from './normal'
import dark from './dark'
const themes = {
normal,
dark,
}
export default function getTheme(theme) {
return themes[theme]
}
And now we'll create our CustomThemeProvider and React Context - CustomThemeProvider.js - also placed in the themes directory.
import React, { useState } from 'react'
import { ThemeProvider } from '@material-ui/core/styles'
import getTheme from './base'
// eslint-disable-next-line no-unused-vars
export const CustomThemeContext = React.createContext(
{
currentTheme: 'normal',
setTheme: null,
},
)
const CustomThemeProvider = (props) => {
// eslint-disable-next-line react/prop-types
const { children } = props
// Read current theme from localStorage or maybe from an api
const currentTheme = localStorage.getItem('appTheme') || 'normal'
// State to hold the selected theme name
const [themeName, _setThemeName] = useState(currentTheme)
// Retrieve the theme object by theme name
const theme = getTheme(themeName)
// Wrap _setThemeName to store new theme names in localStorage
const setThemeName = (name) => {
localStorage.setItem('appTheme', name)
_setThemeName(name)
}
const contextValue = {
currentTheme: themeName,
setTheme: setThemeName,
}
return (
<CustomThemeContext.Provider value={contextValue}>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</CustomThemeContext.Provider>
)
}
export default CustomThemeProvider
Here's how this looks in index.js...
import React from 'react'
import ReactDOM from 'react-dom'
import CssBaseline from '@material-ui/core/CssBaseline'
import App from './App'
import CustomThemeProvider from './themes/CustomThemeProvider'
ReactDOM.render(
<CustomThemeProvider>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<App />
</CustomThemeProvider>,
document.querySelector('#root'),
)
And then using the context in our App.js component...
export default function App() {
const classes = useStyles()
const { currentTheme, setTheme } = useContext(CustomThemeContext)
const isDark = Boolean(currentTheme === 'dark')
const handleThemeChange = (event) => {
const { checked } = event.target
if (checked) {
setTheme('dark')
} else {
setTheme('normal')
}
}
...
The entire source for this as a working 'Create React App'-based repository, including the AppBar and Toggle controls can be found here...
https://github.com/infonomic/material-ui-theme-switcher
Here are a few additional links to theme and color related resources and tools that help in creating custom Material-based themes for Material-UI
- https://material-ui.com/customization/default-theme/
- https://material-ui.com/customization/color/
- https://material.io/design/color/the-color-system.html#color-usage-and-…
- https://material.io/resources/color/#!/?view.left=0&view.right=0
- https://react-theming.github.io/create-mui-theme/
Enjoy!
Add new comment