MUI createTheme is not properly passing theme to MUI components - javascript

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

Related

How do I make a reusable component for the Cards and how can I use the new makeStyles of material-ui?

In the demo.js, I wanted to use the Card along with its CardHeader and put wordings inside the CardContent. Also, I will be using the CardComponent in other files as well. How can I make the CardComponent reusable?
Sample codes: https://codesandbox.io/s/basiccard-material-demo-forked-kkshx?file=/demo.js
Below are the codes for the demo.js:
import * as React from "react";
import CardComponent from "./CardComponent";
export default function BasicCard() {
return (
<>
<h1>Hello</h1>
<CardComponent />
</>
);
}
Below are the codes for the CardComponent:
import React from "react";
import Card from "#mui/material/Card";
import CardContent from "#mui/material/CardContent";
import { CardHeader } from "#mui/material";
const CardComponent = () => {
const CardStyle = {
maxWidth: 500,
margin: "0 auto",
marginBottom: "1rem",
marginTop: "1rem"
};
return (
<Card sx={{ minWidth: 275 }} elevation={5} style={CardStyle}>
<CardHeader title="Card Header Title here" />
<CardContent>//content here</CardContent>
</Card>
);
};
export default CardComponent;
I have another question as well under this component. Coming from material-ui4, mui5 was kind of confusing as I can no longer use the makeStyles. I tried adding this in the codesandbx example, however, it will say that dependency not found:
import { makeStyles } from '#mui/styles';
Hence, I settled with const CardStyle. Any help on how can I implement the newer version of the makeStyles? Also, do I need to install other dependecies from material-ui to make it work? Below is the package.json file.
Also in: https://www.reddit.com/r/reactjs/comments/sgqhh3/how_do_i_make_a_reusable_component_for_the_cards/
You can make it reusable adding props to your child card component. You can add as many props you want to make different cards using the same pattern.
To give styles to the component in mui v5 you have to use styled. You have to import it from #mui/material/styles
Here is the whole code of the new card component
import React from "react";
import {styled} from "#mui/material/styles"
import Card from "#mui/material/Card";
import CardContent from "#mui/material/CardContent";
import { CardHeader } from "#mui/material";
const StyledCard = styled((props) => (
<Card
{...props}
/>
))(({ theme }) => ({
maxWidth: 500,
margin: "0 auto",
marginBottom: "1rem",
marginTop: "1rem"
}));
const CardComponent = (props) => {
const {title,content}=props
return (
<StyledCard sx={{ minWidth: 275 }} elevation={5}>
<CardHeader title={title} />
<CardContent>{content}</CardContent>
</StyledCard>
);
};
export default CardComponent;
And here it is the whole codesandbox.

Material-UI theme remove after page refreash

I am facing a problem with my custom theme, whenever i refreshes my
page my custom theme for Tabs and Button in Navbar disappears,
sometime it doesn't even loads the Tabs and estimate button custom
theme.
Also in Header.js file code it says theme is not used but i am using
it in makeStyle function. (theme is declared on line-2 of Header.js).
Following are my code File:
Header.js
import React, {useState} from 'react'
import theme from "./Theme";
import { makeStyles } from '#mui/styles';
import {AppBar, Box, Button, Tab, Tabs, Typography, useScrollTrigger} from "#mui/material";
import {Toolbar} from "#mui/material";
import logo from '../../assets/logo.svg'
function ElevationScroll(props) {
const { children} = props;
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0
});
return React.cloneElement(children, {
elevation: trigger ? 4 : 0,
});
}
const useStyles = makeStyles(theme=> ({
toolbarMargin: {
...theme.mixins.toolbar,
marginBottom:"3em"
},
companylogo:{
height:"7em"
},
tabName:{
marginLeft:"auto",
},
tab:{
...theme.typography.tab,
minWidth:10,
marginLeft:"25px",
color:"white"
},
estimateButton:{
...theme.typography.estimateButton,
height:"45px",
borderRadius:"25px",
marginLeft:"25px",
marginRight:"25px"
},
}))
function Navbar(){
const classes = useStyles();
const[value,setValue]=useState(0);
const handleChange=(e,value)=>
{
setValue(value);
}
return(
<React.Fragment>
<ElevationScroll>
<AppBar position={"fixed"}>
<Toolbar disableGutters={true}>
<img alt="company logo" className={classes.companylogo} src={logo} />
<Tabs className={classes.tabName} value={value} onChange={handleChange}>
<Tab className={classes.tab} label={"Home"}/>
<Tab className={classes.tab} label={"Services"}/>
<Tab className={classes.tab} label={"The Revolution"}/>
<Tab className={classes.tab} label={"About Us"}/>
<Tab className={classes.tab} label={"Contact Us"}/>
</Tabs>
<Button variant={"contained"} color={"secondary"} className={classes.estimateButton}>Free Estimate</Button>
</Toolbar>
</AppBar>
</ElevationScroll>
<div className={classes.toolbarMargin}/>
</React.Fragment>
);
}
export default Navbar;
Theme.js File:
import {createTheme} from "#mui/material/styles";
const arcBlue="#0B75B9";
const arcOrange="#FFA500";
const Theme = createTheme({
palette: {
primary: {
main: `${arcBlue}`
},
secondary: {
main: `${arcOrange}`
}
},
typography: {
tab:{
fontFamily:"Raleway",
fontWeight:1000,
fontSize:"1rem",
textTransform:"none",
color:"white"
},
estimateButton:{
fontFamily:"Raleway",
textTransform:"none",
fontWeight:700,
fontSize:"1rem",
height:"45px",
color:"white"
},
}
});
export default Theme;
App.js File:
import React from "react";
import Navbar from "../components/ui/header";
import {ThemeProvider} from "#mui/material/styles";
import theme from "./ui/Theme";
function App() {
return (
<>
<ThemeProvider theme={theme}>
<Navbar/>
</ThemeProvider>
</>
);
}
export default App;

material-ui : enable the dark mode automatically

As per the documentation:
It says dark mode theme will be generated automatically and get reflected in UI, but it is not working for me.
Dependencies:
"#emotion/styled": "^11.0.0",
"#material-ui/core": "^5.0.0-alpha.16",
"#material-ui/icons": "^5.0.0-alpha.15",
"#material-ui/lab": "^5.0.0-alpha.16",
Code:
import { createMuiTheme } from "#material-ui/core/styles";
import { CssBaseline, ThemeProvider, useMediaQuery } from "#material-ui/core";
import { green, purple } from "#material-ui/core/colors";
import { useEffect, useMemo } from "react";
import { Route, Switch, useHistory } from "react-router-dom";
import SignIn from "./ui/auth/SignIn.js";
import SignUp from "./ui/auth/SignUp.js";
import Welcome from "./ui/auth/Welcome.js";
import { log } from "./util/logger.js";
const App = () => {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = useMemo(
() => {
log(prefersDarkMode, "Dark Mode");
const themeOptions = {
palette: {
type: prefersDarkMode ? 'dark' : 'light',
primary: purple,
secondary: green
},
}
log(JSON.stringify(themeOptions), "Theme Option")
const theme = createMuiTheme(themeOptions);
log(theme, "Theme");
return theme;
},
[prefersDarkMode],
);
const history = useHistory()
useEffect(() => {
const timer = setTimeout(() => {
history.push("/signin");
}, 3000);
return function cleanup() {
clearTimeout(timer);
};
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Switch>
<Route path="/" component={Welcome} exact />
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
</Switch>
</ThemeProvider>
);
}
export default App;
Signup.js
import React, { useState } from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Grid from '#material-ui/core/Grid';
import Box from '#material-ui/core/Box';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import ForgotPassword from './ForgotPassword';
import { useHistory } from 'react-router-dom';
const Copyright = () => {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</Link>
{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
background: theme.palette.background.default
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
const SignIn = () => {
const classes = useStyles();
const history = useHistory();
// Forgot Password State
const [open, setOpen] = useState(false);
function openForgotPassword(event) {
event.preventDefault();
setOpen(true);
}
function onClose() {
setOpen(false);
}
function goToSignUp(event) {
event.preventDefault();
history.push('/signup');
}
return (
<Container component="main" maxWidth="xs">
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" onClick={openForgotPassword} variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" onClick={goToSignUp} variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={8}>
<Copyright />
</Box>
<ForgotPassword open={open} onClose={onClose} />
</Container>
);
}
export default SignIn;
Background is not getting dark with the type. Can someone help with this?
My bad. The latest version of Material UI now uses mode attribute of palette to determine whether dark mode or not. Simply change from 'type' to 'mode':
// Enabling Dark Mode according to system-wide setting
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = useMemo(
() => createMuiTheme({
palette: {
mode: prefersDarkMode ? 'dark' : 'light',
primary: purple,
secondary: green
},
}),
[prefersDarkMode],
);
Complete code of App.js:
import { createMuiTheme, CssBaseline, ThemeProvider, useMediaQuery } from "#material-ui/core";
import { green, purple } from "#material-ui/core/colors";
import { useEffect, useMemo } from "react";
import { Route, Switch, useHistory } from "react-router-dom";
import SignIn from "./ui/auth/SignIn.js";
import SignUp from "./ui/auth/SignUp.js";
import Welcome from "./ui/auth/Welcome.js";
const App = () => {
// Enabling Dark Mode according to system-wide setting
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = useMemo(
() => createMuiTheme({
palette: {
mode: prefersDarkMode ? 'dark' : 'light',
primary: purple,
secondary: green
},
}),
[prefersDarkMode],
);
const history = useHistory()
useEffect(() => {
// After displaying Welcome screen for 3 seconds
// go to SignIn page
const timer = setTimeout(() => {
history.push("/signin");
}, 3000);
return function cleanup() {
clearTimeout(timer);
};
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Switch>
<Route path="/" component={Welcome} exact />
<Route path="/signin" component={SignIn} />
<Route path="/signup" component={SignUp} />
</Switch>
</ThemeProvider>
);
}
export default App;
With the newer version of Material UI, you need to use createTheme and not createMuiTheme
https://material-ui.com/customization/palette/#user-preference
import React from 'react';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import { createTheme, ThemeProvider } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = React.useMemo(
() =>
createTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return (
<ThemeProvider theme={theme}>
<CssBaseline/>
<Routes />
</ThemeProvider>
);
}

Drawer is overlapping Navbar in react material ui app, do you know how to change?

I want to let the drawer disappear behind my navbar when it is opened. Currently, the drawer is overlaying the navbar. I tried to change it with z-index in my "styles" but apparently it does not work (see screenshot). I set the z-index for the navbar higher than for the drawer.
Can you identify my mistake?
Here is the drawer.js:
import React from "react";
import clsx from "clsx";
import { makeStyles, useTheme } from "#material-ui/core/styles";
import Drawer from "#material-ui/core/Drawer";
const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
},
drawer: {
width: drawerWidth,
zIndex: 400,
flexShrink: 0,
/*whiteSpace: "nowrap",*/
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
And here is my navbar.js:
// import packages
import React, { useContext, Fragment } from "react";
import { Link } from "react-router-dom";
// import local dependenceis
import Logo from "./images/tubot_logo.png";
import AuthContext from "../../Context/Auth/authContext";
// import material-ui
import withStyles from "#material-ui/core/styles/withStyles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
// styling
const styles = (theme) => {
return {
root: {
flexGrow: 1,
zIndex: 2000,
},
title: {
flexGrow: 1,
fontFamily: "shadowsintolight",
textDecoration: "none",
color: "black",
},
};
const Navbar = (props) => {
// destructuring: styling props
const {
root,
title,
} = props.classes;
// react: return jsx
return (
<div className={root}>
<AppBar position="absolute" >
<Toolbar>
/*some navbar stuff*/
</Toolbar>
</AppBar>
</div>
);
};
Try setting the classes prop on your Drawer component like this:
const App = () => {
const classes = useStyles();
return (
<div className="App" className={root}>
<AppBar position="absolute">
<Toolbar>
// Toolbar content...
</Toolbar>
</AppBar>
<Drawer
variant="persistent"
anchor="left"
open={true}
classes={{
paper: classes.drawer,
}}>
// Drawer content...
</Drawer>
</div>
);
};

How to store a function into a store variable?

In a component, i want that my variable from the store is equal a function in order to use it.
I create my function like that:
makeStyles(theme => ({
root: {
flexGrow: 1
},
title: {
flexGrow: 1
}
}));
It is a function from material-ui.
And i get the value like that in my store:
this.state = {
classes: makeStyles()
};
So i'm expected that i can use it like: this.state.classes.root but i don't works (it compile but don't works)
Thats my code:
import React, { Component } from "react";
import { makeStyles } from "#material-ui/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import Typography from "#material-ui/core/Typography";
makeStyles(theme => ({
root: {
flexGrow: 1
},
title: {
flexGrow: 1
}
}));
class Navbar extends Component {
constructor() {
super();
this.state = {
classes: makeStyles()
};
}
render() {
return (
<div className={this.state.classes.root}>
<AppBar position="static">
<Toolbar className="red">
// for example, here i would like to use it like: this.state.classes.root
<div className="blue">
<IconButton edge="start" color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
</div>
<div className="green">
<Button color="inherit">Login</Button>
</div>
</Toolbar>
</AppBar>
</div>
);
}
}
const mapStateToProps = state => {
return {
access_token: state.access_token
};
};
export default withRouter(connect(mapStateToProps)(Navbar));
Instead of
<Toolbar className="red">
I would like to have:
<Toolbar className={this.state.classes.root}>
How should I go about doing this?
To use JavaScript values, you have do this way:
<Toolbar className={this.state.classes.root}>
Check by changing your code as:
(Changes are commented in CAPITAL)
import React, { Component } from "react";
import { makeStyles } from "#material-ui/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import Typography from "#material-ui/core/Typography";
// INITIALIZE THE makeStyles INTO ANOTHER VARIABLE, HERE I USED useStyles
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
title: {
flexGrow: 1
}
}));
class Navbar extends Component {
constructor() {
super();
// NOW CALL useStyles IN THE state
this.state = {
classes: useStyles()
};
}
render() {
return (
<div className={this.state.classes.root}>
<AppBar position="static">
<Toolbar className="red">
// for example, here i would like to use it like: this.state.classes.root
<div className="blue">
<IconButton edge="start" color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
</div>
<div className="green">
<Button color="inherit">Login</Button>
</div>
</Toolbar>
</AppBar>
</div>
);
}
}
const mapStateToProps = state => {
return {
access_token: state.access_token
};
};
export default withRouter(connect(mapStateToProps)(Navbar));
Please comment if in case you face any problem in implementing the solution.
I suggest using the Material-UI styles Hook API. Here's their short-form example:
import React from 'react';
import { makeStyles } from '#material-ui/styles';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
border: 0,
borderRadius: 3,
boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
color: 'white',
height: 48,
padding: '0 30px',
},
});
export default function Hook() {
const classes = useStyles();
return <Button className={classes.root}>Hook</Button>;
}
Your code would look like the following. Note I've converted it to a functional component so it can use Hooks.
import React, { Component } from "react";
import { makeStyles } from "#material-ui/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles({
root: {
flexGrow: 1
},
title: {
flexGrow: 1
}
});
function NavBar({access_token}) {
const classes = useStyles();
render() {
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar className="red">
<div className={classes.root}>
<IconButton edge="start" color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
</div>
<div className="green">
<Button color="inherit">Login</Button>
</div>
</Toolbar>
</AppBar>
</div>
);
}
}
const mapStateToProps = state => {
return {
access_token: state.access_token
};
};
export default withRouter(connect(mapStateToProps)(Navbar));
It doesn't work because you assign the this.state.classes.root value to className, I guess you intended to assign it to style?

Categories

Resources