How to style MUI Tooltip? - reactjs

How can I style MUI Tooltip text? The default tooltip on hover comes out black with no text-wrap. Is it possible to change the background, color etc? Is this option even available?

The other popular answer (by André Junges) on this question is for the 0.x versions of Material-UI. Below I've copied in my answer from Material UI's Tooltip - Customization Style which addresses this for v3 and v4. Further down, I have added a version of the example using v5.
Below are examples of how to override all tooltips via the theme, or to just customize a single tooltip using withStyles (two different examples). The second approach could also be used to create a custom tooltip component that you could reuse without forcing it to be used globally.
import React from "react";
import ReactDOM from "react-dom";
import {
createMuiTheme,
MuiThemeProvider,
withStyles
} from "#material-ui/core/styles";
import Tooltip from "#material-ui/core/Tooltip";
const defaultTheme = createMuiTheme();
const theme = createMuiTheme({
overrides: {
MuiTooltip: {
tooltip: {
fontSize: "2em",
color: "yellow",
backgroundColor: "red"
}
}
}
});
const BlueOnGreenTooltip = withStyles({
tooltip: {
color: "lightblue",
backgroundColor: "green"
}
})(Tooltip);
const TextOnlyTooltip = withStyles({
tooltip: {
color: "black",
backgroundColor: "transparent"
}
})(Tooltip);
function App(props) {
return (
<MuiThemeProvider theme={defaultTheme}>
<div className="App">
<MuiThemeProvider theme={theme}>
<Tooltip title="This tooltip is customized via overrides in the theme">
<div style={{ marginBottom: "20px" }}>
Hover to see tooltip customized via theme
</div>
</Tooltip>
</MuiThemeProvider>
<BlueOnGreenTooltip title="This tooltip is customized via withStyles">
<div style={{ marginBottom: "20px" }}>
Hover to see blue-on-green tooltip customized via withStyles
</div>
</BlueOnGreenTooltip>
<TextOnlyTooltip title="This tooltip is customized via withStyles">
<div>Hover to see text-only tooltip customized via withStyles</div>
</TextOnlyTooltip>
</div>
</MuiThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Here is documentation on tooltip CSS classes available to control different aspects of tooltip behavior: https://material-ui.com/api/tooltip/#css
Here is documentation on overriding these classes in the theme: https://material-ui.com/customization/components/#global-theme-override
Here is a similar example, but updated to work with v5 of Material-UI (pay attention that it works in 5.0.3 and upper versions after some fixes). It includes customization via the theme, customization using styled, and customization using the sx prop. All of these customizations target the "tooltip slot" so that the CSS is applied to the element that controls the visual look of the tooltip.
import React from "react";
import ReactDOM from "react-dom";
import { createTheme, ThemeProvider, styled } from "#mui/material/styles";
import Tooltip from "#mui/material/Tooltip";
const defaultTheme = createTheme();
const theme = createTheme({
components: {
MuiTooltip: {
styleOverrides: {
tooltip: {
fontSize: "2em",
color: "yellow",
backgroundColor: "red"
}
}
}
}
});
const BlueOnGreenTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} componentsProps={{ tooltip: { className: className } }} />
))(`
color: lightblue;
background-color: green;
font-size: 1.5em;
`);
const TextOnlyTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} componentsProps={{ tooltip: { className: className } }} />
))(`
color: black;
background-color: transparent;
`);
function App(props) {
return (
<ThemeProvider theme={defaultTheme}>
<div className="App">
<ThemeProvider theme={theme}>
<Tooltip title="This tooltip is customized via overrides in the theme">
<div style={{ marginBottom: "20px" }}>
Hover to see tooltip customized via theme
</div>
</Tooltip>
</ThemeProvider>
<BlueOnGreenTooltip title="This tooltip is customized via styled">
<div style={{ marginBottom: "20px" }}>
Hover to see blue-on-green tooltip customized via styled
</div>
</BlueOnGreenTooltip>
<TextOnlyTooltip title="This tooltip is customized via styled">
<div style={{ marginBottom: "20px" }}>
Hover to see text-only tooltip customized via styled
</div>
</TextOnlyTooltip>
<Tooltip
title="This tooltip is customized via the sx prop"
componentsProps={{
tooltip: {
sx: {
color: "purple",
backgroundColor: "lightblue",
fontSize: "2em"
}
}
}}
>
<div>
Hover to see purple-on-blue tooltip customized via the sx prop
</div>
</Tooltip>
</div>
</ThemeProvider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Documentation on changes to the theme structure between v4 and v5: https://mui.com/guides/migration-v4/#theme
Tooltip customization examples in the Material-UI documentation: https://mui.com/components/tooltips/#customization

MUI v5 Update
You can customize the Tooltip by overriding the styles in the tooltip slot. There are 3 ways to do that in v5. For reference, see the customization section of Tooltip. More examples of sx prop and createTheme can be seen here and here.
styled()
const ToBeStyledTooltip = ({ className, ...props }) => (
<Tooltip {...props} classes={{ tooltip: className }} />
);
const StyledTooltip = styled(ToBeStyledTooltip)(({ theme }) => ({
backgroundColor: '#f5f5f9',
color: 'rgba(0, 0, 0, 0.87)',
border: '1px solid #dadde9',
}));
sx prop
<Tooltip
title="Add"
arrow
componentsProps={{
tooltip: {
sx: {
bgcolor: 'common.black',
'& .MuiTooltip-arrow': {
color: 'common.black',
},
},
},
}}
>
<Button>SX</Button>
</Tooltip>
createTheme + ThemeProvider
const theme = createTheme({
components: {
MuiTooltip: {
styleOverrides: {
tooltip: {
backgroundColor: 'pink',
color: 'red',
border: '1px solid #dadde9',
},
},
},
},
});

If you want to change text color , font-size ... of Tooltip there is a simple way.
You can insert a Tag inside Title of Martial Ui Tooltip for example :
<Tooltip title={<span>YourText</span>}>
<Button>Grow</Button>
</Tooltip>
then you can style your tag anyhow you want.
check below Example :

This answer is out of date. This answer was written in 2016 for the 0.x versions of Material-UI. Please see this answer for an approach that works with versions 3 and 4.
well, you can change the text color and the element background customizing the mui theme.
color - is the text color
rippleBackgroundColor - is the tooltip bbackground
Example: Using IconButton - but you could you the Tooltip directly..
import React from 'react';
import IconButton from 'material-ui/IconButton';
import MuiThemeProvider from 'material-ui/lib/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';
const muiTheme = getMuiTheme({
tooltip: {
color: '#f1f1f1',
rippleBackgroundColor: 'blue'
},
});
const Example = () => (
<div>
<MuiThemeProvider muiTheme={muiTheme}>
<IconButton iconClassName="muidocs-icon-custom-github" tooltip="test" />
</MuiThemeProvider>
</div>
);
You can also pass a style object for the Tooltip (in IconButton it's tooltipStyles) - but these styles will only be applied for the root element.
It's not possible yet to change the label style to make it wrap in multiple lines.

I ran into this issue as well, and want for anyone seeking to simply change the color of their tooltip to see this solution that worked for me:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Tooltip from '#material-ui/core/Tooltip';
import Button from '#material-ui/core/Button';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles(theme => ({
customTooltip: {
// I used the rgba color for the standard "secondary" color
backgroundColor: 'rgba(220, 0, 78, 0.8)',
},
customArrow: {
color: 'rgba(220, 0, 78, 0.8)',
},
}));
export default TooltipExample = () => {
const classes = useStyles();
return (
<>
<Tooltip
classes={{
tooltip: classes.customTooltip,
arrow: classes.customArrow
}}
title="Delete"
arrow
>
<Button color="secondary"><DeleteIcon /></Button>
</Tooltip>
</>
);
};

MUI v5 custom component
Building on NearHuscarl's answer using sx, the simplest approach for me was to create a custom component to include the styling plus any other properties you want repeated on each tooltip.
For example, the component could display the tooltips on the bottom with an arrow and a larger font size:
const StyledTooltip = ({ title, children, ...props }) => (
<Tooltip
{...props}
title={title}
placement="bottom"
arrow
componentsProps={{
tooltip: {
sx: {
fontSize: '1.125rem',
},
},
}}
>
{children}
</Tooltip>
);
const Buttons = () => (
<div>
<StyledTooltip title="This is one">
<Button>One</Button>
</StyledTooltip>
<StyledTooltip title="This is two">
<Button>Two</Button>
</StyledTooltip>
</div>
);

Another solution with HtmlTooltip
I Use HtmlTooltip and add arrow: {color: '#f5f5f9',}, for the arrow tooltip style.
And much more to the tooltip style itself.
So I use ValueLabelComponent to control the label and put there a Tooltip from MaterialUI.
Hopes it give another way to edit MaterialUI Tooltip :)
const HtmlTooltip = withStyles((theme) => ({
tooltip: {
backgroundColor: 'var(--blue)',
color: 'white',
maxWidth: 220,
fontSize: theme.typography.pxToRem(12),
border: '1px solid #dadde9',
},
arrow: {
color: '#f5f5f9',
},
}))(Tooltip);
function ValueLabelComponent({ children, open, value }) {
return (
<HtmlTooltip arrow open={open} enterTouchDelay={0} placement="top" title={value}>
{children}
</HtmlTooltip>
);
}
...
...
return (
<div className={classes.root}>
<Slider
value={value}
onChange={handleChange}
onChangeCommitted={handleChangeCommitted}
scale={(x) => convertRangeValueToOriginalValue(x, minMaxObj)}
valueLabelDisplay="auto"
valueLabelFormat={(x) => '$' + x}
ValueLabelComponent={ValueLabelComponent}
aria-labelledby="range-slider"
/>
</div>
);

I used makeStyles() and ended with that:
import React from 'react';
import Grid from '#mui/material/Grid';
import Typography from '#mui/material/Typography';
import Tooltip from '#mui/material/Tooltip';
import InfoOutlinedIcon from '#mui/icons-material/InfoOutlined';
import { makeStyles } from '#material-ui/core/styles';
const styles = makeStyles({
tooltip: {
backgroundColor: '#FFFFFF',
color: '#000000',
border: '.5px solid #999999',
fontSize: '.85rem',
fontWeight: '400'
}
});
const HeaderTooltip = ({ header, tooltip }) =>
<Grid container direction="row" alignItems="center" spacing={1}>
<Grid item>
<Typography variant='h5'>{header}</Typography>
</Grid>
<Grid item>
<Tooltip title={tooltip} classes={{ tooltip: styles().tooltip }}>
<InfoOutlinedIcon />
</Tooltip>
</Grid>
</Grid>
export default HeaderTooltip;

With styledComponent and MUI V5
import styled from 'styled-components';
....
....
<StyledTooltip title={tooltip}>
<IconTextStyle>
{icon}
<Label>{label}</Label>
</IconTextStyle>
</StyledTooltip>
const StyledTooltip = styled((props) => (
<Tooltip classes={{ popper: props.className }} {...props} />
))`
& .MuiTooltip-tooltip {
display: flex;
background-color: #191c28;
border-radius: 4px;
box-shadow: 0px 0px 24px #00000034;
}
`;

I'm created custom Tooltip in the following way
import React from 'react'
import Tooltip from '#material-ui/core/Tooltip'
import ErrorOutlineOutlinedIcon from '#material-ui/icons/ErrorOutlineOutlined'
import {
makeStyles,
createStyles,
withStyles,
} from '#material-ui/core/styles'
import Typography from '#material-ui/core/Typography'
import { Divider, Link, Paper } from '#material-ui/core'
const HtmlTooltip = withStyles(theme => ({
arrow: {
'&::before': {
color: 'white'
}
},
tooltip: {
backgroundColor: '#f5f5f9',
boxShadow: theme.shadows[8],
color: 'rgba(0, 0, 0, 0.87)',
fontSize: 14,
maxWidth: 800,
padding: 0,
},
tooltipPlacementTop: {
margin: '4px 0',
},
}))(Tooltip)
const imageStyles = { root: { color: 'deeppink', height: 20, marginBottom: 0, width: 20 } }
const Image = withStyles(imageStyles)(({ classes }) => (
<ErrorOutlineOutlinedIcon classes={classes} />
))
const useStyles = makeStyles(theme =>
createStyles({
content: {
border: `1px solid ${theme.palette.grey[300]}`,
margin: 0,
minWidth: 600,
padding: 0,
zIndex: 1,
},
contentInner: {
padding: theme.spacing(1)
},
header: {
backgroundColor: 'deeppink',
fontWeight: 'bold',
padding: theme.spacing(1),
}
})
)
export default function CustomTooltip(params) {
const classes = useStyles()
const labelDisplay = params.content
const textDispaly = params.text
return (
<>
{labelDisplay && labelDisplay.length > 20 ? (<HtmlTooltip arrow interactive title={
<Paper className={classes.content}>
<div className={classes.header}>
<Typography color='inherit' variant='body1' style={{color: 'white', fontSize: '20px'}}>
{params.title}
</Typography>
</div>
<Divider />
<div className={classes.contentInner}>
{textDispaly}
</div>
</Paper>}
placement='top'
>
<div style={{ alignItems: 'center', display: 'flex', fontSize: '12px', justifyContent: 'space-between' }}>
{labelDisplay}<Image/>
</div>
</HtmlTooltip>) : (labelDisplay)}
</>
)
}

Related

How can use Material ui custom pagination?

<Pagination count={35} variant="outlined" shape="rounded" color="primary"/>
This sets a default background colour and text colour, but I need custom background colour and text colour. I can't change it. I am trying to change the colour but I failed.
import * as React from 'react';
import Pagination from '#mui/material/Pagination';
import Stack from '#mui/material/Stack';
import { styled } from '#mui/system';
//Make a styled pagination component using styled API that overrides default style
const MyPagination = styled(Pagination)({
'& .Mui-selected': {
backgroundColor: 'red',
color:'#19D5C6',
},
"& .MuiPaginationItem-root": {
border: "1px solid red"
}
//There has a lot of Global classes. you have to use it according to your requirement
//Some classes are MuiPaginationItem-root, MuiPaginationItem-page and Mui-selected
});
export default function BasicPagination() {
return (
<Stack spacing={2}>
<MyPagination count={10} />
</Stack>
);
}
click to get all classes name
I would use a theme which will apply consistency throughout your project.
Codesandbox implementation here: https://codesandbox.io/s/mutable-river-e15yxw
Theme.js
import { ThemeProvider, createTheme } from "#mui/material/styles";
import CssBaseline from "#mui/material/CssBaseline";
export default function Theme(props) {
const theme = createTheme({
components: {
MuiPagination: {
styleOverrides: {
root: ({ ownerState }) => ({ backgroundColor: "#ffeeaa" })
}
},
MuiPaginationItem: {
styleOverrides: {
root: ({ ownerState }) => ({ backgroundColor: "#ffcc00", color: "maroon" })
}
}
}
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{props.children}
</ThemeProvider>
);
}
Demo.js
import * as React from "react";
import Pagination from "#mui/material/Pagination";
import Stack from "#mui/material/Stack";
import Theme from "./Theme";
export default function BasicPagination() {
return (
<Theme>
<Stack spacing={2}>
<Pagination count={10} sx={{ backgroundColor: "#eeffaa" }} />
<Pagination count={10} color="primary" />
<Pagination count={10} color="secondary" />
<Pagination count={10} disabled />
</Stack>
</Theme>
);
}
And there is another one if you prefer it, utilising the sx prop:
<Pagination
count={35}
shape="rounded"
color="primary"
sx={{
"& .MuiPagination-ul": { backgroundColor: "yellow" },
"& .MuiPaginationItem-page": { color: "red" },
"& .Mui-selected": { backgroundColor: "green" },
}}
/>
This is the result:
EDIT:
<Pagination
count={35}
shape="rounded"
color="primary"
sx={{
"& .MuiPagination-ul": { backgroundColor: "yellow" },
"& .MuiPaginationItem-page": { color: "red", border: "1px solid green" },
"& .Mui-selected": { backgroundColor: "green" },
}}
/>

mui v5 what is the best way to use style with pragmatic condition?

I'm upgrading a project from material ui v4 to v5 and struggle to update classes/styles properly.
this is a sandBox :
https://codesandbox.io/s/69629346-mui-v5-theming-with-emotion-mui-forked-2j8vze?file=/demo.tsx:1611-1618
In this code 2 box are displayed with 2 ways of applying style. I want to avoid using makeStyles and use SX/emotion as recommanded.
So backgroundColor is red, on hover it become blue.
It works on both.
Now if i click the switch, the backgroundColor become yellow, but on hover of second box the color stay blue instead of grey.
what i'm missing ? thanks
import React, { useState } from "react";
import { makeStyles } from "#mui/styles";
import clsx from "clsx";
import { Box, Switch } from "#mui/material";
import { createTheme, ThemeProvider } from "#mui/material/styles";
const theme = createTheme();
const useStyles = makeStyles((theme) => ({
imageWithBorder: {
height: theme.spacing(10),
width: theme.spacing(30),
padding: theme.spacing(2),
margin: theme.spacing(2),
backgroundColor: "red",
"&:hover": {
backgroundColor: "blue"
}
},
greyHover: {
backgroundColor: "yellow",
"&:hover": { backgroundColor: "grey" }
}
}));
const styles = {
imageWithBorder: {
height: 80,
width: 240,
padding: 2,
margin: 2,
backgroundColor: "red",
"&:hover": {
backgroundColor: "blue"
}
},
greyHover: {
backgroundColor: "yellow",
"&:hover": { backgroundColor: "grey" }
}
};
export default function Test() {
const classes = useStyles();
const [checked, setChecked] = useState(false);
return (
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Box>
Enable grey hover : <Switch checked={checked} onChange={handleChange} />
</Box>
<p>1 With clsx & useStyles</p>
<Box
className={clsx(classes.imageWithBorder, checked && classes.greyHover)}
/>
<p>2 With sx & plain styles</p>
<Box sx={[styles.imageWithBorder, checked && styles.greyHover]} />
</Box>
);
function handleChange(event) {
setChecked(event.target.checked);
}
}
export default function BasicUsage() {
return (
<ThemeProvider theme={theme}>
<Test />
</ThemeProvider>
);
}
By some reason mui doesn't accept backgroundColor: "grey". It's not even render it in the output css.
See gif
Instead, use gray or hex value.
https://codesandbox.io/s/69629346-mui-v5-theming-with-emotion-mui-forked-d0npw6?file=/demo.tsx

How do you change a style of a child when hovering over a parent using MUI styles?

I'm using MUI in react. Let's say I have this component with these styles:
const useStyles = makeStyles(theme => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100]
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
function App() {
const classes = useStyles();
return (
<Grid container>
<Grid item className={classes.outerDiv}>
<AddIcon className={classes.addIcon} />
</Grid>
</Grid>
);
}
I want to change the style of addIcon when hovering over outerDiv using the styles above.
Here's my example.
Below is an example of the correct syntax for v4 ("& $addIcon" nested within &:hover). Further down are some v5 examples.
import * as React from "react";
import { render } from "react-dom";
import { Grid, makeStyles } from "#material-ui/core";
import AddIcon from "#material-ui/icons/Add";
const useStyles = makeStyles(theme => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100],
"& $addIcon": {
color: "purple"
}
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
function App() {
const classes = useStyles();
return (
<Grid container>
<Grid item className={classes.outerDiv}>
<AddIcon className={classes.addIcon} />
</Grid>
</Grid>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Related documentation and answers:
https://cssinjs.org/jss-plugin-nested?v=v10.0.0#use-rulename-to-reference-a-local-rule-within-the-same-style-sheet
how to use css in JS for nested hover styles, Material UI
Material UI: affect children based on class
Advanced styling in material-ui
For those who have started using Material-UI v5, the example below implements the same styles but leveraging the new sx prop.
import Grid from "#mui/material/Grid";
import { useTheme } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
export default function App() {
const theme = useTheme();
return (
<Grid container>
<Grid
item
sx={{
p: 4,
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
"& .addIcon": {
color: "purple"
}
}
}}
>
<AddIcon
className="addIcon"
sx={{
height: "50px",
width: "50px",
color: theme.palette.grey[400],
mb: 2
}}
/>
</Grid>
</Grid>
);
}
Here's another v5 example, but using Emotion's styled function rather than Material-UI's sx prop:
import Grid from "#mui/material/Grid";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
import styled from "#emotion/styled/macro";
const StyledAddIcon = styled(AddIcon)(({ theme }) => ({
height: "50px",
width: "50px",
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
}));
const StyledGrid = styled(Grid)(({ theme }) => ({
padding: theme.spacing(4),
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
[`${StyledAddIcon}`]: {
color: "purple"
}
}
}));
const theme = createTheme();
export default function App() {
return (
<ThemeProvider theme={theme}>
<Grid container>
<StyledGrid item>
<StyledAddIcon />
</StyledGrid>
</Grid>
</ThemeProvider>
);
}
And one more v5 example using Emotion's css prop:
/** #jsxImportSource #emotion/react */
import Grid from "#mui/material/Grid";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import AddIcon from "#mui/icons-material/Add";
const theme = createTheme();
export default function App() {
return (
<ThemeProvider theme={theme}>
<Grid container>
<Grid
item
css={(theme) => ({
padding: theme.spacing(4),
backgroundColor: theme.palette.grey[200],
"&:hover": {
backgroundColor: theme.palette.grey[100],
cursor: "pointer",
"& .addIcon": {
color: "purple"
}
}
})}
>
<AddIcon
className="addIcon"
css={(theme) => ({
height: "50px",
width: "50px",
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})}
/>
</Grid>
</Grid>
</ThemeProvider>
);
}
This denotes the current selector which is the parent component:
'&': { /* styles */ }
This means the parent component in hover state:
'&:hover': { /* styles */ }
This means the child component inside the parent that is in hover state:
'&:hover .child': { /* styles */ }
You can also omit the ampersand & if you're using a pseudo-class:
':hover .child': { /* styles */ }
Complete code using sx prop (The same style object can also be used in styled()):
<Box
sx={{
width: 300,
height: 300,
backgroundColor: "darkblue",
":hover .child": {
backgroundColor: "orange"
}
}}
>
<Box className="child" sx={{ width: 200, height: 200 }} />
</Box>
Possibly an obvious point, but just to add to the answer above: if you are referencing a separate className, don't forget that you also need to create it in the makeStyles hook or else it won't work. For instance:
const useStyles = makeStyles({
parent: {
color: "red",
"&:hover": {
"& $child": {
color: "blue" // will only apply if the class below is declared (can be declared empty)
}
}
},
// child: {} // THIS must be created / uncommented in order for the code above to work; assigning the className to the component alone won't work.
})
const Example = () => {
const classes = useStyles()
return (
<Box className={classes.parent}>
<Box className={classes.child}>
I am red unless you create the child class in the hook
</Box>
</Box>
)
}
If you were using makeStyles in MUI v4 and have migrated to MUI v5 then you are likely now importing makeStyles from tss-react. If that is the case, then you achieve the same by the following:
import { makeStyles } from 'tss-react';
const useStyles = makeStyles((theme, props, classes) => ({
outerDiv: {
backgroundColor: theme.palette.grey[200],
padding: theme.spacing(4),
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.grey[100],
[`& .${classes.addIcon}`]: {
color: "purple"
}
}
},
addIcon: (props: { dragActive: boolean }) => ({
height: 50,
width: 50,
color: theme.palette.grey[400],
marginBottom: theme.spacing(2)
})
}));
The third argument passed to the makeStyles callback is the classes object.

Custom color to Badge component not working

I need to add a custom color to my Badge component and it does not seem to work.
I have tried these:
<Badge className="badge" badgeStyle={{backgroundColor: '#00AFD7'}} variant="dot" />
<Badge className="badge" color='#00AFD7' variant="dot" />
These do not work. How can I pass a custom color to my Badge component
You can leverage withStyles and use the badge css class to customize this.
Here's an example:
import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "#material-ui/core/styles";
import Badge from "#material-ui/core/Badge";
import MailIcon from "#material-ui/icons/Mail";
const styles = theme => ({
margin: {
margin: theme.spacing.unit * 2
},
customBadge: {
backgroundColor: "#00AFD7",
color: "white"
}
});
function SimpleBadge(props) {
const { classes } = props;
return (
<div>
<Badge
classes={{ badge: classes.customBadge }}
className={classes.margin}
badgeContent={10}
>
<MailIcon />
</Badge>
</div>
);
}
SimpleBadge.propTypes = {
classes: PropTypes.object.isRequired
};
export default withStyles(styles)(SimpleBadge);
In v4, you can use functions within the styles that leverage props.
Documentation here: https://material-ui.com/styles/basics/#adapting-the-higher-order-component-api
const styles = theme => ({
margin: {
margin: theme.spacing.unit * 2
},
customBadge: {
backgroundColor: props => props.color,
color: "white"
}
});
In MUI v5, you can use either the sx prop:
<Badge
badgeContent={130}
sx={{
"& .MuiBadge-badge": {
color: "lightgreen",
backgroundColor: "green"
}
}}
>
<MailIcon />
</Badge>
Or styled() function:
const StyledBadge = styled(Badge)({
"& .MuiBadge-badge": {
color: "red",
backgroundColor: "pink"
}
});
I left the bg property empty and it accepted the background from the style. I am using bootstrap-5.
<Badge bg="" style={{backgroundColor: '#00AFD7'}} variant="dot">...</Badge>

How to add padding and margin to all Material-UI components?

I need to add padding or margin to some of Material-UI components, but could not find an easy way to do it. Can I add these properties to all components? something like this:
<Button color="default" padding={10} margin={5}>
I know that this is possible using pure CSS and classes but I want to do it the Material-UI way.
You can use de "Spacing" in a BOX component just by importing the component first:
import Box from '#material-ui/core/Box';
The Box component works as a "Wrapper" for the component you want to "Modify" the spacing.
then you can use the next properties on the component:
The space utility converts shorthand margin and padding props to margin and padding CSS declarations. The props are named using the format {property}{sides}.
Where property is one of:
m - for classes that set margin
p - for classes that set padding
Where sides is one of:
t - for classes that set margin-top or padding-top
b - for classes that set margin-bottom or padding-bottom
l - for classes that set margin-left or padding-left
r - for classes that set margin-right or padding-right
x - for classes that set both *-left and *-right
y - for classes that set both *-top and *-bottom
blank - for classes that set a margin or padding on all 4 sides of the element
as an example:
<Box m={2} pt={3}>
<Button color="default">
Your Text
</Button>
</Box>
Material-UI's styling solution uses JSS at its core. It's a high performance JS to CSS compiler which works at runtime and server-side.
import { withStyles} from '#material-ui/core/styles';
const styles = theme => ({
buttonPadding: {
padding: '30px',
},
});
function MyButtonComponent(props) {
const { classes } = props;
return (
<Button
variant="contained"
color="primary"
className={classes.buttonPadding}
>
My Button
</Button>
);
}
export default withStyles(styles)(MyButtonComponent);
You can inject styles with withStyle HOC into your component. This is how it works and it's very much optimized.
EDITED: To apply styles across all components you need to use createMuiTheme and wrap your component with MuiThemeprovider
const theme = createMuiTheme({
overrides: {
MuiButton: {
root: {
margin: "10px",
padding: "10px"
}
}
}
});
<MuiThemeProvider theme={theme}>
<Button variant="contained" color="primary">
Custom CSS
</Button>
<Button variant="contained" color="primary">
MuiThemeProvider
</Button>
<Button variant="contained" color="primary">
Bootstrap
</Button>
</MuiThemeProvider>
In Material-UI v5, one can change the button style using the sx props. You can see the margin/padding system properties and its equivalent CSS property here.
<Button sx={{ m: 2 }} variant="contained">
margin
</Button>
<Button sx={{ p: 2 }} variant="contained">
padding
</Button>
<Button sx={{ pt: 2 }} variant="contained">
padding top
</Button>
<Button sx={{ px: 2 }} variant="contained">
padding left, right
</Button>
<Button sx={{ my: 2 }} variant="contained">
margin top, bottom
</Button>
The property shorthands like m or p are optional if you want to quickly prototype your component, you can use normal CSS properties if you want your code more readable.
The code below is equivalent to the above but use CSS properties:
<Button sx={{ margin: 2 }} variant="contained">
margin
</Button>
<Button sx={{ padding: 2 }} variant="contained">
padding
</Button>
<Button sx={{ paddingTop: 2 }} variant="contained">
padding top
</Button>
<Button sx={{ paddingLeft: 3, paddingRight: 3 }} variant="contained">
padding left, right
</Button>
<Button sx={{ marginTop: 2, marginBottom: 2 }} variant="contained">
margin top, bottom
</Button>
Live Demo
import Box from '#material-ui/core/Box';
<Box m={1} p={2}>
<Button color="default">
Your Text
</Button>
</Box>
We can use makeStyles of material-ui to achieve this without using Box component.
Create a customSpacing function like below.
customSpacing.js
import { makeStyles } from "#material-ui/core";
const spacingMap = {
t: "Top", //marginTop
b: "Bottom",//marginBottom
l: "Left",//marginLeft
r: "Right",//marginRight
a: "", //margin (all around)
};
const Margin = (d, x) => {
const useStyles = makeStyles(() => ({
margin: () => {
// margin in x-axis(left/right both)
if (d === "x") {
return {
marginLeft: `${x}px`,
marginRight: `${x}px`
};
}
// margin in y-axis(top/bottom both)
if (d === "y") {
return {
marginTop: `${x}px`,
marginBottom: `${x}px`
};
}
return { [`margin${spacingMap[d]}`]: `${x}px` };
}
}));
const classes = useStyles();
const { margin } = classes;
return margin;
};
const Padding = (d, x) => {
const useStyles = makeStyles(() => ({
padding: () => {
if (d === "x") {
return {
paddingLeft: `${x}px`,
paddingRight: `${x}px`
};
}
if (d === "y") {
return {
paddingTop: `${x}px`,
paddingBottom: `${x}px`
};
}
return { [`padding${spacingMap[d]}`]: `${x}px` };
}
}));
const classes = useStyles();
const { padding } = classes;
return padding;
};
const customSpacing = () => {
return {
m: Margin,
p: Padding
};
};
export default customSpacing;
Now import above customSpacing function into your Component and use it like below.
App.js
import React from "react";
import "./styles.css";
import customSpacing from "./customSpacing";
const App = () => {
const { m, p } = customSpacing();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2
style={{ background: "red" }}
className={`${m("x", 20)} ${p("x", 2)}`}
>
Start editing to see some magic happen!
</h2>
</div>
);
};
export default App;
click to open codesandbox
We can use makeStyles or styles props on the Typography component to give margin until version 4.0.
I highly recommend to use version 5.0 of material ui and on this version Typography is having margin props and it makes life easy.
Specific for "padding-top" (10px) using Global style
Read this!
import React from "react";
import { Container, makeStyles, Typography } from "#material-ui/core";
import { Home } from "#material-ui/icons";
const useStyles = makeStyles((theme) => ({
container: {
paddingTop: theme.spacing(10),
},
}));
const LeftBar = () => {
const classes = useStyles();
return (
<Container className={classes.container}>
<div className={classes.item}>
<Home className={classes.icon} />
<Typography className={classes.text}>Homepage</Typography>
</div>
</Container>
);
};
export default LeftBar;
<Button color="default" p=10px m='5px'>
set initial spacing first in the themeprovider i.e the tag enclosing you app entry. It should look like this
import { createMuiTheme } from '#material-ui/core/styles';
import purple from '#material-ui/core/colors/purple';
import green from '#material-ui/core/colors/green';
const theme = createMuiTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: green[500],
},
},
});
function App() {
return (
<ThemeProvider theme={theme}>
<LandingPage />
</ThemeProvider>
);
}
that's it. so add the theme section to the code and use margin/padding as you wish
const theme = {
spacing: 8,
}
<Box m={-2} /> // margin: -16px;
<Box m={0} /> // margin: 0px;
<Box m={0.5} /> // margin: 4px;
<Box m={2} /> // margin: 16px;
you can use "margin" or "m" for short same applies to padding
or
const theme = {
spacing: value => value ** 2,
}
<Box m={0} /> // margin: 0px;
<Box m={2} /> // margin: 4px;
or
<Box m="2rem" /> // margin: 2rem;
<Box mx="auto" /> // margin-left: auto; margin-right: auto

Resources