How to bolden ListItem text in Material UI React - reactjs

I have the following styling to embolden the fontWeight of ListItem text in the Material UI library but unfortunately, it isn't working as expected.
Here is the code
import {
IconButton,
Collapse,
List,
ListItem, ListItemIcon,
ListItemText,
makeStyles,
useTheme
} from '#material-ui/core';
......
const useNavStyles = makeStyles((theme) => ({
navLinkItem: {
borderTopRightRadius: 100,
borderBottomRightRadius: 100,
paddingBottom: 12,
paddingTop: 12,
backgroundColor: theme.palette.background.paper,
fontWeight: 'bold' //This is not working
},
navLinkIcons: {
paddingLeft: 20,
},
nested: {
paddingLeft: theme.spacing(4),
},
}));
And here I try to use it in my render function as follows
const theme = useTheme();
const classes = useNavStyles(theme);
....
<ListItem button className={classes.navLinkItem}
selected={selectedEntry === title}
....
How can this be resolved?
Thank you.

#Gnut's suggestion is correct, but I thought I'd post an example.
The CSS section in https://material-ui.com/api/list-item-text/#css describes class attributes you can apply to effect style changes in various parts of the controls. Here's an example of how to style the primary text in a ListItemText:
const useStyles = makeStyles({
list: {
width: 300,
border: "1px solid gray"
},
text: {
fontWeight: "bold",
fontFamily: "courier",
color: "blue",
backgroundColor: "orange"
}
});
export default function App() {
const classes = useStyles();
return (
<div className="App">
<List className={classes.list}>
<ListItem button>
<ListItemText primary="Unstyled" />
</ListItem>
<ListItem button>
<ListItemText primary="Styled" classes={{ primary: classes.text }} />
</ListItem>
</List>
</div>
);
}
Codesandbox here: https://codesandbox.io/s/inspiring-euclid-gs7fp

You can have a look at their docs:
How to apply styles to deeper elements
The list of customization points for ListItem is listed here, under CSS section:
ListItem API
At first glance button, root and container should be your first tries.

Related

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.

Change Material-UI ListItem children on hover/active

Consider the following component structure of a side-bar navigation:
<ListItem button dense component={CustomNavLink} to="/dashboard">
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText primary="Dashboard" />
</ListItem>
The task is to change the ListItemIcon and ListItemText appearance on hover or when the CustomNavLink becomes active.
Note that CustomNavLink is an extended React Router's NavLink component
that gets an active class applied to when it matches with the current route.
The following, somewhat hacky way achieves that (abridged and simplified for clarity) via classes property:
const styles = {
root: {
...
'&.active, &:hover, &.active:hover': {
'& path': {
fill: 'red'
},
'& span': {
color: 'red'
}
}
}
};
(classes are then applied to the ListItem component)
This seems like an extremely lousy way of going about it, as the structure of the nested components leaks into the parent's styling... which is akin to doing this in the "old" CSS:
div:hover > ul > li > a {
color: red;
}
What is the idiomatic Material-UI way of solving this?
For reference, this is how it would be done in styled-components:
const CustomNavLink = styled(NavLink)`
...
&:hover {
${ListItemIcon} {
path: {
fill: red;
}
}
${ListItemText} {
color: red;
}
}
`;
Please Try following example for Change Material UI ListItem children on hover/active
const wrapperStyles = {
parent: {
backgroundColor: 'yellow',
'&:hover $child': {
color: 'red'
}
},
child: {
fontSize: '2em',
padding: 24
}
}
Expanding answer by #Patel Charul. In case you want to change the style of multiple children on hover.
const wrapperStyles = {
parent: {
backgroundColor: 'yellow',
'&:hover': {
'& $child1': {
color: 'red'
},
'& $child2': {
color: 'blue'
}
},
child1: {
fontSize: '2em',
padding: 24
},
child2: {
fontSize: '4em',
padding: 28
}
}
This is one way to do it in MUI v5, first import the following components:
import ListItem, { listItemClasses } from "#mui/material/ListItem";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
Then define the your custom NavLink, this NavLink will add the active className when it matches the current route:
function MyNavLink(props) {
return <NavLink {...props} activeClassName="active" />;
}
Then in the List component, add the following styles to style the ListItem in active and hover state:
<List
sx={{
[`& .active, & .${listItemClasses.root}:hover`]: {
color: "red",
fontWeight: "bold",
"& svg": {
fill: "red"
}
}
}}
>
<ListItem component={MyNavLink} to="/" exact>
<ListItemButton>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItemButton>
</ListItem>
{/* other NavLink component */}
</List>
Live Demo

MUI - Styling text inside ListItemText

I'm trying to apply style to the text inside a ListItemText (MUI):
const text = {
color: 'red'
}
<ListItem button><ListItemText style={text} primary="MyText" /></ListItem>
But the rendered Typograhy element inside is not styled at all ("MyText" is not red).
Looking at the generated code, it seems that the default CSS rules for Typography > subheading is overriding my CSS.
Thanks for your help
Edit: In the first version of the question, there was a misake ("className" instead of "style" prop on ListItemText, sorry about that).
I beleive the only way to achieve this right now is to use the 'disableTypography' prop of the ListItemText element.
<ListItemText
disableTypography
primary={<Typography variant="body2" style={{ color: '#FFFFFF' }}>MyTitle</Typography>}
/>
This lets you embed your own text element with whatever styling you want on it.
this is good one, you can implement without disabling typography
<ListItemText
classes={{ primary: this.props.classes.whiteColor }}
primary="MyTitle"
/>
Per the documentation, the <ListItemText /> component exposes the prop primaryTypographyProps, which we can use to accomplish what you're attempting in your question:
const text = {
color: "red"
};
<ListItem button>
<ListItemText primaryTypographyProps={{ style: text }} primary="MyText" />
</ListItem>
Hope that helps!
<ListItem >
<Avatar style={{ backgroundColor: "#ff6f00" }}>
<LabIcon />
</Avatar>
<ListItemText
primary={<Typography variant="h6" style={{ color: '#ff6f00' }}>Lab</Typography>}
secondary="Experiments" />
</ListItem>
Turns out there's an even better way to do this as such:
const styles = {
selected: {
color: 'green',
background: 'red',
},
}
const DashboardNagivationItems = props => (
<ListItemText
classes={{ text: props.classes.selected }}
primary="Scheduled Calls"
/>
)
export default withStyles(styles)(DashboardNagivationItems)
You can read more about how this is done here: https://material-ui-next.com/customization/overrides/#overriding-with-classes
Method 1
const textColor = {
color: "red"
};
<ListItemText primaryTypographyProps={{ style: textColor }} primary="BlodyLogic" />
For the Secondary Text
const secondaryColor = {
color: 'green'
}
<ListItemText secondaryTypographyProps={{ style: secondaryColor }}
secondary="If you say that you" />
Method 2
<ListItemText
primary={
<Typography variant="caption" display="block" gutterBottom>
caption text
</Typography>
}
/>
Custom design:
const useStyles = makeStyles({
text: {
color: 'red',
fontSize: 49
},
});
/.....// all make classes
<ListItemText
primary={
<Typography className={classes.text}>
caption text
</Typography>
}
/>
Offical Docs
MUI v5 update
You can leverage system properties in Typography to directly add styling props in the primary and secondary components inside the ListItemText:
<ListItemText
primary="Photos"
secondary="Jan 9, 2014"
primaryTypographyProps={{
fontSize: 22,
color: 'primary.main',
}}
secondaryTypographyProps={{
fontSize: 15,
color: 'green',
}}
/>
You can also use styled if you want to reuse ListItemText in multiple places:
import MuiListItemText from '#mui/material/ListItemText';
import { styled } from '#mui/material/styles';
const ListItemText = styled(MuiListItemText)({
'& .MuiListItemText-primary': {
color: 'orange',
},
'& .MuiListItemText-secondary': {
color: 'gray',
},
});
Live Demo
If you are using material-ui 3.x, this is how it is done:
import { withStyles } from '#material-ui/core/styles';
const styles = {
listItemText: {
color: 'white',
},
}
class YourComponent extends Component {
...
render() {
const { classes } = this.props; // this is magically provided by withStyles HOC.
return (
<ListItem button>
<ListItemIcon>
<DashboardIcon />
</ListItemIcon>
<ListItemText classes={{ primary: classes.listItemText }} primary="My Bookings" />
</ListItem>
);
...
}
export default withStyles(styles)(YourComponent);
set all your text related styles on primary property. Sad that it's hidden so deep in the documentation. https://material-ui.com/api/list-item/
Material v1.0
I would add something to #SundaramRavi in regards to:
the way he is using style element which is not great as for Material v1.0 (read the very important difference between v0.16+ and v1.0.
the way files can be structured for better separation of concern.
Whatever.styles.js
const styles = theme => ({
white: {
color: theme.palette.common.white
}
});
exports.styles = styles;
Whatever.js
const React = require('react');
const PropTypes = require('prop-types');
const {styles} = require('./Whatever.styles');
class Whatever extends React.Component {
constructor(props) {
super(props);
}
render() {
const {classes} = this.props;
return (
<div>
<ListItemText
disableTypography
primary={
<Typography type="body2" style={{body2: classes.white}}>
MyTitle
</Typography>
}
/>
</div>
);
}
}
Whatever.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired
};
exports.Whatever = withStyles(styles, {withTheme: true})(Whatever);
you can easily style text by using & span
const useStyles = makeStyles(theme => ({
listItem: {
"& span": {
color: "red"
}
}
}));
..
..
..
<ListItem button>
<ListItemIcon>
<SendIcon />
</ListItemIcon>
<ListItemText className={classes.listItem} primary="Sent mail"/>
</ListItem>
If your are using "#material-ui/core": "^4.11.4" (4.X.X or newer version) then it's simple:
#1st step: Define your styles like this:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
// Other Styling if you wish to use it
root: {
width: '100%',
maxWidth: '36ch',
backgroundColor: theme.palette.background.paper
},
// Other Styling if you wish to use it
inline: {
display: 'inline'
},
// Styling that you asked for
textColor: {
color: 'red'
}
}),
);
#2nd step: Define a constant to use the specific Styles like this:
const AlignItemsList = (props: any) => {
const classes = useStyles(); // Like this one
......
}
#3rd step: In your ListItemText component do like this:
const AlignItemsList = (props: any) => {
const classes = useStyles();
......
<ListItemText
primary="Your Text Goes Here"
classes={{ primary: classes.textColor }} // Like this one
...
/>
};
#4th & final step: Just export your component normally without any other stuff, like this:
export default AlignItemsList;
MUI v5
I recommend to you use global styles for all components. For example you can override styles when you use createTheme.
Here is small example:
export default createTheme({
components: {
MuiListItemText: {
styleOverrides: {
root: {
marginTop: 0,
marginBottom: 0,
},
primary: {
fontSize: '1rem',
},
secondary: {
fontSize: '0.8rem',
},
},
},
},
});
More details on official page

How to style MUI Tooltip?

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)}
</>
)
}

Resources