changing background color in drawer - MUI - reactjs

i cannot change backgroundColor in Drawer component. I do as I found in other refs and it is not working for me. I created two classes
import { makeStyles } from '#mui/styles'
import { Drawer, Typography } from '#mui/material';
const drawerWidth = 240;
const useStyles = makeStyles({
drawer: {
width: drawerWidth,
},
drawerPaper: {
width: drawerWidth,
backgroundColor: "#fcba03"
},
});
export default function Sidebar() {
const classes=useStyles()
return (
<>
<Drawer
className={classes.drawer}
variant="permanent"
anchor="left"
classes={{paper: classes.drawerPaper},
{root:classes.drawerRoot}}
>
<div>
<Typography variant='h5'> Home </Typography>
</div>
</Drawer>
</>
)
}
thanks for answer!

You're not passing the classes in correct way. The classes prop expects an object with keys containing the class names from makeStyle hook. The correct syntax should be like
classes={{ paper: classes.drawerPaper, root: classes.drawerRoot }}
The updated code could be
import { makeStyles } from "#mui/styles";
import { Drawer, Typography } from "#mui/material";
const drawerWidth = 240;
const useStyles = makeStyles({
drawer: {
width: drawerWidth
},
drawerPaper: {
"&&": {
width: drawerWidth,
backgroundColor: "#fcba03"
}
}
});
export default function Sidebar() {
const classes = useStyles();
return (
<>
<Drawer
className={classes.drawer}
variant="permanent"
anchor="left"
classes={{ paper: classes.drawerPaper, root: classes.drawerRoot }}
>
<div>
<Typography variant="h5"> Home </Typography>
</div>
</Drawer>
</>
);
}
Note: && is added to increase the specificity of the applied styles to the paper.
Also, the support of makeStyles is going to be a legacy solution at sometime in future. If possible, you should probably look at the newer styling option provided in the mui v5.

Yes, this "improved" props like p, px, my, bgcolor etc are on the component listed above, but MUI expose for each of their components, a sx prop, that is an object that accept this kind of prop ! Also, I don't know if it could help, but you still can customize MUI components from the theme object if you want this style to be applied on all components occurences

Related

MUI Theme hook version 5 : creating global theme

I'm trying to create a theme for my Next.JS application with MUI version 5. I created the Theme in my layout component, and I expected the Theme to have effect in other child components. but I can't seem to get my Button to change from the default primary colour. It does work with the "h1"tag, and I'm wondering why it works for the h1 tag and not for the Button component.
//layout component
import { AppBar, Container, CssBaseline, Toolbar, Typography ,createTheme, ThemeProvider} from '#mui/material';
import useStyles from '../utils/styles';
export default function Layout({ title, children, description }) {
const theme = createTheme({
typography: {
h1: {
fontSize: '1.6rem',
fontWeight: 400,
margin: '1rem 0', // this is working
},
h2: {
fontSize: '1.4rem',
fontWeight: 400, // this is working
margin: '1rem 0',
},
palette: {
type: 'light',
primary: { // this is not working
main: '#f0c000',
},
secondary: {
main: '#208080',
},
},
},
});
const classes = useStyles()
return (
<div>
<ThemeProvider theme={theme}>
<CssBaseline/>
<AppBar position="static" className={classes.navbar}>
<Toolbar>
<Typography>App</Typography>
</Toolbar>
</AppBar>
<Container className={classes.main}>{children}</Container>
<footer className={classes.footer}>
<Typography>All right reserved</Typography>
</footer>
</ThemeProvider>
</div>
);
}
Component where I want to use the Theme :
import useStyles from '../../utils/styles'
import { useTheme } from '#mui/material';
export default function ButtonScreen() {
const theme = useTheme();
const classes = useStyles();
return (
// this h1 tag responds to the Theme style provided in the layout component
<Typography component="h1" variant="h1">
Button Action
</Typography>
//The button default colour still persist, even with the theme in place.
<Button fullWidth variant='contained' color="primary">Click me</Button>
)
}
Can someone help me figure out what I am missing here?!

target pseudo selectors in material ui

I'm wondering if there's a way to target psedo selectors (::before, ::after) in material ui?
For example, in a component like this?
const useStyles = makeStyles((theme) => ({
root: {
textAlign: 'center',
'&::before': {
content: '"blabla"'
},
'&::after': {
content: '"blabla"'
},
':before': {},
after: {}
}
}));
function App(props) {
const classes = useStyles();
return (
<Typography
className={{ root: classes.root, before: classes.before, after: classes.after }}>
{props.children}
</Typography>
);
}
I have created this sandbox project, you can check, things are working fine or correct me if I am missing something to understand your problem
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles(theme => ({
root: {
textAlign: "center",
"&::before": {
content: '"-"'
},
"&::after": {
content: '"-"'
}
}
}));
export default function App(props) {
const classes = useStyles();
return (
<Typography className={classes.root} {...props}>
Hello
</Typography>
);
}
I think you are using the className props in a wrong way, you have to pass the string, not an object.
classes props expect an object, we generally use classes props on the component which have exposed class names to override their inner styles, for example in case of Typography Component you can override root element style like this.
export default function App(props) {
const classes = useStyles();
return (
<Typography classes={{ root: classes.root }} {...props}>
Hello
</Typography>
);
}
so classes and classNames are two different things in Material-UI, but sometimes(when you want to apply the style to root element of component) both provide the same solution.
I have created one more Sandbox project with the second solution

How to override anchor <a> element in material ui v3?

I have tried to override the in typography with
root: {
'&a':{
color: '#FF6600'
},
},
but didn't work any suggestions ?
There are multiple ways to change the color(style) of Material-UI <Typography /> locally.
Mostly been used options would be considered as:
Add style based on the provided CSS API - refer to MUI Typography API document
Override style using the nesting selector for elements and classes - you can find the details inside the browser dev tools
import React from "react";
import "./styles.css";
import { makeStyles } from "#material-ui/core/styles";
import { Typography } from "#material-ui/core";
const useStyles = makeStyles(theme => ({
option1: {
color: "red"
},
option2: {
"&.MuiTypography-root": {
color: "blue"
}
}
}));
export default function App() {
const classes = useStyles();
return (
<div className="App">
<Typography
variant="h5"
component="h5"
classes={{ root: classes.option1 }}
>
Use CSS API with attribute: root
</Typography>
<Typography variant="h5" component="h5" className={classes.option2}>
Use nesting selector of className: MuiTypography-root
</Typography>
</div>
);
}

Set Typography text color in MUI

I'm pretty new to MUI, and I'm trying to set a Typography with a text color like this:
const theme = createMuiTheme({
palette: {
text:{
primary: "#FFFFFF"
}
}
});
const WhiteText = (props: { text:string, varient: Variant | 'inherit'}) => {
return <ThemeProvider theme={theme}>
<Typography variant={props.varient} align="center" color="textPrimary">{props.text}</Typography>
</ThemeProvider>
}
...
<WhiteText varient="h3" text="This text should be white"/>
but the text will not change color :/
Am I applying the theme wrong?
Though your approach works fine in this sandbox, it is not the approach I would recommend. Instead of nested themes, for customizations like this I would recommend using withStyles as shown below (for v4 of Material-UI -- v5 example further down).
import React from "react";
import { withStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
const WhiteTextTypography = withStyles({
root: {
color: "#FFFFFF"
}
})(Typography);
export default function App() {
return (
<div className="App" style={{ backgroundColor: "black" }}>
<WhiteTextTypography variant="h3">
This text should be white
</WhiteTextTypography>
</div>
);
}
In v5, MUI has enhanced the color prop significantly (for all components that have a color prop) to support any color in the theme's palette, so for white you can use common.white:
import React from "react";
import Typography from "#mui/material/Typography";
export default function App() {
return (
<div className="App" style={{ backgroundColor: "black" }}>
<Typography variant="h3" color="common.white">
This text should be white
</Typography>
</div>
);
}
Related answer: Can you add an additional color in Material UI?
If you want to set a default color for all Typography elements, but not for other Material UI elements you can try this:
const theme = createMuiTheme({
typography: {
allVariants: {
color: "pink"
},
},
});
If you don't want to use any themes. You can set it via style Attribute also.
<Typography style={{color:"#00adb5"}} variant="h3" >My Text</Typography>
For MUI 5, use sx attribute,
<Typography sx={{ color: "#00adb5" }} variant="h3">
My Text
</Typography>
The color prop of Typography is theme aware which is a nice feature of sx prop. This means besides setting the color as usual like this:
<Typography variant="h1" color="#00ff00">
You can reference the themed colors, either from the default palette or a custom palette defined like below:
const theme = createTheme({
palette: {
tomato: '#FF6347',
pink: {
deep: '#FF1493',
hot: '#FF69B4',
medium: '#C71585',
pale: '#DB7093',
light: '#FFB6C1',
},
},
});
After registering the custom theme in ThemeProvider, you can use it in Typography by specifying the string path of the Palette object to the color value:
<Typography color="tomato">text</Typography>
<Typography color="pink.deep">text</Typography>
<Typography color="pink.hot">text</Typography>
<Typography color="pink.medium">text</Typography>
<Typography color="pink.pale">text</Typography>
<Typography color="pink.light">text</Typography>
Here is a couple of examples of Typograhy using the default colors from the palette:
<Typography color="primary.main">text</Typography>
<Typography color="primary.dark">text</Typography>
<Typography color="primary.light">text</Typography>
<Typography color="secondary">text</Typography>
<Typography color="text.secondary">text</Typography>
<Typography color="text.disabled">text</Typography>
Set Typography Text Color in Material UI
<Typography gutterBottom variant="h9" component="h2" color="secondary">
{card.unitNumberList}
</Typography>
I would try this -
Include a typgraphy property in your theme, something like below with an 'h3' variant.
const theme = createMuiTheme({
palette: {
text: {
primary: "#FFFFFF"
}
},
typography: {
useNextVariants: true,
fontFamily: "Montserrat",
h3: {
fontSize: 33,
fontFamily: "Montserrat",
fontWeight: 300,
color: "#2882F8",
letterSpacing: "0.0075em",
verticalAlign: "middle",
alignItems: "center",
textAlign: "center"
}
}
});
Then the color of your Typography should come directly from the variant="h3" that you just declared inside theme. You dont need to seperately pass the 'color' props to Typgraphy
For a working implementations of this, you can check this Repo of mine, where I am keeping all my Typography variants in a single central global file called globalTheme.js and in the App.js wrapping all the other components within MuiThemeProvider as below
<MuiThemeProvider theme={globalTheme}>
So all Typography component anywhere in the project will have access to the variants that I have declared in that globalTheme.js file.
First of all, you need to define alternative colors for the text elements.
text: {
primary: 'rgba(60, 72, 88, 1)',
secondary: 'rgba(132, 146, 166, 1)',
disabled: 'rgba(60, 72, 88, 0.38)',
hint: 'rgba(60, 72, 88, 0.38)',
}
Then you can do the following:
<Typography variant="h1">Lorem ipsum</Typography> // Default text color
<Typography variant="subtitle1" color="textSecondary">dolor sit amet</Typography> // Secondary text color.
<Typography variant="body1" color="secondary">consectetur adipiscing elit</Typography> // Global secondary color.
You can try using make styles from the material-ui core to create a custom look for your text which can include the text colour as shown in the example below
import {makeStyles} from '#material-ui/core/styles'
const useStyles=makeStyles((theme)=>({
text:{
color:"#ffffff"
}
}));
const classes=useStyles();
<Typography align="center" className={classes.text}>This text should be white</Typography>
For those who are still on v4, uses typescript and want to have a typesafe definition can extend mui's Typography like this:
import React, { FC } from "react";
import { createStyles, makeStyles, Theme } from "#material-ui/core";
import MuiTypography, { TypographyProps } from "#material-ui/core/Typography";
import clsx from "clsx";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
warning: {
color: theme.palette.warning.main,
},
success: {
color: theme.palette.success.main,
},
})
);
type AdditionalColorKeys = keyof ReturnType<typeof useStyles>;
export type TypographyWithSpacingProps = Omit<TypographyProps, "color"> & {
color?: AdditionalColorKeys | TypographyProps["color"];
};
export const Typography: FC<TypographyWithSpacingProps> = ({ color, className, ...props }) => {
const classes = useStyles();
let colorClass = "";
if (color && color in classes) {
colorClass = classes[color as keyof ReturnType<typeof useStyles>];
}
return <MuiTypography {...props} className={clsx(className, colorClass)} />;
};
You can also simply change the Typography's color by adding system props 'sx'
like this
<Typography
variant="h6"
sx={{
color: "white",
}}
>

Reference to theme's primary color instead of a specific color in MUI

Using ReactJS and MUI, I have a project in which I have changed the theme colors.
const newTheme = getMuiTheme({
fontFamily: 'Roboto, sans-serif',
palette: {
primary1Color: cyan500,
primary2Color: cyan700,
primary3Color: grey400,
accent1Color: amberA400,
accent2Color: grey100,
accent3Color: grey500,
textColor: darkBlack,
alternateTextColor: white,
canvasColor: white,
borderColor: grey300,
disabledColor: fade(darkBlack, 0.3),
pickerHeaderColor: cyan500,
clockCircleColor: fade(darkBlack, 0.07),
shadowColor: fullBlack,
},
});
// App class
render() {
return(
<ThemeProvider theme={newTheme}>
<Project />
</ThemeProvider>
)
}
Everything works as expected. Certain components, like buttons have the ability to set the color based on the primary prop. However, I have a component that uses an icon that needs the primary color. I can import the color and set it directly:
import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {cyan500} from 'material-ui/styles/colors';
export default class LockIcon extends React.Component {
render() {
return(
<ActionLock color={cyan500} />
)
}
}
Is there some way to reference the theme's primary color, rather than setting the color in each component individually? Something like:
import React from 'react';
import ActionLock from 'material-ui/svg-icons/action/lock';
import {primary1Color} from 'somewhere';
export default class LockIcon extends React.Component {
render() {
return(
<ActionLock color={primary1Color} />
)
}
}
If you're using React v16.8.0 and Material-UI v3.5.0 or greater, you can utilize the useTheme() hook:
import { useTheme } from '#material-ui/core/styles';
function LockIcon = () => {
const theme = useTheme();
return (
<ActionLock color={theme.palette.primary1Color} />
}
Yes you have!
using muiThemeable..
import muiThemeable from 'material-ui/styles/muiThemeable';
class LockIcon extends React.Component {
render() {
return(
<ActionLock color={this.props.muiTheme.palette.primary1Color} />
)
}
}
export default muiThemeable()(LockIcon)
from material-ui docs
Adding how to access theme colors in material-ui v1.0.0 (currently beta) Using withTheme component.
Also check the following Example.
import React, {Component} from 'react';
import { withTheme } from 'material-ui/styles';
class WithThemeExample extends Component {
render() {
const { theme } = props;
const {primary, secondary} = theme.palette.text;
return (
<div>
<div style={{color: primary}}>Hi in Primary color</div>
<div style={{color: secondary}}>Bye in Secondary color</div>
</div>
);
}
}
export default withTheme()(WithThemeExample);
If you're using system properties, you can define a string path of the Palette object to the color value like below:
<Box sx={{ color: "primary.main" }}>primary.main</Box>
<Box sx={{ color: "secondary.main" }}>secondary.main</Box>
<Box sx={{ color: "error.main" }}>error.main</Box>
<Box sx={{ color: "warning.main" }}>warning.main</Box>
<Box sx={{ color: "info.main" }}>info.main</Box>
<Box sx={{ color: "success.main" }}>success.main</Box>
<Box sx={{ color: "text.primary" }}>text.primary</Box>
<Box sx={{ color: "text.secondary" }}>text.secondary</Box>
<Box sx={{ color: "text.disabled" }}>text.disabled</Box>
The above is the same as:
<Box sx={{ color: theme => theme.palette.primary.main }}>primary.main</Box>
<Box sx={{ color: theme => theme.palette.secondary.main }}>secondary.main</Box>
<Box sx={{ color: theme => theme.palette.error.main }}>error.main</Box>
<Box sx={{ color: theme => theme.palette.warning.main }}>warning.main</Box>
<Box sx={{ color: theme => theme.palette.info.main }}>info.main</Box>
<Box sx={{ color: theme => theme.palette.success.main }}>success.main</Box>
<Box sx={{ color: theme => theme.palette.text.primary }}>text.primary</Box>
<Box sx={{ color: theme => theme.palette.text.secondary }}>text.secondary</Box>
<Box sx={{ color: theme => theme.palette.text.disabled }}>text.disabled</Box>
The example using the callback is more verbose but is type-safe, the shorter one with only string is quicker and good when prototyping, but you may want to store the string in a constant to prevent any typo errors and help the IDE refactor your code better.
Live Demo
Ok if you are using material-ui version greater than 4, then the above solution might not work for you. Follow the below's code
import { withTheme } from '#material-ui/core/styles';
function DeepChildRaw(props) {
return <span>{`spacing ${props.theme.spacing}`}</span>;
}
const DeepChild = withTheme(DeepChildRaw);
Reference: https://material-ui.com/styles/advanced/
With react hooks, now you don't need to warp component in withTheme, just use useTheme:
import { useTheme } from '#material-ui/core/styles';
export default function MyComponent() {
const theme = useTheme();
return <span>{`spacing ${theme.spacing}`}</span>;
}
MUI V5
For the users of MUI v5, you can specify a function inside the sx css style directly, ex:
<Box sx={{ color: (theme) => theme.palette.primary1Color }} />
You can use the useTheme() hook and access the colors like the example below.
There are also some other color variants as well.
Mui 5:
import * as React from 'react';
import PropTypes from 'prop-types';
import { NavLink } from "react-router-dom";
import { useTheme } from "#mui/material/styles";
function VinNavLink(props) {
const theme = useTheme();
return (
<NavLink {...props} style={({ isActive }) => isActive ? { textDecoration: "underline", color: theme.palette.primary.main} : undefined}>{props.children}</NavLink>
);
}
export default VinNavLink;

Resources