How to Make Clickable MUI Badges and Badges with Tooltips

The MUI Badge renders as two spans: one that wraps the anchor component and one that renders the ‘visible’ Badge area. This means click and hover events fire for the Badge even when the events occur on the anchor component.

In this tutorial we will solve this problem. We will make the Material-UI Badge on the Button seen below, and we will ensure only the red Badge area is clickable and shows a Tooltip.

MUI Badge with Tooltip
MUI Badge with Tooltip

Full React example code is in the sections below.

How to Make the MUI Badge Clickable

We can add an onClick prop and handler to the MUI Badge easily, but we run into a problem: the onClick fires whenever the component wrapped in the Badge is clicked

This is because the Badge renders as a wrapping span and an inner child span (the visible badge, see the DOM screenshot below). The click event fires on click of the visible badge or the wrapping span.

Clickable MUI Badge
Clickable MUI Badge

There are likely a couple of ways to control this, but the easiest is to add onClick to the Badge and detect which node was clicked (the wrapped element or the visible badge span). Here’s the code:

import Badge from "@mui/material/Badge";
import Button from "@mui/material/Button";

export default function CustomBadges() {
  const handleClick = (
    event: React.MouseEvent<HTMLSpanElement, MouseEvent>
  ) => {
    if ((event.target as HTMLElement).nodeName === "SPAN") {
      console.log("Badge Clicked!");
    }
  };

  return (
    <Badge
      badgeContent="BB"
      color="error"
      onClick={handleClick}
    >
      <Button variant="contained">Badge Me Too!</Button>
    </Badge>
  );
}

The important thing to notice inside the handleClick function is that the code detects if the clicked node is of type SPAN. This may seem odd if you recall that I said a Badge span wraps the Button. However, the highest event.target node on hover over the Button is of type BUTTON, so we are safe to check for SPAN.

If you are not using TypeScript, change (event.target as HTMLElement).nodeName simply to event.target.nodeName. This was a quick way to retype event.target so that the compiler knew nodeName would be an available field.

How to Add Tooltip to Material-UI Badge

Adding a Tooltip to the Badge presents similar challenges to adding click event handling to the Badge: we only want to have the Tooltip appear on hover of the visible Badge, not on hover of the wrapped child.

The challenge was similar, and the solution is also similar. We need to detect node type on hover and limit the Tooltip popup to node type SPAN.

const [tooltipOpen, setTooltipOpen] = useState(false);

const handleHover = (
  event: React.MouseEvent<HTMLSpanElement, MouseEvent>
) => {
  if ((event.target as HTMLElement).nodeName === "SPAN") {
    setTooltipOpen(!tooltipOpen);
  } else {
    setTooltipOpen(false);
  }
};

<Tooltip title="<<< Badge Tooltip" open={tooltipOpen} placement="right-start">
  <Badge
    badgeContent="TT"
    color="error"
    onMouseOver={handleHover}
    onMouseOut={handleHover}
  >
    <Button variant="contained">Badge Me Too!</Button>
  </Badge>
</Tooltip>

There are three primary additions to this code compared to the code for making Badges clickable:

  • The Tooltip JSX
  • onMouseOver and onMouseOut events
  • The tooltipOpen state value

One important aspect of opening the Tooltip only on Badge hover is that the Tooltip needs to appear near the actual Badge. We can partially accomplish this with the Tooltip position prop. Here’s how to more precisely position the Tooltip.

Next, if we code the handler properly then we can use the same hover handler for onMouseOver and onMouseOut. Notice how the handler always closes the Tooltip if the hover event is over the Button, but opens or closes based on current state for hover over/out of the visible Badge span.

Resources and Related Links

Check out these additional useful MUI posts:

Material-UI Badge Docs

Material-UI Tooltip Docs

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.