hotcakedev
hotcakedev

Reputation: 2504

How to pass a custom component to title props in MUI tooltip?

I am trying to customize a Tooltip component by passing a custom component like the image.

enter image description here

At first time, I've used Popover once, but the main reason why I am going to use Tooltip is because of the arrow of Tooltip.

Basically, I am using React and MUI v5 running on TypeScript.

I built a custom Tooltip component like this.

    <Tooltip
      open={open}
      arrow
      placement={placement}
      title={
        <Box component="span" p={1} width={width}>
          <IconButton size="small" onClick={onClose}>
            <CloseIcon />
          </IconButton>
          <Box my={2} px={4}>
            <Typography my={2}>
              {message}
            </Typography>
            <FormControlLabel control={<Checkbox defaultChecked />} label="Don’t show again" />
          </Box>
        </Box>
      }
      {...rest}
    >
      {children}
    </Tooltip>

It seems to be working, but it keeps saying an error message Tooltip title. Zero-length titles string are never displayed. 'title' is specified more than once, so this usage will be overwritten.ts(2783).

How can I resolve this issue, or should I use Popover rather than Tooltip component?

enter image description here

Upvotes: 2

Views: 9100

Answers (2)

KARTHIKEYAN.A
KARTHIKEYAN.A

Reputation: 20088

We can pass custom compoenent as title props in the following way

import { withStyles } from '@mui/material/styles'
import WarningRoundedIcon from '@mui/icons-material/WarningRounded'
import CheckCircleIcon from '@mui/icons-material/CheckCircle'
import ErrorIcon from '@mui/icons-material/Error'
import Alert from '@mui/material/alert'
import Tooltip from '@mui/material/Tooltip'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './styles'


const Component = ({
    classes,
    message,
    status
}) => {

    const LightTooltip = withStyles(theme => ({
        tooltip: {
            borderRadius: '2px',
            fontSize: 12,
            padding: 0,
            width: '300px',
        },
    }))(Tooltip)

    const CustomTooltipComponent = ({status, color, message, icon}) => (<LightTooltip
        arrow
        placement={'top'}
        title={
            <Alert severity={status} style={{ border: `1px solid ${color}`}} >
                <strong>{status.charAt(0).toUpperCase() + status.slice(1)} : </strong>{message.join(', ')}
            </Alert>
        }
    >
        {icon}
    </LightTooltip>)

    const RenderValidated = isValidated => {
        switch (isValidated) {
            case 'success':
                return (<CustomTooltipComponent
                    status={isValidated}
                    color={'green'}
                    icon={<CheckCircleIcon className={classnames(classes.icon, classes.success)}/>}
                    message={[ 'Request row has been submitted' ]}
                />)
            case 'error':
                return (<CustomTooltipComponent
                    status={isValidated}
                    color={'red'}
                    icon={<ErrorIcon className={classes.icon} color='error'/>}
                    message={message}
                />)
            case 'warning':
                return (<CustomTooltipComponent
                    status={isValidated}
                    color={'orange'}
                    icon={<WarningRoundedIcon className={classes.icon} color='warning'/>}
                    message={message}
                />)
        }
    }

    return RenderValidated(status)
}

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

export default withStyles(styles)(Component)

Upvotes: 0

m51
m51

Reputation: 2010

You need to move title prop after {...rest} parameters.

It looks like your rest paramaters already have title property inside, so basically you are overwriting your title with something else from rest parameters (at least typescript thinks that).

It is the same as:

const foo = { title: 'aaaa', sth: 'cccc' };

const bar = { title: 'bbbb', ...foo}

console.log(bar.title); // => 'aaaa'

If you open this code in some environment with typescript support, it will also show same error as yours, see

Edit TypeScript Playground Export

What you need to do is:

const foo = { title: 'aaaa', sth: 'cccc' };

const bar = { ...foo, title: 'bbbb' };

console.log(bar.title); // => 'bbbb'

Upvotes: 2

Related Questions