What is the alternative of makeStyles for Material UI v.5 - javascript

I just started using Material UI version 5. Originally to use my custom theme's styles, I would use makestyles, but it seems that does not work in v.5. My themes are on their own component, and to import those, I used {createTheme} instead of the old {createMuiTheme}. I have my theme imported into the Parent component as usual and have it set up as <ThemeProvider theme{theme}></ThemeProvider>.
Now, on my other component, I again was trying to use useStyles, but it was not working because it is not used in version 5. I am having a hard time trying to figure out how to convert it so that it can be used in version 5. Here is some of the unfinished code I was working on:
const useStyles = makeStyles((theme) => ({
logo: {
height: "8em",
marginLeft: "0.2em",
},
tabContainer: {
marginLeft: "auto",
},
tab: {
...theme.typography.tab,
minWidth: 10,
marginRight: "50px",
opacity: 1,
"&hover": {
color: theme.palette.common.purple,
textDecoration:"none",
},
},
}));
export default function Navigation(props) {
const classes = useStyles();
const [value, setValue] = useState(0);
const handleChange = (e, value) => {
setValue(value);
};
const refreshPage = () => {
window.location.reload();
};
useEffect(() => {
switch (window.location.pathname) {
case "/":
if (value !== 0) {
setValue(0);
}
break;
default:
break;
}
}, [value]);
return (
<React.Fragment>
<ElevationScroll>
<AppBar
position="relative"
style={{
borderBottom: "2px solid black",
}}
>
<Toolbar disableGutters>
<img src={logo} alt="nasa logo" className={classes.logo}/>
<Typography variant="h1" style={{ textAlign: "center" }}>
Nasa<br></br>Photos
</Typography>
<Tabs
value={value}
onChange={handleChange}
className={classes.tabContainer}
indicatorColor="primary"
>
<Tab
className={classes.tab}
component={Link}
onClick={refreshPage}
to="/"
label="Home"
/>
</Tabs>
</Toolbar>
</AppBar>
</ElevationScroll>
</React.Fragment>
);
}
I have read about the xs property and I have also heard of the styled() through Material UI's documentation, but I am having a hard time applying it to the code that I have written and would like a push in the right direction.
So to edit what I had earlier, I am going to also add my Theme.js file as well. I thought that this has been done correctly, but again it isn't reading my tab nor my palette.
import {createTheme} from "#mui/material/styles";
const pink = "#FFC0CB";
const lightblue = "#ADD8E6";
const purple = "#800080";
const black = "#000000";
const theme = createTheme({
palette: {
common: {
pink: pink,
lightblue: lightblue,
purple: purple,
black: black
},
primary: {
main: pink,
mainGradient: "linear-gradient(to left, purple, pink)",
},
secondary: {
main: lightblue,
mainGradient: "linear-gradient(to right, lightblue, pink)"
},
},
typography: {
tab: {
fontFamily:"Orbitron",
textTransform: "none",
fontSize: "2.5rem",
color: black,
},
h1: {
fontFamily: "Orbitron",
fontSize: "2.5em"
},
h2: {
fontFamily: "Orbitron",
fontSize: "2.5em"
},
subtitle1: {
fontFamily: "Orbitron"
},
subtitle2: {
fontFamily: "Orbitron",
fontSize: "1.5rem"
},
buttons: {
fontFamily: "Orbitron",
textTransform: "none"
},
},
});
export default theme
I have imported my theme into my App.js file which is my top level file, I will include that here just in case something has been done wrong with that:
import React,{useState} from "react";
import PicOfDay from "./Components/PictureOfDay";
import Navigation from "./Components/Navigation";
import {
Typography,
} from "#mui/material";
import {ThemeProvider} from '#mui/material/styles'
import theme from "../src/ui/Theme";
import {BrowserRouter as Router} from "react-router-dom";
function App(props) {
const [date, setDate] = useState(new Date());
return (
<ThemeProvider theme={theme}>
<Router>
<Navigation date={date} setDate={setDate} />
<Typography
variant="h1"
style={{fontSize: "5rem", textAlign: "center", marginTop:"2rem"}}
>
Astronomy Picture of the Day
</Typography>
{/* <PicOfDay date={date} /> */}
</Router>
</ThemeProvider>
);
}
export default App;
I did look at some documentation a couple of you sent me, and I was looking at the troubleshooting part where it said "[Types] Property "palette", "spacing" does not exist on type 'DefaultTheme'" because makeStyles is exported differently and it does not know about Theme. There seems to be a snipet to put in a typescript project (which I am not running, I am using javascript) and there was a section to add a ts file to my javascript and put the snippet it recommended, which I tried, but am I missing something because it did not do anything and I am not sure if I need to put something in my App.js file in order for it to read that?

You can still use the makeStyles utils as what you're using, but in material v5 if you love to do it you need to install one more package #mui/styles and
import { makeStyles } from '#mui/styles';
https://mui.com/guides/migration-v4/#mui-material-styles
The makeStyles JSS utility is no longer exported from #mui/material/styles. You can use #mui/styles/makeStyles instead.
Also, you need to add tab and purple to createTheme if you need them
const theme = createTheme({
typography: {
tab: {
fontSize: 20,
},
},
palette: {
common: {
purple: 'purple',
},
},
})

Based on documentation:
#mui/styles is the legacy styling solution for MUI. It is deprecated in v5. It depends on JSS as a styling solution, which is not used in the #mui/material anymore.
You can use the-sx-prop or styled

so what i understood from this question is that you want to add custom classes to the material-ui components. and makestyles is giving you error about theme.. you can resolve this by providing default theme to makestyles. you can use ThemeProvider to do that.. all you've to do is create a default theme with createTheme() then use that in ThemeProvider to pass it to all components in tree below ThemeProvider.. just use ThemeProvider to wrap your root component and that will provide default theme to each makeStyles that are currently in use..
import { makeStyles } from '#mui/styles';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme();
const useStyles = makeStyles((theme) => (
root : {
background: theme.palette.primary.main,
}));
function Component() {
const classes = useStyles();
return <div className={classes.root} />
}
// In the root of your app
function App(props) {
return <ThemeProvider theme={theme}><Component {...props} /></ThemeProvider>;
}

import * as React from 'react';
import { StyledEngineProvider } from '#mui/material/styles';
export default function GlobalCssPriority() {
return (
<StyledEngineProvider injectFirst>
{/* Your component tree. Now you can override MUI's styles. */}
</StyledEngineProvider>
);
}
You need to use provider on main file to get default styles first.
Visit here Material UI injections!

Related

Material UI changes style of components

Every time I render component, it's keep changing styles.
import React from 'react';
import FormControl from '#material-ui/core/FormControl';
import MenuItem from '#material-ui/core/MenuItem';
import Select from '#material-ui/core/Select';
import Button from '#material-ui/core/Button';
import { makeStyles } from "#material-ui/core/styles";
import sharedTheme from '../../styling/theme.js';
import { Icon } from '#twilio/flex-ui';
import { withStyles } from '#material-ui/core/styles';
import { makeInternalCall } from './index';
import { StylesProvider } from '#material-ui/core/styles';
import { createGenerateClassName } from '#material-ui/core/styles';
const styles = theme => (sharedTheme(theme));
class InternalDialpad extends React.Component {
.........
render() {
const { classes, manager } = this.props;
const { contact_uri: worker_contact_uri } =
manager.workerClient.attributes;
return (
<div className={classes.boxDialpad}>
<div className={classes.titleAgentDialpad}>Call Agent</div>
<div className={classes.subtitleDialpad}>Select agent</div>
<FormControl className={classes.formControl}>
<Select
value={this.state.selectedWorker}
onChange={this.handleChange}
isClearable
>
{this.state.workerList.map((worker)=> {
const { activity_name } = worker;
const { contact_uri, full_name } = worker.attributes;
return (
contact_uri !== worker_contact_uri &&
activity_name !== "Offline"
) ? (
<MenuItem value={contact_uri} key={contact_uri}>
{full_name}
</MenuItem>
) : null
}
)}
</Select>
<div className={classes.buttonAgentDialpad}>
<Button
variant="contained"
color="primary"
disabled={!this.state.selectedWorker}
onClick={this.makeCall}
className={classes.dialPadBtn}
>
<Icon icon="Call"/>
</Button>
</div>
</FormControl>
</div>
)
}
}
export default withStyles(styles)(InternalDialpad);
Theme.js
const sharedTheme = (theme) => ({
root: {
flexGrow: 1,
display: "flex",
flexWrap: "wrap",
},
main:{
margin: 0,
padding: 0
},
formControl: {
width: "250px",
},
boxDialpad: {
borderTop: "1px solid #eeeeee",
},
titleAgentDialpad: {
width: "100%",
textTransform: "uppercase",
textAlign: "center",
fontWeight: "bold",
fontSize: theme.typography.fontSize,
},
subtitleDialpad: {
textTransform: "uppercase",
},
buttonAgentDialpad: {
display: "flex",
justifyContent: "center",
},
dialPadBtn: {
borderRadius: "100px",
minWidth: "0px",
}
});
Now as expected, I can see styles classes are being assigned to each elements, but as soon as I render this component , it changes it's class name or add similar class to that element with additional css styles. Not sure why it is happening.
Material UI components are native HTML elements with additional styles applied as classes in order for them to achieve the clean look that they have out of the box.
Using the component <Button /> for instance is just shorthand for the MUI custom Button component implementation, which includes a native <input type="button" />, several <div />s, and more. Look in your browser dev tools at what renders to the DOM where you imported the MUI elements in your JSX.
The styles you are adding via classes.customClassName extends that default, but is not the only styling on the element. If you need to override these defaults, you can see which classes will be added to each element during render in the API section of each MUI component's documentation.

Converting class to function React Error invalid hook call

I have been converting my class components to functions but I'm stuck on this hook error to do with my export default. I'm sure it's something simple, but I can't find the answer I'm looking for.
This is the code causing the error:
import React from 'react'
import {AppBar, Toolbar, Button, Typography, makeStyles} from '#material-ui/core'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import Menu from './Menu'
const useStyles = makeStyles((theme) => ({
header: {
backgroundColor: "#1d3834",
},
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}))
function Header(props) {
const classes = useStyles()
const renderContent = () => {
switch (props.auth) {
case null:
return
case false:
return (
<Button color="inherit" href="/signin">Sign In</Button>
)
default:
return (
<Button color="inherit" href="/api/logout">Sign Out</Button>
)
}
}
return(
<div className={classes.root}>
<AppBar position="static" className={classes.header}>
<Toolbar>
<Menu/>
<Typography variant="h6" className={classes.title} >
<Link
to={props.auth ? '/items' : '/'}
className="left brand-logo"
>
</Link>
</Typography>
{renderContent()}
</Toolbar>
</AppBar>
</div>
);
}
function mapStateToProps({auth}) {
return{ auth }
}
export default connect(mapStateToProps)(makeStyles(useStyles) (Header))
I'm hoping someone has ran into a similar issue before and would be able to give me some feedback, Thanks :)
The main issue is how you export your component. Try instead as the following:
export default connect(mapStateToProps)(Header)
You don't really need the makeStyles(useStyles) part there.
+1 suggestion - not related to the question:
This suggestion is not related to the question itself, it's just a small improvement how I like to organize makeStyles stuff in my code repository with Material-UI.
Usually I create a styles.tsx which would look like in your case as the following, placed next to your component file:
import { makeStyles } from "#material-ui/core"
const useStyles = makeStyles((theme) => ({
header: {
backgroundColor: "#1d3834",
},
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}))
export default useStyles
Then import in the component as the following:
import useStyles from "./styles"
And the usage similarly as in your component:
function Header(props) {
const classes = useStyles()
// ... rest of your component
}

Invalid prop `className` of type `object` supplied to `Card`, expected `string`

I'm currently working on a React web app using Material-UI. I've been experimenting with the Card component to see how it works. I am currently running the following code:
import React from 'react';
import Card from '#material-ui/core/Card';
import CardMedia from '#material-ui/core/CardMedia';
const useStyles = {
media: {
height: 0,
},
cardWidth: {
maxWidth: 345,
},
cardBounds: {
paddingLeft: '10px',
paddingRight: '10px',
paddingTop: '10px',
paddingBottom: '10px',
}
};
export default function ByteCard(props) {
const classes = useStyles;
return(
<div className= {classes.cardBounds}>
<Card className={classes.cardWidth}>
<CardMedia
className={classes.media}
image={props.byte.image}
title={props.byte.name}
/>
{props.byte.name}
</Card>
</div>
);
}
It's some pretty simple code for sure. However, when running this on Chrome, I get the following two error messages in the inspection console:
It seems really odd to me that the className for the div is not throwing errors but the className for the Card and CardMedia are throwing red flags. I don't see what I'm doing wrong as I think I'm using the className tag the way Material-UI is using it in their examples. Any constructive input whatsoever would be awesome as well!
Use Material-UI style hooks makeStyles
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(theme => ({
media: {
height: 0,
},
cardWidth: {
maxWidth: 345,
},
cardBounds: {
paddingLeft: '10px',
paddingRight: '10px',
paddingTop: '10px',
paddingBottom: '10px',
}
}));
const classes = useStyles();
<Card className={classes.cardWidth}>
You have to use the makeStyles hook like this:
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
yourStyle: {...}
});
export default () => {
const classes = useStyles();
return <Button className={classes.yourStyle}>Hook</Button>;
}

MUI Drawer set background color

How to simply set background color of MUI Drawer?
tried this, but doesn't work
<Drawer
style={listStyle3}
open={this.state.menuOpened}
docked={false}
onRequestChange={(menuOpened) => this.setState({menuOpened})}
/>
const listStyle3 = {
background: '#fafa00',
backgroundColor: 'red'
}
Edit: (May-21) - Material UI V4.11.1
This can be done differently in version 4.11.1 and functional components.
There's no need to use an HoC anymore. Here's how it's done:
You should use the makeStyles helper to create the hook with a definitions of the classes and use the hook to pull them out.
const useStyles = makeStyles({
list: {
width: 250
},
fullList: {
width: "auto"
},
paper: {
background: "blue"
}
});
const DrawerWrapper = () => {
const classes = useStyles();
return (
<Drawer
classes={{ paper: classes.paper }}
open={isOpen}
onClose={() => setIsOpen(false)}
>
<div
tabIndex={0}
role="button"
onClick={() => setIsOpen(true)}
classes={{ root: classes.root }}
>
{sideList}
</div>
</Drawer>
)
}
Here's a working sandbox
Edit: (Jan-19) - Material UI V3.8.3
As for the latest version asked, the way to configure the backgroundColor would be by overriding the classes.
Based on material-ui documentation here, and the css api for drawer here - This can be done by creating an object in the form of:
const styles = {
paper: {
background: "blue"
}
}
and passing it to the Drawer component:
<Drawer
classes={{ paper: classes.paper }}
open={this.state.left}
onClose={this.toggleDrawer("left", false)}
>
A working example can be seen in this codesandbox.
Don't forget to wrap your component with material-ui's withStyles HoC as mentioned here
Based on the props you used I have the reason to think that you're using a version which is lower than v1.3.1 (the last stable version) but for the next questions you'll ask, I recommend writing the version you're using.
For version lower than V1, you can change the containerStyle prop like this:
<Drawer open={true} containerStyle={{backgroundColor: 'black'}}/>
In MUI v5, you can use the sx prop to style MUI components:
<Drawer
PaperProps={{
sx: {
backgroundColor: "pink",
color: "red",
}
}}
Or use styleOverrides to define the custom styles in createTheme:
const theme = createTheme({
components: {
MuiDrawer: {
styleOverrides: {
paper: {
backgroundColor: "pink",
color: "red",
}
}
}
}
});
Material UI V4.3.2
As in this version you can change the backgroundColor by making use of makeStyles from '#material-ui/core/styles' as shown below:
import Drawer from '#material-ui/core/Drawer';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
paper: {
background: 'black',
color: 'white'
}
});
const SideDrawer = props => {
const styles = useStyles();
return (
<Drawer
anchor="right"
open={props.drawerOpen}
onClose={() => props.toggleDrawer(false)}
classes={{ paper: styles.paper }}
>
Items
</Drawer>
);
};
export default SideDrawer;
Drawer doesn't accept style props. Use classes instead
See Drawer API
If anyone's looking for how to do this conditionally for dark/light mode, you can make 2 separate classes and use a conditional to use the right one in the component. Here's an example of how to modify #Yirenkyi's answer do achieve this:
import Drawer from '#material-ui/core/Drawer';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
paperLight: {
background: 'white',
color: 'black'
},
paperDark: {
background: 'black',
color: 'white'
}
});
const SideDrawer = props => {
const userPrefersDarkMode = true; //here's your condition
const styles = useStyles();
return (
<Drawer
anchor="right"
open={props.drawerOpen}
onClose={() => props.toggleDrawer(false)}
classes={{ paper: userPrefersDarkMode ? styles.paperDark : styles.paperLight }}
>
Items
</Drawer>
);
};
export default SideDrawer;

How to override (overwrite) classes and styles in material-ui (React)

I'm using version 1.2.1 of material-ui and I'm trying to override the AppBar component to be transparent. The documentation outlines how to override styles here.
My code:
import React, { Component } from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import logo from '../Assets/logo.svg';
class NavigationBar extends Component {
render() {
const styles = {
root: {
backgroundColor: 'transparent',
boxShadow: 'none',
},
};
return (
<AppBar position={this.props.position} classes={{ root: styles.root }}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
}
export default NavigationBar;
But this yields no results. Am I trying to override wrong? Not sure where I'm going wrong here...
This answer makes #Nadun answer complete - he deserves the credit.
To override material ui classes we need to understand these things:
1. Add your styles in a const variable at the top
const styles = {
root: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
2. We need to use higher order function with "withStyles" to override material ui classes
export default withStyles(styles)(NavigationBar);
3. Now these styles are available to us as props in the render function
try doing this - console.log(this.props.classes) - you get a classes name correspoding to properties you include in styles object,
like - {root: "Instructions-root-101"}.
Add that with classes attribute
render() {
const { classes } = this.props;
return (
<AppBar classes={{ root: classes.root }}>
// Add other code here
</AppBar>
)
}
import React, { Component } from 'react';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import logo from '../Assets/logo.svg';
import { withStyles } from '#material-ui/core/styles';
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
class NavigationBar extends Component {
render() {
return (
<AppBar className={classes.transparentBar}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
}
export default withStyles(styles)(NavigationBar);
find the important part as :
backgroundColor: 'transparent !important'
refer this guide for more details: https://material-ui.com/customization/overrides/
hope this will help you
Adding to above answers, if you want to add style to some internal autogenerated element, you can do this using this syntax
<TextField className={classes.txtField}
then in the classes object, we can approach the label present inside TextField via this way
const useStyles = makeStyles((theme) => ({
txtField: {
"& label": {
padding: 23
}
}
});
import ...;
import { withStyles } from '#mui/styles';
const styles = {
transparentBar: {
backgroundColor: 'transparent !important',
boxShadow: 'none',
paddingTop: '25px',
color: '#FFFFFF'
}
};
function NavigationBar (props) {
const { classes } = props;
return (
<AppBar className={classes.transparentBar}>
<Toolbar>
<img src={logo} style={{ height: '28px' }} />
</Toolbar>
</AppBar>
);
}
export default withStyles(styles)(NavigationBar);
It works for me.
note! update MUI core version

Categories

Resources