Conditionally show Tooltip depending on parent Popper component being open

1.8k views Asked by At

I am trying to understand the best way of conditionally showing a Tooltip, based on if a sibling component Popper is open or not. I want to to show it by default on hover of its child the ButtonBase. I want the tooltip to never be open if the Popper is open. The tooltip title is acting as a summary of what's selected in the options list in the Popper when its closed, having it open with the Popper open is not ideal and cluttered. I am new to hooks so trying to understand how I can incorporate a hook to set the tooltipOpen state correctly with the conditional need.

export default function TooltipWithPopper() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [value, setValue] = React.useState([options[1], options[11]]);
  const [pendingValue, setPendingValue] = React.useState([]);
  const [tooltipOpen, setTooltipOpen] = React.useState(false);

  const handleClick = (event) => {
    setPendingValue(value);
    setAnchorEl(event.currentTarget);
    setTooltipOpen(false);
  };

  const handleClose = (event, reason) => {
    if (reason === "toggleInput") {
      return;
    }
    setValue(pendingValue);
    if (anchorEl) {
      anchorEl.focus();
    }
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? "github-label" : undefined;

  return (
    <React.Fragment>
      <div className={classes.root}>
        <Tooltip title={value.map((i) => i.title).join(", ")}>
          <ButtonBase
            disableRipple
            className={classes.button}
            aria-describedby={id}
            onClick={handleClick}
          >
            <span>Label</span>
            {value.length}/{options.length}
          </ButtonBase>
        </Tooltip>
      </div>
      <Popper
        id={id}
        open={open}
        anchorEl={anchorEl}
        placement="bottom-start"
        className={classes.popper}
      >
        <Autocomplete
          open
          onClose={handleClose}
          multiple
          classes={{
            paper: classes.paper,
            option: classes.option,
            popperDisablePortal: classes.popperDisablePortal
          }}
          value={pendingValue}
          onChange={(event, newValue) => {
            setPendingValue(newValue);
          }}
          disableCloseOnSelect
          disablePortal
          renderTags={() => null}
          noOptionsText="No labels"
          .....
        />
      </Popper>
    </React.Fragment>
  );
}

Here is a demo of the tooltip being applied to the trigger element. How can I set it to only be open depending on another components' state? I've tried adding a setTooltipOpen(false) call when the handleClick is called when opens the Popper.

Demo: https://codesandbox.io/s/material-demo-forked-0wgyh?file=/demo.js:0-6181

1

There are 1 answers

0
95faf8e76605e973 On

You can control the Tooltip open prop value with your tooltipOpen state (implementation is up to you) and provide conditions that if the Popper is open, then automatically, the Tooltip open prop value computation will disregard the tooltipOpen state and assign false.

In my example below, I control the tooltipOpen state via onMouseEnter && onMouseLeave events

<Tooltip
  open={open === true ? false : tooltipOpen}
  title={value.map((i) => i.title).join(", ")}
>
  <ButtonBase
    disableRipple
    className={classes.button}
    aria-describedby={id}
    onClick={handleClick}
    onMouseEnter={() => setOpen(true)}
    onMouseLeave={() => setOpen(false)}
  >
    <span>Label</span>
    {value.length}/{options.length}
  </ButtonBase>
</Tooltip>

Edit Material demo (forked)