Building CampaignHawk: Connecting Tooltips with React (Part 5)

The tooltips are now properly styled but are not connected. Connecting things takes a lot longer in React than I’m used to with Blaze, but as Nick Wientge put it:

React can be very frustrating at first because it literally forces you to do things the “right” way. However, anytime I hit a wall with React I later realized it was because I was trying to do something that would have gotten me in trouble later.

I happen to agree with this sentiment, and the bigger my projects get, I find they are much more easily maintained when I use React.

Now is a good time to give some thought to the functions we need to pass down to the child components. SidenavTooltip will need to know the x and y position of the cursor on hover and whether or not the tooltip should be visible. SidenavIcons will need to know when each item is being hovered-over to tell the parent component to show the tooltip.

<SidenavTooltip 
showTooltip={this.state.showTooltip}
tooltipX={this.state.tooltipX}
tooltipY={this.state.tooltipY}/>

In the component above, we’re passing the x and y position of tooltipX and tooltipY to tell our SidenavTooltip where to go. In the SidenavIcons component below, we’re passing two functions to change the state of showTooltip to either true or false based on whether an icon is being hovered over or not.

<SidenavIcons 
showTooltip={this.showTooltip}
hideToolip={this.hideTooltip} />

First let’s go into SidenavTooltip and set the inline style we talked about earlier:

tooltipStyle = {
top: this.props.tooltipY,
left: this.props.tooltipX

}

Then we need to change the opacity based on the status of showTooltip:

if (this.props.showTooltip) {
tooltipStyle.opacity = "1";
tooltipStyle.visibility = "visible";
} else {
tooltipStyle.opacity = "0";
tooltipStyle.visibility = "hidden";
}

We’re not quite done with tooltips. We need to change the content of the tooltip based on the icon being hovered over. To do this, we’ll have to change our icons into objects with a name and a description. For the sake of space, I’m not going to fill out all items. You should get an idea from the example below:

let iconList = [
{name: "fa fa-database", description: "Data Layers"},
...

You’ll also have to change the key and className to item.name in your map function.

In Sidenav, add a new initial state called tooltipDescription:

...
tooltipDescription: "",
...

And since Sidenav is the component that ultimately handles the name of the tooltip, we need to create a new function to set tooltipDescription:

setTooltipDescription(item) {
this.setState({
tooltipDescription: item.description
})
},

We also need to pass the value of tooltipDescription into SidenavTooltip and pass the setTooltipDescription function into SidenavIcons.

<SidenavTooltip
tooltipDescription={this.state.tooltipDescription}
...

…And:

<SidenavIcons
setTooltipDescription={this.setTooltipDescription}
...

Then we want to add an onMouseEnter event in our SidenavIcons to bind to item so we can set tooltipDescription, an onMouseOver event to keep the tooltip showing while the mouse is over the icon, and an onMouseOut event to stop it from showing.

<li key={item.name}
onMouseEnter={this.props.setTooltipDescription.bind(null, item)}
onMouseOver={this.props.showTooltip}

onMouseOut={this.props.hideTooltip}
...

And the last thing we need to do to finish the tooltips is set the tooltipDescription in the SidenavTooltip component using this.props.tooltipDescription that we passed in from Sidenav.

<div className="sidenav-tooltip" style={tooltipStyle}>
<p>{this.props.tooltipDescription}</p>

The last thing to change is the width of the tooltip box.

First remove the width property from sidenav-tooltip. This is just another CSS property that we need to add to our paragraph tag .

p {
color: $default-text-color;
white-space: nowrap;
font-size: 1.5em;
padding: 10px;
align-self: center;
}

At this point, the app looks like the example below. There is no map and no real functionality. Just a nice sidenav with icons and tooltips.

Next Steps

Now that our tooltips behave properly, we need to build some modals. Most of the tools in our sidenav will trigger a modal, so we need to make sure they’re decent.