I'm a newbie to JS, ReactJS, and Material UI. I was following a tutorial on building a simple ReactJS webpage, but looks like the person was using Material UI v4 and now that Material UI v5 is out, a few of the APIs and tools used in the tut are outdated (withStyles, makeStyles). Around 10:46 in the video, he is showing how he is creating classes to stylize each part of the Toolbar.
I'm trying to figure out how I could accomplish the same stylizing for the Toolbar and its Typography components using that same exact structure, via injecting it with className?
My Code:
Navbar.js
import React from 'react'
import logo from '../assets/logo.svg' // imported assets for the navbar
import logoMobile from '../assets/logoMobile.svg'
import { Toolbar, Typography } from '@mui/material' // these two needed for toolbar
import { styled } from '@mui/material'
import CustomButton from './CustomButton'
const styles = styled({
bar:{ // class name
paddingTop: "1.15rem",
backgroundColor: "#fff",
['@media (max-width:780px)']:{flexMedia: "column"}, // media queries - for different devices and web-browser sizes
},
// logo: {
// width: "15%",
// ['@media (max-width:780px)']: {display: "none"},
// },
// logoMobile:{
// width: "100%",
// display: "none",
// ['@media (max-width:780px)']: {display: "inline-block"},
// },
menuItem: {
cursor: "pointer",
flexGrow: 1,
"&:hover": {color: "#4f25c8"},
['@media (max-width:780px)']: {paddingBottom: "1rem"},
}
})
function NavBar() {
const classes = styles()
return (
<Toolbar position="sticky" color="rgba(0, 0, 0, 0.87)" className={classes.bar}>
{/* <img src={logo} className={classes.logo}/>
<img src={logoMobile} className={classes.logoMobile}/> */}
<Typography variant="h5" className={classes.menuItem}>
About Me
</Typography>
<Typography variant="h5" className={classes.menuItem}>
Projects
</Typography>
<Typography variant="h5" className={classes.menuItem}>
Resume
</Typography>
<Typography variant="h5" className={classes.menuItem}>
Contact Me
</Typography>
<CustomButton txt="a test button!"></CustomButton>
</Toolbar>
)
}
export default NavBar
And here's what it ends up looking like
vs what it should look like
I tried utilizing {styled } from '@mui/material'
but I can only get the toolbar to show. But it will not apply the styling expected, from the video -- confused as to why? Also this question accomplishes the same task, but it doesn't do it the way that I'm asking about.
Because styled
create custom components with additional styles, it attaches the styles without specifying and adding class names manually.
Here is a quick example for a styled
version of your code: (live demo on: stackblitz)
First use styled
to create some custom components, in this case based on the MUI components Toolbar
and Typography
, with some styles attached to them.
// 👇 This component based on Toolbar
const MyToolbar = styled(Toolbar)(({ theme }) => ({
paddingTop: '1.15rem',
backgroundColor: '#fff',
color: 'rgba(0, 0, 0, 0.87)',
position: 'sticky',
// 👇 Optional: consider to use theme.breakpoints for this
['@media (max-width:780px)']: { flexDirection: 'column' },
}));
// 👇 This component based on Typography
const MyItem = styled(Typography)(({ theme }) => ({
cursor: 'pointer',
flexGrow: 1,
'&:hover': { color: '#4f25c8' },
// 👇 Optional: consider to use theme.breakpoints for this
['@media (max-width:780px)']: { paddingBottom: '1rem' },
}));
While the media queries works in here, perhaps consider to use the breakpoints syntax with theme
for a potentially cleaner solution.
// 👇 Optional: replaces @media line in MyToolbar
[theme.breakpoints.down('md')]: { flexDirection: 'column' }
// 👇 Optional: replaces @media line in MyItem
[theme.breakpoints.down('md')]: { paddingBottom: '1rem' }
Otherwise, if it is in some (less common) situations that theme
is not needed, then {theme}
could be omitted in styled
syntax, for example:
// 👇 Only when theme is not needed
const MyToolbar = styled(Toolbar)({
paddingTop: '1.15rem',
backgroundColor: '#fff',
color: 'rgba(0, 0, 0, 0.87)',
position: 'sticky',
['@media (max-width:780px)']: { flexDirection: 'column' },
});
// 👇 Only when theme is not needed
const MyItem = styled(Typography)({
cursor: 'pointer',
flexGrow: 1,
'&:hover': { color: '#4f25c8' },
['@media (max-width:780px)']: { paddingBottom: '1rem' },
});
After attached with styles, the components MyToolbar
and MyItem
can then be used in the output, for example:
<MyToolbar>
<MyItem variant="h5">About Me</MyItem>
<MyItem variant="h5">Projects</MyItem>
<MyItem variant="h5">Resume</MyItem>
<MyItem variant="h5">Contact Me</MyItem>
<Button>Custom Btn</Button>
</MyToolbar>
Note that the inline styles position="sticky" color="rgba(0, 0, 0, 0.87)"
does not work here, and is moved to the above styled
. If inline styles are needed, consider use the sx
prop.
Hope this will help.