I am using Material-UI for a React project. However, I'm not sure as to how to apply a theme globally.
Here I have tried for individual components
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
import CardCommon from '../../common/card/CardCommon';
import purple from '#material-ui/core/colors/purple';
import Button from '#material-ui/core/Button';
import { Link } from 'react-router-dom';
//const primary = red[500]; // #F44336
import { Paths } from '../../../Routes';
const theme = createMuiTheme({
palette: {
primary: { main: purple[500] }, // Purple and green play nicely together.
secondary: { main: '#11cb5f' }, // This is just green.A700 as hex.
},
});
So how can I change the primary and secondary colors globally?
You can structure your app like this. Wrap the child components inside a MuiThemeProvider and pass a createMuiTheme object to it as a theme property value.
Also typography: {useNextVariants: true }
fixes the following error:
(Warning: Material-UI: you are using the deprecated typography variants that will be removed in the next major release.)
The official Material UI docs have more detailed information on this:
MuiThemeProvider
Color
Edit the index.js file as follows
import React from 'react';
import ReactDOM from 'react-dom';
import { MuiThemeProvider, createMuiTheme } from '#material-ui/core/styles';
import './index.css';
import App from './App';
const theme = createMuiTheme({
palette: {
primary: {
light: '#fff',
main: 'rgb(23, 105, 170)',
dark: '#000'
},
secondary: {
main: '#f44336',
},
},
typography: {
useNextVariants: true
}
});
ReactDOM.render(
<MuiThemeProvider theme = { theme }>
<App />
</MuiThemeProvider>,
document.getElementById('root')
);
Material UI Version 5 code:
import { ThemeProvider, createTheme } from '#mui/material/styles';
const themeOptions = {
palette: {
type: 'light',
primary: {
main: '#3f51b5',
},
secondary: {
main: '#f50057',
},
},
};
const theme = createTheme(themeOptions);
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
In Material UI Version 5.4, the imports should be from from '#mui/material/styles';
import { ThemeProvider, createTheme } from '#mui/material/styles';
Doc: https://mui.com/customization/theming/#api
Related
so i'm learning tailwindcss with react and I've been trying to apply different classes on the body using the useEffect hook.
I did a small configuration on my tailconfig.js
/** #type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,js}', './src/components/*.(js)'],
theme: {
extend: {},
colors: {
body: '#DCDCDC',
'selected-text': '#A3A3FF',
theme: '#3F3FFF',
nav: '#404053',
secondary: '#9191A4',
badge: '#3F3F51',
'input-border': '#565666',
input: '#2A2A35',
},
fontFamily: {
poppins: ["'Poppins'", 'sans-serif'],
},
},
plugins: [],
}
This is my App.js
import { useEffect } from 'react'
function App() {
useEffect(() => {
document.body.classList.add('text-white', 'bg-color', 'font-poppins')
// 👇️ checking if body element contains a class
if (document.body.classList.contains('font-poppins')) {
console.log('body tag contains class')
}
}, [])
return <p className="text-white">Test</p>
}
export default App
and this is my index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import AppNavbar from './components/AppNavbar'
import reportWebVitals from './reportWebVitals'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<React.StrictMode>
<AppNavbar /> //this is another component
<App />
</React.StrictMode>
)
When i start the application and check the console , the classes have been added to the body and p tags but the 'text-white' class isn't working.What am i doing wrong ?
When you put the colors or any other custom values also like fontFamily this will override tailwindcss values, that's why text-white isn't working, to fix this you need to insert your custom values inside extend like this :
extend: {
colors: {
body: "#DCDCDC",
"selected-text": "#A3A3FF",
theme: "#3F3FFF",
nav: "#404053",
secondary: "#9191A4",
badge: "#3F3F51",
"input-border": "#565666",
input: "#2A2A35",
},
fontFamily: {
poppins: ["'Poppins'", "sans-serif"],
},
},
"#mui/material": "^5.5.3"
Hi there,
I'm trying to style my MUI form using values, imported from the SCSS variables.
Everything seems to be working fine (I can see passed values in devtools) except for the colors actually never change.
Registration.tsx
import {AppDataContext} from './context/app-data-context';
import {createTheme, ThemeProvider} from '#mui/material/styles';
export const Registration = () => {
const appData = useContext(AppDataContext);
const myTheme = useMemo(() => {
const colors = appData.brandedSCSS.default;
return createTheme({
palette: {
primary: {
main: colors.primary // #fdab0a
},
secondary: {
main: colors.secondary // #ffffff
}
}
})
}, [appData])
return (
<ThemeProvider theme={myTheme}>
// some code here
</ThemeProvider>
);
Somewhere going down the components tree:
import {Button, CircularProgress, Grid} from "#mui/material";
// some code here
return (
//some code there
<Button
color="primary"
type="submit"
>
)
Theme seems to be applied correctly
but the buttons is still blue
What am I doing wrong? Thanks.
this is how i'm changing the default theme colors of mui
index.js
import { ThemeProvider } from "#mui/material"
// or import { ThemeProvider } from '#emotion/react';
import { createTheme } from '#mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#554149',
contrastText: '#fff',
},
secondary: {
main: '#00AA9C',
contrastText: '#fff',
},
info: {
main: "#906D9A",
contrastText: '#fff',
},
},
})
<ThemeProvider theme={theme}>
<App/>
</ThemeProvider>
"#mui/material": "^5.0.6",
I'm studying MUI, and in the course, the instructor asks me to style just one component and not the entire theme.
For that, it uses the makeStyles function and spreads the theme.mixins.toolbar. The problem is when I do this, I have the following error:
TypeError: Cannot read properties of undefined (reading 'toolbar')
This course is apparently in version 4, and I am using version 5. Despite this, my code appears to follow the changes that the documentations asks for. So what could be causing this error?
app.js
import "./App.css";
import Header from "./components/ui/Header";
import { ThemeProvider } from "#material-ui/core/styles";
import theme from "./components/ui/Theme";
function App() {
return (
<ThemeProvider theme={theme}>
<Header />
</ThemeProvider>
);
}
export default App;
Theme.js
import { createTheme } from "#material-ui/core/styles";
const arcBlue = "#0B72B9";
const arcOrange = "#FFBA60";
export default createTheme({
typography: {
h3: {
fontWeight: 100,
},
},
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`,
},
secondary: {
main: `${arcOrange}`,
},
},
});
header/index.jsx
import React from "react";
import AppBar from "#mui/material/AppBar";
import Toolbar from "#mui/material/Toolbar";
import useScrollTrigger from "#mui/material/useScrollTrigger";
import Typography from "#mui/material/Typography";
import { makeStyles } from "#material-ui/styles";
function ElevationScroll(props) {
const { children, window } = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
target: window ? window() : undefined,
});
return React.cloneElement(children, {
elevation: trigger ? 10 : 0,
});
}
const useStyles = makeStyles((theme) => ({
toolbarMargin: { ...theme.mixins.toolbar },
}));
function Header() {
const classes = useStyles();
return (
<React.Fragment>
<ElevationScroll>
<AppBar color="primary">
<Toolbar>
<Typography variant="h3" component="h3">
Nome de teste
</Typography>
</Toolbar>
</AppBar>
</ElevationScroll>
<div className={classes.toolBarMargin} />
</React.Fragment>
);
}
export default Header;
Since you're using v5, change your ThemeProvider, createTheme and makeStyles import path from:
import { ThemeProvider, createTheme, makeStyles } from "#material-ui/core/styles";
To:
import { ThemeProvider, createTheme } from "#mui/material/styles";
import { makeStyles } from "#mui/styles";
#material-ui/core is v4 package and #mui/material is the v5 equivalent. The API from the 2 versions are not compatible. In v5, makeStyles is also moved to a legacy package called #mui/styles, if you are using MUI v5 in a new project, you should switch completely to styled/sx API as recommended by the MUI team.
Related answers
Difference between #mui/material/styles and #mui/styles?
Cannot use palette colors from MUI theme
MUI createTheme is not properly passing theme to MUI components
I created a project on CodeSandbox and it doesn't seem the problem in code.
I guess you need to check the version of package you installed in package.json file.
Here is the link to the CodeSandbox project and you can see the console.log message on console tab.
https://codesandbox.io/s/check-makestyle-eq67m?file=/src/components/ui/Header/index.js
I faced similar issue with Can not read properties of undefined, reading refs thrown by makeStyles. In my case it was mui v5 and the issue occurred after upgrading to React 18.
In my case it turned out I had some legacy makeStyles(()=>createStyles) wrapped in a manner:
const useStyles = (minWidth: number) =>
makeStyles((theme: Theme) => ...
I had to change it to:
const useStyles =
makeStyles((theme: Theme) => ...
Perhaps it will be useful for somebody else facing the issue.
Solution
Install #mui/styles
npm install #mui/styles
Change
import { ThemeProvider, createTheme } from "#material-ui/core/styles";
To
import { ThemeProvider, createTheme } from "#mui/material/styles";
And
import { makeStyles } from "#material-ui/styles";
To
import { makeStyles } from "#mui/styles";
And
<div className={classes.toolBarMargin} />
To
<div className={classes.toolbarMargin} />
I'm trying to toggle between light and dark theme in react using a Switch from material-ui. It is happening only once in which it is toggling from dark to light theme. This is the link to the code sandbox where all the code is hosted.
With the help of console logs I can see the theme changing in console but react is not updating it.
I know react state updates are asynchronous but what is the work around I can do for this?
Here is a working code:
import React, { useState } from "react";
import { ThemeProvider, CssBaseline } from "#material-ui/core";
import darkTheme from "./Theme/darkTheme";
import lightTheme from "./Theme/lightTheme";
import PrimarySearchAppBar from "./Components/Appbar";
import { createMuiTheme } from "#material-ui/core/styles";
function App() {
const [dark, setDark] = useState(true);
const Theme = dark ? createMuiTheme(darkTheme) : createMuiTheme(lightTheme);
return (
<ThemeProvider theme={Theme}>
<CssBaseline />
<div>
<PrimarySearchAppBar thm={dark} Togglethm={setDark} />
</div>
</ThemeProvider>
);
}
export default App;
Please note the two lines that are different from your code:
import { createMuiTheme } from "#material-ui/core/styles";
...
...
const Theme = dark ? createMuiTheme(darkTheme) : createMuiTheme(lightTheme);
It appears that for the themes to work MUI needs to create the theme (using createMuiTheme on every render). I do realize you're using createMuiTheme in your theme definitions (darkTheme.js and lightTheme.js), but those are superfluous. You can safely rewrite those files like so (which is what I did in my sandbox):
const darkTheme = {
palette: {
type: "dark",
primary: {
main: "#00e676"
},
secondary: {
main: "#e6006f"
}
}
};
export default darkTheme;
Sandbox: https://codesandbox.io/s/delicate-butterfly-d8jqd?file=/src/App.js
All you have to do is to import and use createMuiTheme instead of using the theme directly and you can export the plain objects from dakTheme.js and lightTheme.js
you have to recreate theme each time the app stat changes (user toggles theme)
to avoid unnecessary reRenders of the ThemeProvider and as a result reRendering of the whole app you should use a useMemo react hook for changing the theme depending on the dark state.
App.js
import React, { useState, useMemo } from "react";
import { ThemeProvider, CssBaseline } from "#material-ui/core";
import darkTheme from "./Theme/darkTheme";
import lightTheme from "./Theme/lightTheme";
import PrimarySearchAppBar from "./Components/Appbar";
import { createMuiTheme } from "#material-ui/core";
function App() {
const [dark, setDark] = useState(true);
const Theme = useMemo(() => createMuiTheme(dark ? darkTheme : lightTheme), [dark]);
return (
<ThemeProvider theme={Theme}>
<CssBaseline />
<div>
<PrimarySearchAppBar thm={dark} Togglethm={setDark} />
</div>
</ThemeProvider>
);
}
export default App;
dartkTheme.js
const darkTheme = {
palette: {
type: "dark",
primary: {
main: "#00e676",
},
secondary: {
main: "#e6006f",
}
},
}
export default darkTheme;
lightTheme.js
const lightTheme = {
palette: {
type: "light",
primary: {
main: "#2196f3"
},
secondary: {
main: "#f50057"
}
}
};
export default lightTheme;
I'm trying to include some components from #material-ui package at my app, using the ThemeProvider at the root, but i'm having some troubles.
Other components that use styles defined locally (without theme properties) render ok.
sandbox:
https://codesandbox.io/s/theme-provider-issues-t72f3
Here is how the theme is being created:
import React from "react";
import { createMuiTheme } from "#material-ui/core/styles";
import { ThemeProvider } from "#material-ui/styles";
import { blue, white } from "#material-ui/core/colors";
function AppTheme(props) {
const theme = createMuiTheme({
palette: {
primary: blue,
text: white
}
});
return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
}
export default AppTheme;
I'm not certain what you were trying to achieve with text: white, but that created an invalid structure for your theme. theme.palette.text should be an object rather than a color, and the error was caused by Material-UI looking for theme.palette.text.primary.
Changing AppTheme.js to the following solves the problem:
import React from "react";
import { createMuiTheme } from "#material-ui/core/styles";
import { ThemeProvider } from "#material-ui/styles";
import { blue } from "#material-ui/core/colors";
const theme = createMuiTheme({
palette: {
primary: blue
}
});
function AppTheme(props) {
return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
}
export default AppTheme;
I've got another error, was fixed here