How to style Material UI Tooltip?
Asked Answered
S

15

86

How can I style the Material UI Tooltip title? 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?

Shipwright answered 21/4, 2016 at 4:55 Comment(0)
D
90

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);

Edit Tooltip customization

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);

Edit Tooltip customization

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

Drugget answered 9/2, 2019 at 14:6 Comment(2)
I am just curious, why do we need to create the styled component in this way? styled(({ className, ...props }) => ( <Tooltip {...props} componentsProps={{ tooltip: { className: className } }} /> ) Why styled(Tooltip) is not working in this case?Jairia
@Jairia styled(Tooltip) would result in applying styles via the className prop, but Tooltip passes along most props that it receives (including className) to the child element that it wraps (probably so that a component wrapped with Tooltip can receive props in largely the same way as if it weren't wrapped by Tooltip), so styled(Tooltip) would actually style the wrapped element rather than the tooltip.Drugget
K
70

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',
        },
      },
    },
  },
});

Codesandbox Demo

Kriegspiel answered 3/11, 2021 at 8:27 Comment(3)
How can I use this on another component, like a simple div or Typography ?Heterochromosome
@Heterochromosome The same as what I did with the Button in my answer. Is there anything wrong?Kriegspiel
I had to change compoentsProps into slotProps but otherwise it worked :)Aurum
T
17

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 :

Edit modest-allen-6ubp6

Toomer answered 12/11, 2019 at 8:37 Comment(2)
Most simple answer so far. In my case I could also styled <span> with styled-components.Haloid
@LucasAndrade yeah right , i'm happy that it was helpful for you , good luckToomer
D
14

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.

Dubenko answered 21/4, 2016 at 13:49 Comment(0)
N
13

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>
    </>
  );
};
Nashner answered 11/3, 2020 at 18:29 Comment(3)
There seems to be an "edge" case that I have stumbled on to. If the children of <Tooltip> are functional components then React throws a warning message that refs cannot be passed to functional components. So if I have something like <Tooltip>StyleMenu/></Tooltip>. It works but react throws a warning message indicating the ForwardRef should be used? How do I handle that?Mcmullan
This worked better as passing a span only colored the area that span covered so the outlying area of the tooltip still had the default color, this method changes the tooltip back groundHyperplane
which version of MUI covers this?Paredes
B
3

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>
);
Bushtit answered 23/12, 2021 at 21:53 Comment(0)
C
3

For me, after trying multiple solutions which didn't work, I found this and this is working perfect:


    <Tooltip
                open={!!tooltipContent}
                title={tooltipContent}
                onClose={hideTooltip}
                style={{
                  position: "fixed",
                  top: tooltipPosition.top,
                  left: tooltipPosition.left,
                }}
                componentsProps={{
                  tooltip: {
                    sx: {
                      bgcolor: state
                        ? ThemeColors.warning
                        : ThemeColors.warningdark,
                    },
                  },
                }}
              >
....
              </Tooltip>

Cutin answered 9/8, 2023 at 8:27 Comment(1)
Really appreciate for posting out! componentsProps solution was the only working to disable maxWidth properly of the Tooltip box!Einkorn
S
1

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>
  );
Sherysherye answered 4/9, 2020 at 19:40 Comment(0)
A
1

For me, while using v5 and the sx prop, this worked:

<Tooltip
  slotProps={{
    tooltip: {
      sx:{
        [`&.${tooltipClasses.tooltip}`]: {
          backgroundColor: "red",
          color: "white"
        }
      }
    }
  }}
  arrow
  title="This is a test"
>

Using componentProps wasn't working for some reason. slotProps yielded the correct result.

Aurum answered 13/6, 2023 at 9:22 Comment(1)
It worked for me but with following changes: slotProps: {{ popper: { sx: { [& .${tooltipClasses.tooltip}]: {...style} } } }} Notice the extra space between & and period. also replacement of "tooltip" to "popper"Bueschel
E
0

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;
Electrocardiograph answered 8/10, 2021 at 22:26 Comment(0)
P
0

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;
  }
`;
Purusha answered 17/5, 2022 at 11:14 Comment(0)
A
0

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)}
        </>
    )
}
Auliffe answered 2/9, 2022 at 16:14 Comment(0)
A
0

We can customize tooltip style in the following way

import CheckCircleIcon from '@material-ui/icons/CheckCircle'
import ErrorIcon from '@material-ui/icons/Error'
import { withStyles } from '@material-ui/core/styles'
import Tooltip from '@material-ui/core/Tooltip'
// import getOr from 'lodash/fp/getOr'
import isEmpty from 'lodash/fp/isEmpty'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './styles'


const Component = ({
    classes,
    value
}) => {
    const LightTooltipSuccess = withStyles(theme => ({
        tooltip: {
            backgroundColor: '#16181a',
            border: '2px solid limegreen',
            borderRadius: '2px',
            fontSize: 12,
            width: '300px'
        },
    }))(Tooltip)

    const LightTooltipFailure = withStyles(theme => ({
        tooltip: {
            backgroundColor: '#16181a',
            border: '2px solid red',
            borderRadius: '2px',
            fontSize: 12,
            width: '300px'
        },
    }))(Tooltip)

    const RenderValidated = isValidated => {
        return isEmpty(isValidated)
            ? <LightTooltipSuccess {...{
                placement: 'top',
                title: 'Success: Request row has been submitted'
            }}>
                <CheckCircleIcon className={classnames(classes.icon, classes.success)}/>
            </LightTooltipSuccess>
            : <LightTooltipFailure {...{
                placement: 'top',
                title: `Error: ${isValidated.join(', ')}` // Error: ${getOr([], isValidated).join(', ')}`
            }}>
                <ErrorIcon className={classes.icon} color='error'/>
            </LightTooltipFailure>
    }

    return RenderValidated(value)
}

Component.displayName = 'ValidatedFramework'
Component.propTypes = {
    classes: PropTypes.shape({
        icon: PropTypes.string.isRequired,
        success: PropTypes.string.isRequired
    }),
    value: PropTypes.arrayOf(PropTypes.string).isRequired
}

export default withStyles(styles)(Component)
Auliffe answered 20/4, 2023 at 5:19 Comment(0)
T
0
"& .MuiTooltip-arrow": {
      color: #f2f2f2,
 }
Tysontyumen answered 2/12, 2023 at 8:54 Comment(0)
S
0

Short Story use 'classes' props to style the tooltip not the color of the arrow is 'color' not 'background-color' for tailwind text-[color] not bg-[color]

classes={{tooltip: "bg-white text-black",arrow: "bg-white text-white"}} 

Below is a complete illustration of how to use it with a slider

import { styled } from "@mui/material/styles";
import Slider, {
    SliderValueLabelProps,
  } from "@mui/material/Slider";
  import Tooltip from "@mui/material/Tooltip";

function ValueLabelComponent(props: SliderValueLabelProps) {
        const { children, value } = props;
        return (
          <Tooltip open={true} enterTouchDelay={0} placement="top" 
          classes={{
                tooltip: "bg-white text-black",
                arrow: "bg-white text-white"}} 
           title={value} arrow
          >
            {children}
          </Tooltip>
        );
      }

<CustomSlider
          value={value}
          onChange={handleChange}
          valueLabelDisplay="auto"
          slots={{valueLabel:ValueLabelComponent}}
          />

const CustomSlider = styled(Slider)({
    color: "#000",
    height: 8,
    "& .MuiSlider-track": {
      border: "none",
    },
    "& .MuiSlider-thumb": {
      height: 0,
      width: 0,
      backgroundColor: "#fff",
      border: "0px solid currentColor",
      "&:focus, &:hover, &.Mui-active, &.Mui-focusVisible": {
        boxShadow: "inherit",
      },
      "&::before": {
        display: "none",
      },
    },
 
    "& .MuiSlider-valueLabel": {
      lineHeight: 1.2,
      fontSize: 12,
      background: "unset",
      padding: 0,
      width: 32,
      height: 32,
      borderRadius: "50% 50% 50% 0",
      backgroundColor: "#52af77",
      transformOrigin: "bottom left",
      transform: "translate(50%, -100%) rotate(-45deg) scale(0)",
      "&::before": { display: "none" },
      "&.MuiSlider-valueLabelOpen": {
        transform: "translate(50%, -100%) rotate(-45deg) scale(1)",
      },
      "& > *": {
        transform: "rotate(45deg)",
      },
    },
  });
Seascape answered 11/5 at 19:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.