vijayscode
vijayscode

Reputation: 2025

Show hide multiple tooltips React material

I'm using React material framework in one of my projects. I'm trying to add multiple controlled tooltips which are going to be visible only when their respective state is visible.

Unfortunately, right now I'm stuck because I'm sharing the same state with multiple components hence all the tooltips are visible once you hover on any one of them. Is there any way to do so ? I think this can be done by array.

P.S there are going to be multiple parent components inside a page each having three set of tooltip i.e Edit, Delete, View

class ControlledTooltips extends React.Component {
  state = {
    open: false,
  };

  handleTooltipClose = () => {
    this.setState({ open: false });
  };

  handleTooltipOpen = () => {
    this.setState({ open: true });
  };

  render() {
    return (
      <div>
        <Tooltip
          enterDelay={300}
          id="tooltip-controlled"
          leaveDelay={300}
          onClose={this.handleTooltipClose}
          onOpen={this.handleTooltipOpen}
          open={this.state.open}
          placement="bottom"
          title="Edit"
        >
          <IconButton aria-label="Delete">
            <Edit />
          </IconButton>
        </Tooltip>
        <Tooltip
          enterDelay={300}
          id="tooltip-controlled"
          leaveDelay={300}
          onClose={this.handleTooltipClose}
          onOpen={this.handleTooltipOpen}
          open={this.state.open}
          placement="bottom"
          title="view"
        >
          <IconButton aria-label="view">
            <Visibility />
          </IconButton>
        </Tooltip>
        <Tooltip
          enterDelay={300}
          id="tooltip-controlleded"
          leaveDelay={300}
          onClose={this.handleTooltipClose}
          onOpen={this.handleTooltipOpen}
          open={this.state.open}
          placement="bottom"
          title="Delete"
        >
          <IconButton aria-label="Delete">
            <DeleteOutlined />
          </IconButton>
        </Tooltip>
      </div>
    );
  }
}

codesandbox link

Any help will be appreciated :)

Upvotes: 1

Views: 2608

Answers (2)

Einar &#211;lafsson
Einar &#211;lafsson

Reputation: 3187

I would advise against complicating your component state too much. In my opinion, each component should control a very precise part of its state.

What I would recommend is to create a custom tooltip that will handle the state for each element. You can build your 3 Edit, Delete, View width them.

class TooltipCustom extends React.Component {
  state = {
    open: false
  };

  toggleState = () => {
    this.setState({ open: !this.state.open });
  };

  render() {
    return (
      <IconButton aria-label={this.props.title}>
        <Tooltip
          enterDelay={300}
          leaveDelay={300}
          onClose={this.toggleState}
          onOpen={this.toggleState}
          open={this.state.open}
          placement="bottom"
          title={this.props.title}
        >
          {this.props.children}
        </Tooltip>
      </IconButton>
    );
  }
}

const Delete = () => (
  <TooltipCustom title="delete">
    <DeleteIcon />
  </TooltipCustom>
);

const Edit = () => (
  <TooltipCustom title="Edit">
    <EditIcon />
  </TooltipCustom>
);

const View = () => (
  <TooltipCustom title="View">
    <VisibilityIcon />
  </TooltipCustom>
);

const ControlledTooltips = () => (
  <div>
    <Delete />
    <Edit />
    <View />
  </div>
);

Upvotes: 2

vijayscode
vijayscode

Reputation: 2025

In case someone is looking for an answer. As suggested by @Einar Ólafsson, I made a custom tooltip wrapper which had all three tooltips inside it.

Tooltip name which was needed to be shown was passed to handleTooltipOpen() and handleTooltipClose() function. Inside this function, I changed the state of the individual tooltip.

class ControlledTooltips extends React.Component {
  state = {
    edit: false,
    delete: false,
    view: false
  };
  handleTooltipClose = (name) => {
    this.setState({ [name]: false });
  };

  handleTooltipOpen = (name) => {
    this.setState({ [name]: true });
  };

  render() {
    return (
      <div>
        <Tooltip
          id="tooltip-controlled-delete"
          onClose={() => this.handleTooltipClose("delete")}
          onOpen={() => this.handleTooltipOpen("delete")}
          open={this.state.delete}
          placement="bottom"
          title="Delete"
        >
          <IconButton name="delete" aria-label="Delete">
            <DeleteOutlined name="delete" />
          </IconButton>
        </Tooltip>
        <Tooltip
          id="tooltip-controlled-edit"
          onClose={() => this.handleTooltipClose("edit")}
          onOpen={() => this.handleTooltipOpen("edit")}
          open={this.state.edit}
          placement="bottom"
          title="edit"
        >
          <IconButton name="edit" aria-label="edit">
            <Edit />
          </IconButton>
        </Tooltip>
        <Tooltip
          id="tooltip-controlled-view"
          onClose={() => this.handleTooltipClose("view")}
          onOpen={() => this.handleTooltipOpen("view")}
          open={this.state.view}
          placement="bottom"
          title="view"
        >
          <IconButton name="view" aria-label="view">
            <Visibility />
          </IconButton>
        </Tooltip>
      </div>
    );
  }
}

Upvotes: 0

Related Questions