Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to show an Ant Design Tooltip conditionally only when the content has ellipsis?

Tags:

reactjs

antd

I'm using the Ant Design component <Paragraph> to show a text with a variable size, and I use the ellipsis option to show "..." when that text exceeds the length of its container.

I also added a <Tooltip> to that <Paragraph> to show the entire text when it is collapsed:

<Tooltip title="This text is displayed, so I don't want to show a tooltip.">
  <Paragraph ellipsis>
    This text is displayed, so I don't want to show a tooltip.
  </Paragraph>
</Tooltip>

Unfortunately, I can't find a way to know when the ellipsis appears on the paragraph, so my Tooltip is always shown.

tooltip-shows-on-a-fully-displayed-text

Is it possible to show an Ant Design Tooltip only when the content has been affected by the ellipsis option?

like image 334
Óscar Giménez Avatar asked Nov 02 '25 03:11

Óscar Giménez


2 Answers

Ant Design v4.2.0 made that possible by adding an "onEllipsis" function to the "ellipsis" object.

TooltipParagraph API

Working example

const TooltipParagraph: React.FC<ParagraphProps> = ({
  children,
  ellipsis,
  ...props
}) => {
  const [truncated, setTruncated] = useState(false);

  return (
    <Tooltip title={truncated ? children : undefined}>
      <Paragraph
        {...props}
        ellipsis={{ ...ellipsis, onEllipsis: setTruncated }}
      >
        {/* NOTE: Fragment is necessary to avoid showing the title */}
        <>{children}</>
      </Paragraph>
    </Tooltip>
  );
};
like image 131
Alex Avatar answered Nov 03 '25 17:11

Alex


I do not know about antdegin, But I faced this problem once and I was able to resolve it.

To know if an text tag has overflown this check will be truthy:

element.offsetWidth < element.scrollWidth.

I tried to think about a generic way to solve this issue and ended up with this component (this is not production ready!)


function SmartText({
  TypographyComponent = "h1",
  TypographyComponentProps = {},
  TooltipComponent = ({ children }) => children, // just for demo purpose, it will do nothing basically if not passed
  ToolTipComponentProps = {},
  children = ""
}) {
  const textComponentRef = React.useRef(null);
  const [tooltipTitle, setTooltipTitle] = React.useState("");

  React.useEffect(() => {
    if (
      textComponentRef.current &&
      textComponentRef.current.offsetWidth <
        textComponentRef.current.scrollWidth
    ) {
      setTooltipTitle(textComponentRef.current.innerText);
    }
  }, [children]);

  return (
    <TooltipComponent {...ToolTipComponentProps} title={tooltipTitle}>
      <TypographyComponent {...TypographyComponentProps} ref={textComponentRef}>
        {children}
      </TypographyComponent>
    </TooltipComponent>
  );
}

The TypographyComponent in your case is the Paragraph, to use this method, the TypographyComponent has to forward the ref or to support it.

I used the SmartText with @material-ui tooltip like this:

<SmartText
  TypographyComponentProps={{
    style: {
      whiteSpace: "nowrap",
      maxWidth: 500,
      textOverflow: "ellipsis",
      overflow: "hidden",
      textAlign: "left"
    }
  }}
  TooltipComponent={Tooltip}
  ToolTipComponentProps={{
    placement: "right"
  }}
>
  Tooltip is needed because this text is long
</SmartText>
<SmartText
  TypographyComponentProps={{
    style: {
      whiteSpace: "nowrap",
      maxWidth: 300,
      textOverflow: "ellipsis",
      overflow: "hidden",
      textAlign: "left"
    }
  }}
  TooltipComponent={Tooltip}
  ToolTipComponentProps={{
    placement: "right"
  }}
>
  No tooltip needed
</SmartText>

Finally, here is working codesandbox demo

like image 35
Incepter Avatar answered Nov 03 '25 16:11

Incepter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!