What would be the approach to configure the material-ui theme object on the fly?
That behavior is implemented when a user clicks on the button "set docs colors" on the documentation page of the mui.
You can use theme-provider to create & provide the theme to your app. Basic code to create & provide theme is given below.
import { MuiThemeProvider } from '#material-ui/core';
import { createMuiTheme } from '#material-ui/core/styles';
import App from './App';
const theme = createMuiTheme({
palette: {
primary: {
light: '#757ce8',
main: '#3f50b5',
dark: '#002884',
contrastText: '#fff',
},
secondary: {
light: '#ff7961',
main: '#f44336',
dark: '#ba000d',
contrastText: '#000',
},
},
});
export default props => (
<MuiThemeProvider theme={theme}>
<App {...props}/>
</MuiThemeProvider>
);
where App is your main app component.
if you have multiple themes then you have to maintain a state where you will define which theme you want to provide.
import { MuiThemeProvider } from '#material-ui/core';
import React, { useState } from 'react';
import DarkTheme from './DarkTheme';
import LightTheme from './LightTheme';
import App from './App';
export default props => {
const [darkTheme, setDarkTheme] = useState(false);
return (
<MuiThemeProvider theme={darkTheme ? DarkTheme : LightTheme}>
<App
{...props}
darkTheme={darkTheme}
handleDarkThemeChanged={setDarkTheme}/>
</MuiThemeProvider>
);
};
Related
I created custom button variant and added custom stylings, the problem is that when page is loading first time custom styling not applying. Stylings applying only when page is refreshed.
I had applied custom variants to Next.js projects, but this time I'm adding to React.js project without success
materialTheme.ts
import { createTheme } from '#mui/material'
import { systemColors, systemStylingSettings } from '../globalVariables'
declare module '#mui/material/Button' {
interface ButtonPropsVariantOverrides {
containedRed: true
}
}
const theme = createTheme({
components: {
// Buttons
MuiButton: {
variants: [
{
props: { variant: 'containedRed' },
style: {
backgroundColor: systemColors.orange,
borderRadius: systemStylingSettings.borderRadius,
boxShadow: 'none',
color: '#ffffff !important',
'&:hover': {
backgroundColor: systemColors.orangeDark,
boxShadow: 'none'
}
}
}
]
}
}
})
export default theme
index.js
import React, { Suspense } from 'react'
import ReactDOM from 'react-dom'
import './index.scss'
import App from './App'
import * as serviceWorker from './serviceWorker'
import './i18n'
import { Provider } from 'react-redux'
import store from './redux/store'
import { BrowserRouter as Router } from 'react-router-dom'
import { SnackbarProvider } from 'notistack'
import { ThemeProvider } from '#mui/material'
import theme from './styles/materialTheme.ts'
ReactDOM.render(
<Suspense fallback='Loading'>
<ThemeProvider theme={theme}>
<Provider store={store}>
<Router>
<SnackbarProvider maxSnack={10}>
<App />
</SnackbarProvider>
</Router>
</Provider>
</ThemeProvider>
</Suspense>,
document.getElementById('root')
)
serviceWorker.unregister()
jobs.tsx
import { Button } from '#mui/material'
import React from 'react'
const Jobs = () => {
return (
<div>
<main>
{/* Create new job button */}
<Button variant='containedRed'>Custom style button</Button>
</main>
</div>
)
}
export default Jobs
I am trying to use MUI's createTheme and utilize the Button component. The theme is working for the entire application, however for some reason the component is throwing this error when attempt to use it.
Uncaught TypeError: color is undefined
Here is my theme.js
import { createTheme } from "#mui/material/styles";
export const theme = createTheme({
palette: {
primary: {
main: "#aa130f",
},
secondary: {
light: "#726A6A",
main: "#000000",
},
error: {
main: "#D72A2A",
},
warning: {
main: "#FC7B09",
},
info: {
light: "CDCDCD",
main: "#902020",
},
success: {
main: "#09FE00",
},
background: {
default: "#342c2c",
},
divider: "#000000" ,
text: "#000000",
overrides: {
MuiButton: {
label: {
color: "#f1#f1#f1",
}
}
}
}
});
Here is my index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./app/App";
import { ApolloClient, InMemoryCache, ApolloProvider } from "#apollo/client";
import { BrowserRouter } from "react-router-dom";
import { ThemeProvider, StyledEngineProvider } from "#mui/material/styles";
import { theme } from "./utils/theme/themes";
import { CssBaseline } from "#mui/material";
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
<CssBaseline enableColorScheme />
<BrowserRouter>
<App />
</BrowserRouter>
</StyledEngineProvider>
</ThemeProvider>
</ApolloProvider>
</React.StrictMode>,
document.getElementById("root")
);
Here is part of my component.
list.js
import {
Box,
Button
} from "#mui/material";
return(
<Box sx={{display: "flex"}}>
<NavBar />
<Box sx={{
marginTop: 5,
display: "flex",
justifyContent:"space-between"
}}>
<Button onClick={handleOpen}>Master List</Button>
<Button>Test</Button>
</Box>
</Box>
)
I have tried a few different solutions that I have seen on here but I have unable to figure out what is causing the issue. If I remove palette:{} from createTheme the theme colors are the default palette colors and the button component will work however, the app isn't the correct style. I tried overriding the Button in the createTheme and this still didn't work.
I was able to determine that the issue was the way I had defined the "text" color within createTheme.
Original theme.js
text: "#000000",
Working theme.js
text: {
primary: "#000000",
}
I think your problem is setting the wrong value in the MuiButton color style, maybe should be like this.
MuiButton: {
label: {
color: "#f1f1f1",
}
}
I used material-UI version 4 for my project. I recently changed it to version 5.5.0. But createTheme does not work properly. None of the colors and settings used in the palette apply.
next: 11.0.0
react:17.0.2
mui : 5.5.0
theme.js
import { createTheme, responsiveFontSizes } from "#mui/material/styles";
import { deepPurple, amber } from "#mui/material/colors";
import palette from './palette';
import typography from './typography';
let theme = createTheme({
palette,
typography,
zIndex: {
appBar: 1200,
drawer: 1100
}
});
// const Theme = responsiveFontSizes(theme);
export default theme;
As you can see below I used ThemeProvider in _app.js, I put the document file in the github similar to the UI material example. Do I need to do anything else?
https://github.com/mui/material-ui/blob/master/examples/nextjs/pages/_document.js
_app.js
import React from "react";
import PropTypes from 'prop-types';
import Head from 'next/head';
import dynamic from 'next/dynamic';
import { ThemeProvider } from '#mui/styles';
import CssBaseline from '#mui/material/CssBaseline';
import { CacheProvider } from '#emotion/react';
import createEmotionCache from '../theme/createEmotionCache';
import theme from "../theme"
import { wrapper } from '../_redux/store';
import MenuTop from '../_components/Sessions/menu_top';
import Footer from '../_components/Sessions/footer';
import MenuIndex from '../_components/Sessions/menu_index';
import Header from '../_components/Sessions/header';
import Snackbar from '../_components/Sessions/Snackbar';
import "../styles/404.css";
import "../styles/index.css";
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
function MyApp(props) {
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
return (
<CacheProvider value={emotionCache}>
<Head>
</Head>
<ThemeProvider theme={theme}>
<Snackbar {...pageProps.alert} />
<MenuTop/>
<Header/>
<MenuIndex/>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
<div style={{ userSelect: "none" }}>
{/* <StylesProvider jss={jss}> */}
<Component {...pageProps} />
{/* </StylesProvider> */}
<Footer/>
</div>
</ThemeProvider>
</CacheProvider>
);
}
MyApp.propTypes = {
Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
};
export default wrapper.withRedux(MyApp);
You can try to remove the zIndex in the createTheme so the theme should be work.
let theme = createTheme({
palette,
typography
});
I have created a theme in the index of my React.JS project using MUI. When I try to apply my style to my Appbar the theme does not correctly modify the menu button nor the menu itself. the button looks generic default and the menu remains white when it should match the color of the Appbar itself.
My index.tsx looks as such:
import React from "react";
import ReactDOM from "react-dom";
import AppbarTop from "./AppbarTop";
import { Router } from "react-router";
import { createBrowserHistory } from "history";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import { LocalizationProvider } from "#mui/lab";
import { createTheme } from "#mui/material";
import { ThemeProvider } from "#mui/styles";
import { StyledEngineProvider } from "#mui/material/styles";
const customHistory = createBrowserHistory();
const theme = createTheme({
palette: {
primary: {
main: "#242526"
},
secondary: {
main: "#d975d0"
},
text: {
primary: "#E4E6EB",
secondary: "#B0B3B8"
},
background: {
default: "#242526",
paper: "#242526"
}
}
});
ReactDOM.render(
<React.StrictMode>
<LocalizationProvider dateAdapter={AdapterDateFns}>
<Router history={customHistory}>
<ThemeProvider theme={theme}>
<StyledEngineProvider injectFirst>
<AppbarTop />
</StyledEngineProvider>
</ThemeProvider>
</Router>
</LocalizationProvider>
</React.StrictMode>,
document.getElementById("root")
);
My appbar.tsx looks like this:
import React from "react";
import {
AppBar,
Box,
Button,
Container,
Menu,
MenuItem,
Toolbar
} from "#mui/material";
import HomeIcon from "#mui/icons-material/Home";
import { makeStyles } from "#mui/styles";
const useStyles = makeStyles((theme?: any) => ({
appBar: {
background: theme.palette.primary.main,
height: "60px",
position: "relative"
}
}));
const AppbarTop: React.FC<{ [key: string]: any }> = () => {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState<any>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<>
<AppBar position="static" className={classes.appBar}>
<Toolbar>
<Button
id="basic-button"
aria-controls="basic-menu"
aria-haspopup="true"
aria-expanded={open ? "true" : undefined}
onClick={handleClick}
>
Dashboard
</Button>
<Menu
id="basic-menu"
anchorEl={anchorEl}
open={open}
onClose={handleClose}
MenuListProps={{
"aria-labelledby": "basic-button"
}}
>
<MenuItem onClick={handleClose}>
<HomeIcon />{" "}
</MenuItem>
</Menu>
{/*test speed dial*/}
<Container maxWidth="sm"></Container>
<Box></Box>
</Toolbar>
</AppBar>
</>
);
};
export default AppbarTop;
Can someone please explain what I am missing?
Change this line:
import { ThemeProvider } from "#mui/styles";
To:
import { ThemeProvider } from "#mui/material/styles";
Reason: There are 2 ThemeProviders here
The one from #mui/styles: This ThemeProvider does send the Theme object down via context, it works fine, you can still access it using the useTheme hook:
const theme = useTheme();
return <Box sx={{ width: 10, height: 10, bgcolor: theme.palette.primary.main }} />
The one from #mui/material/styles: This ThemeProvider is a wrapper of the above, but it also injects the theme to the StyledEngineThemeContext.Provider, which allows you to access the theme when using MUI API (sx prop/styled()). The problem here is that the Button and Menu components uses the styled() API under-the-hood so the ThemeProvider needs to be imported from #mui/material/styles to make it work.
return <Box sx={{ width: 10, height: 10, bgcolor: 'primary.main' }} />
Related answers
Difference between #mui/material/styles and #mui/styles?
Cannot use palette colors from MUI theme
MUI - makeStyles - Cannot read properties of undefined
Material UI Dark Mode
I'm trying to apply typography changes to the theme using Material UI. But object changes are not working. However, the palette is working.
I tried to make some changes to the H3 variation and also to the default font size, but none of the changes work.
However, the colors on the palette work.
App.js
import React from "react";
import "./App.css";
import Header from "./components/ui/Header";
import { ThemeProvider } from "#material-ui/styles";
import theme from "./components/ui/Theme";
function App() {
return (
<ThemeProvider theme={theme}>
<Header />
</ThemeProvider>
);
}
export default App;
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";
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,
});
}
function Header() {
return (
<ElevationScroll>
<AppBar color="primary">
<Toolbar>
<Typography variant="h3" component="h3">
Nome de teste
</Typography>
<h3>Teste</h3>
Teste
</Toolbar>
</AppBar>
</ElevationScroll>
);
}
export default Header;
Theme.js
import { createTheme } from "#material-ui/core/styles";
const arcBlue = "#0B72B9";
const arcOrange = "#FFBA60";
export default createTheme({
typography: {
fontSize: 60,
h3: {
fontWeight: 500,
},
},
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`,
},
secondary: {
main: `${arcOrange}`,
},
},
});
If anyone can help, I would be very grateful.
Solution
I was importing from:
import { ThemeProvider } from "#material-ui/styles";
However, according to the documentation, it needs to be:
import { ThemeProvider } from "#mui/material/styles";