reactjsreact-reduxtooltipmaterial-uiellipsis

React show Material-UI Tooltip only for text that has ellipsis


Looking for a way to have material-ui's tooltip expand the text in a table cell ONLY if the text is cut off with an ellipsis (overflowing).

Currently in my table I have a cell like this:

<TableCell className={classes.descriptionCell}>{row.description}</TableCell>

and my styling for descriptionCell is like this:

    descriptionCell: {
        whiteSpace: 'nowrap',
        maxWidth: '200px',
        overflow: 'hidden',
        textOverflow: 'ellipsis'
    }

This makes the text behave the way I would like it to in this table, but I want to be able to hover and view the rest of it in a tooltip, preferably Material-UI's built in tooltip component.

I know there is a package that exists here https://www.npmjs.com/package/react-ellipsis-with-tooltip which should do this, BUT it uses bootstrap tooltip, not material UI.


Solution

  • To go off of @benjamin.keen answer. Here is a standalone functional component which is just an extension of his answer using hooks to perform the comparison functions.

    import React, { useRef, useEffect, useState } from 'react';
    import Tooltip from '@material-ui/core/Tooltip';
    const OverflowTip = props => {
      // Create Ref
      const textElementRef = useRef();
    
      const compareSize = () => {
        const compare =
          textElementRef.current.scrollWidth > textElementRef.current.clientWidth;
        console.log('compare: ', compare);
        setHover(compare);
      };
    
      // compare once and add resize listener on "componentDidMount"
      useEffect(() => {
        compareSize();
        window.addEventListener('resize', compareSize);
      }, []);
    
      // remove resize listener again on "componentWillUnmount"
      useEffect(() => () => {
        window.removeEventListener('resize', compareSize);
      }, []);
    
      // Define state and function to update the value
      const [hoverStatus, setHover] = useState(false);
    
      return (
        <Tooltip
          title={props.value}
          interactive
          disableHoverListener={!hoverStatus}
          style={{fontSize: '2em'}}
        >
          <div
            ref={textElementRef}
            style={{
              whiteSpace: 'nowrap',
              overflow: 'hidden',
              textOverflow: 'ellipsis'
            }}
          >
            {props.someLongText}
          </div>
        </Tooltip>
      );
    };
    
    export default OverflowTip;