Using the on:mouseover Event to Create Tooltips With Svelte

Revealing more information to the user via a tooltip

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Better Data Visualizations with Svelte course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Better Data Visualizations with Svelte, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Better Data Visualizations with Svelte
  • [00:00 - 01:25] Hey everyone, in this lesson we're going to bring our chart to the next level by adding some interactivity, specifically in the form of a tooltip. To describe exactly what we want, as we hover over each of these individual circle elements , we want to know what country is being referenced. Right now it's pretty pointless to see all of these grouped. I mean maybe we can see some like aggregate trends, but we want to know what countries are being referenced by each individual circle, to see the outliers, to see interesting trends, etc. So the way that we're going to do that, we're going to basically address three things. First we're going to need hover events on each individual circles. So I hover, something happens. Second we need a variable to keep track of the hover data point. So whenever I hover I don't just want to like console log the country, I want to keep track of which country is being hovered over. And then third a tooltip that is rendered if and when a hovered country exists. Right so if I leave we want to reset hovered country to be null, and we don't want to render a tooltip. But if and when hovered exists, aka I am hovering over a circle, that's when we want to render a tooltip. And to keep things nicely separated, we'll add this tooltip based logic on its own tooltip component. So let's tackle number one, which is adding a hovered event to each circle. Okay, so within our circles, in our each block, so I'm going to close that so it's a bit easier to read.

    [01:26 - 03:02] We can add a hover event by using on mouse over. And what do we want to do? For now, let's just console dot log hover. Sorry, let's console dot log node. Now if I save this, you'll see that as I move over new circles, the console consistently updates and shows the new country that I am hovering over. Easy enough. You're going to notice that felt well yell at you at first by saying on mouse over, also needs to have on focus. So let's go ahead and add that at the exact same handler. This would now make these keyboard accessible if they had the proper tab index. So that on focus, using a keyboard, you would see the same information. And let's go ahead and add a tab index. You'll remember we did this in the last lesson. So they are in fact focusable. Let's add a tab index of zero. Now if I go here, and if I go into my chart and I tab, you'll see each of these elements are accessible via the keyboard. So we've added a hover event. But obviously we don't want to, you can ignore this because this is an interactive element according to our code, I believe. So sorry, this is going to be annoying to read. So we go ahead and disable that if you'd like so that it doesn't have that compiler yellow underline. Anyway, we have console log node, but we don't want to console log it. We want to set a variable equal to the node if and when we hover. Up in our script tag, let's go ahead and create a new variable, call it hovered by default.

    [03:03 - 04:32] This is going to be undefined, or you can make it null by by default. Either one doesn't matter. We're just going to make it hovered alone. And this will make it undefined. And then let's go ahead and keep track of what we are covering over by console. I've covered any time that it changes. So now within our mouse over and focus events, we don't want to console log, we want to reset hovered to be equal to node. Let's do that on both mouse over and on focus. Now if we hover over, we'll see that these consoles are doing the exact same thing. The difference is their console logging a variable called hovered, which we can keep track of throughout our application. Finally, let's add a mouse leave event as well. So we do on mouse leave, and we say whenever you leave the circle, make hovered equal to nothing. You could either do this on the individual circle element so that it goes back to null, or you could do it on the larger parent called inner chart, so that the tool tip will stay until you leave the chart itself. This is really personal preference. Notice how now it's not going to become null until I leave the entire chart. That's the main difference. So this is personal preference. I'm going to leave it here for now. So whenever I leave the larger chart body, hover will be reset to null. So what do we want to do from here? Well, we have a hovered variable that is updating whenever I hover over a circle. That's great.

    [04:33 - 09:30] And from here, we basically want to say if hovered exists, let's go ahead and render a new element. In our case, it'll be called a tool tip. Now where do we want that tool tip to live? Well, it's going to be an HTML element, right? And so we don't want it to live inside of an SVG tag. Remember that SVG elements contain groups , text elements, circle elements. They don't contain divs. And we want our tool tip to be a div. So let's go ahead and under our SVG tag directly under that. Let's add a new reactive block, an if block, that says if hovered exists, render something inside. In our case, we're going to want to render a new component that we haven't created yet that we will. It's called tool tip. Now what do we want tool tip to accept? Let's give it a single property called data. And data will be equal to hovered. Remember that here the syntax is what is the name of the prop within tool tip, right? So whenever we create the file, we will accept data. And its value is equal to what is currently called hovered within the larger app dots felt. So if we wanted to make it easier, like we could call it hovered in both tool tip and an app dots felt. But I like the idea of data as a name for rendering and tool tip. So I'm going to keep this. Then I'm going to end the if block and save. At first you're going to see that there's an error because tool tip is not defined, obviously. So let's go ahead and address this by first importing a new component called tool tip from tool tip dots felt. Again, the issue is that this doesn't exist. So let's go ahead and create tool tip dots felt. And what do we want to do in our script tag? We want to accept the prop that we just passed, which is going to be called data. Let's go ahead and verify this is working by console logging data with int tool tip dots felt. If I hover over a circle, you 're at first going to see an error, which is not great. And I think you might need to refresh your page. Yep, okay. Now you're going to see that you're going to have two consoles for every hover event. The first is going to be from app dots felt right here. The second is from tool tip dots felt. And it looks like these data elements are, in fact, identical. These are both referencing this country. And so that means that we're definitely doing something right. We are passing the proper value into tool tip dots felt to keep things clean. Let's go ahead and delete this console dot log, move these together. And now we can handle pretty much all of our, the remainder of this lesson within the tool tip dot spell component. And this really illustrates why this component driven design is really helpful because if we're working on a discrete functionality rendering a tool tip, we don't want to clog up our existing script tag and app dots felt, we can keep it all in its own file, which I think is quite nice. So what do we want to do here? We know what data contains. It contains a continent, a country, a happiness score, and then some internals that were created from the internal physics engine from D three fours, VX, VY, X and Y. So what we want to do is render a tool tip at the X and Y position that are circle currently occupies, right? So if I hover over this country, I'll notice, MART, MIRIT, I'm not going to try to say that country. It has an X value of 354 and a Y value of 294. And that is precisely where we want to render our tool tip. So just like last module, we're going to use an absolute positioning technique to position our div precisely at that XY position. Let's illustrate what I mean with an example. Let's go ahead and create a new div with a class of tool tip. And within this, we're going to add some styles. We're going to first make it have a position of absolute. You could do this down in your style tag if you wanted, but I like to keep it up here so that it's more clear what we're doing. We're going to give it a top that is equivalent to data.Y position. And then we need a pixel value because this is just a number. And what CSS or HTML expects is a PX suffix. Then we want to position it on the left axis according to data.X PX. So what is happening here? Before we hit save, let's go ahead and describe what's happening and what we expect to see if I hit save. For this country, for example, Mauritius, it has an X value of 354 and a Y value of 294. What we expect is that if and when tool tip is being rendered, it is going to be rendered at the position 294, 354. Right? That is the Y X position that we are passing into our tool tip and is positioned absolutely .

    [09:31 - 10:39] Let's go ahead and verify this works by rendering some text here. And then let 's hit save. Now, if I hover over a text element, you see that it does in fact match one to one with where we are hovering. We see high renders might be hard to see a mouse, but it renders at each circle position that I'm hovering over, which means we're definitely doing something right. Rather than rendering high here, we can render something helpful like data.country. And now we see the name of the country I can't pronounce. Saudi Arabia, which I can pronounce. Singapore, Taiwan, Uruguay, etc. There are obviously some issues here, but what we have on a very high level is a functional yet ugly tool tip. So let's add a few more styles to our tool tip so that it just looks better as more functional serves the purpose better. Because the reality here is that in just ten minutes of this lesson, we 've actually created a functional tool tip that achieves the objective. It just needs some additional polish and some styling, some additional numbers to look cool. But you basically have the pattern down for a tool tip in ten minutes, right?

    [10:40 - 12:21] So let's review that before we get into styling because I think this is the more important part of this lesson, right? We did three things. First, we created a hovered variable, which we can access anywhere in our application by passing it as a prop. And we reset that hovered variable on mouse over, on focus, and then we set it back to null on mouse leave of the larger chart object. Okay? So we are resetting a variable called hovered to equal whatever is being hovered over if and when we move over an element. Then we use dynamic rendering, this if block, to render a new component called tool tip only if something was being hovered over. And then within that tool tip, remember this is an HTML element, that's important. That allows us to use absolute positioning, which we can then use the circles own x and y position to render this tool tip directly on the circle that we're hovering over. So that is in ten minutes how to create a tool tip. Let's add some final styling to make this a bit better. And this is going to be a bit of styling. I like to make my tool tips look pretty. So feel free to kind of get the high level and then leave whenever. But this is what I think we're going to want to do for our tool tip today. First, let's add a background of white and let's add a slight box shadow. You could add a border like a border of black, but I prefer box shadows because I think they look a bit better. We'll give it a horizontal offset of two pixels, vertical offset of three pixels. Let's give it a blur of eight pixels and let's give it a value of this 15% transparent black.

    [12:22 - 12:45] And then let's hover over and see. Now you see, okay, this looks a bit nicer. You can see it has some 3D texture with the background. Obviously, it still needs some work , though. Let's first give it some padding. So we want that white rectangle to be larger around the sides than the text element itself. Six pixels and eight pixels. Now we see it's actually looking like a real tool tip. Let's add a border radius.

    [12:46 - 13:20] So it has some rounded corners to make it a border radius of three pixels. Looking at it. And then finally, let's address this nasty bug where if I hover over the text element itself, it deletes the tool tip. That's problematic. We can get rid of that problem by adding pointer events of none to the text element. So now even if the text element is overlapping with my circle, with my cursor, we can still see it. So that's a lot nicer. Now we can go between circles and this text element updates, but it doesn't hijack the pointer event, which is pretty important.

    [13:21 - 14:19] And then what we can do now is add some additional content to it. So like I said, this is a functional, this is a sufficient tool tip against the job done. But maybe some other information that we want to show is like, what's the happiness score out of 10, right? Like, this is six point something. This is seven point something. This is almost eight, I can guess, but I can't really see it. So let 's go ahead and, you know, add some additional text elements to our tool tip with the note that this is not necessary, but can make your tool tip look a lot better. Let's wrap our country in an H one tag. By default, this isn't going to change much, but it will allow us to style that country in particular, you know, that H one in particular on its own. Then let's add some additional info. So the first thing that I want to add is a span that's going to represent the score. And I'm going to go ahead and write data dot happiness, just to remind the reader I'm going to put out of 10, because that is how many points you could achieve on this happiness score.

    [14:20 - 15:11] Then I'll go ahead and add the continent as well, in case we need a third way to encode the country's continent. Again, a lot of over encoding redundancy, just illustrating how we can do certain things. Okay. So here we see Afghanistan, 2.404 out of 10, and it's in Asia. Obviously there's some styling issues here. So let's go ahead and style our span elements. Let's go ahead and reposition them so they look a bit nicer. So currently score and continent, right? 4.251 Africa are right next to each other. But I think that they could be positioned a bit better so that they have more space between them on like wider continents. Let me find an example of this maybe. Need a really long country name to find this, but.

    [15:12 - 17:36] So here, for example, imagine this country where a few pixels wider, these, the two bottom items, 4.67 out of 10 in Africa, would be right next to each other on the left axis. We actually want them to span the entirety of the tool tip itself. So if it were wider, they would go to the very edges. They have maximum breathing room. So the way that I'm going to do that is I'm going to wrap them in a new div and I'm going to call it info. And then I'm going to keep these two spans within that div. And I'm going to be applying the styling to info itself. So I want info. You'll notice that we're making a lot of use of this in this module to have a display. I apologize. A flex. So they're going to be right next to each other on the row axis. And then I'm going to add this justify content argument and say space between, which says basically put as much space between element one and element two as is humanly possible, or as is computer possible. And then I'll add a gap as well. So there's more space between them. I'll add a column gap of 8 pixels. Now if I hover over what you're going to immediately notice is a bit more space between these two. And here's a great example in S. Whatini you see that now they are distributed horizontally as far away from one another as is possible. So I think this looks a bit nicer. You might as well take advantage of the full horizontal space if you have it. So what else do we want to style? I think that we want to make both the score and the continent smaller personally. So I'm going to add a new class here for score and I'm going to give it a font size of like nine pixels. See how that looks. That's very small. Maybe I will make it 12 pixels. Again, more of an art than a science. Just play around with what works well. And then I'm also going to make continent smaller. Maybe I'll make this font size of 11 pixels and see how this looks. Okay, very small. But I actually want to also make this look more like a label than just a text element. So I'm going to add a background color to it. Some padding, some text transforms, etc. The first thing I'll do is add padding. So I'll make it three pixels all around. And then I'll add a background of let's do white for now.

    [17:37 - 17:44] Now let's do plum for now. But we're going to change this later and save and look. So now this is looking pretty good, right? It's looking kind of like a label.

    [17:45 - 20:07] Some other things we could do. Think of border radius. Maybe three pixels to make it rounded. That's looking good. And text transform. I love making my labels all caps like they're screaming at the reader. So let's make this uppercase. Hit save. Go ahead and look. I think that's looking quite nice. The most evident thing we need to tackle here is the background of plum. We don't want a background of plum for like Bolivia, whenever it's a South American country and it should be yellow, just like circle. So up here, let's get rid of this background and where do we want to include instead? We want to provide an inline style to our continent in our markup. Okay. And we basically want to say instead of, you know, a background of plum down there, let's go ahead and do a background of plum here. Now it's going to have the same effect for now because we're just doing an inline style. We don't want this to be background of plum. We wanted to use the color scale to render the correct color for that continent. That is a really hard phrase to say. So let's go ahead and render color scale of data dot continent. At first, this is not going to work because color scale does not exist. So let's go back up into our app dots felt and pass color scale as a prop in two tool tip. Let's hit save, go into tool tip and accept it. Now if I hit save and go look, you'll see that we have that color immediately reflected in our tool tip. Very easy, honestly, very nice little polish to have these labels looking quite good, rendering the country and the continent with constancy with the color itself. So I think our tool tip is looking pretty good. What else can we edit? I think that maybe these two text elements on the bottom, that info div could be vertically aligned. So what I'm going to do is add align items. Again, that is how we vertically align row based elements. And I'm going to give it an align items of center. And save that and see if it changes anything. There you go. Now they are vertically aligned and they match up basically on the vertical axis. Next, I think the text element itself could use some work, the country that is. So I'm going to target the H1 and I'm going to give it a font size 14 pixels font weight. So it's slightly more bold to 500.

    [20:08 - 20:26] And let's give it a margin bottom. So right now you'll notice that it's really snug with the elements below it. So let's give it a margin bottom of four pixels. That's safe. Now this is looking much better. And I think this tool tip is looking pretty darn good. Probably going to make this font size slightly bigger, 18 pixels.

    [20:27 - 21:49] And I am pretty content with how that tool tip is looking. So feel free to end the lesson here. But if you want to do something kind of fun, kind of funky , we can add one final feature that I think makes this chart, this tool tip, go to the next level, which is an inline bar chart. Again, totally optional, but I think it's kind of fun. So if you're going to bear with me, let's get into it. What we want to do is on hover, we already see this whole tool tip. But we want to show a bar on the bottom, kind of think of a border bottom, that corresponds to that country's happiness level on a scale of one to 10. So for 3.574, we would see a bar that makes up 35.74% of the entire tool tip width. The way that we're going to want to do this is rendering an entire new div under our info div. And we're going to basically add two elements. First is going to be a bar background. Second is going to be a bar foreground. Let's go ahead and create these as spans so that they're in line. And like I said, we're going to have a bar background. And I'm just going to copy that down and create a bar foreground. By default, nothing's going to render here because these are zero zero, no width, no height elements. What do we want to do with these bars? Well, we want both bars to occupy the very, very bottom of the chart.

    [21:50 - 23:13] So we're going to add a position of absolute, a bottom value of zero, and a left value of zero, which basically makes sure that these two bars are pushed to the very bottom left corner of our entire tool tip. We're also going to now apply a height and a width. Let's give it a height of three pixels. So it's barely visible and a width of 100%. Now by default, you're not going to see anything. But if I gave it a background, for example, of black, you would now see this bar at the bottom of our tool tip over and over again, spanning the entire width of our chart or of our tool tip. So this works, but obviously we don't want the background to be black . What do we want the background to be? Well, for the background bar itself, so we want to target the background bar, we want the background to be some muted gray. Maybe we could do like E or CCC or CCC, play around with it. I'll do E. Now I see the background bar very, very faintly. You can kind of zoom in and see it. See that bar? Very, very faint. The foreground of the bar chart, so this actual bar, not the background, actually needs to be two things. It needs to be dynamically positioned on its width according to the happiness score. Right? That's the first thing. And second, it needs to be colored according to the hovered continent.

    [23:14 - 23:40] So the first thing that we can do is add the background color. And what we're going to want to do is find this foreground element and add these styles in line. Because we're using logic from JavaScript, from the style tag, that's where we want to use inline styling. So first, let's do the background. Let's give it a background that's equal to color scale of data dot continent. Again, this makes a lot of sense. This is basically the exact same treatment that we gave our labels earlier.

    [23:41 - 24:21] So let's save this. And now you'll see that these bars exceed the entire width of the D tool tip. But they are the correct color. Now the only thing we need to change is the width of that element. So it's not 100%. It is instead equal to data dot happiness. Remember that is on a scale of one to 10. So let's just multiply it by 10, which will make it on a scale of one to 100. And then add a percent sign. Let's hit save, get rid of our extra quotation mark. And now you see that as we get higher and higher, the bar gets greater and greater. It fills the width of the given tool tip.

    [24:22 - 24:36] Beautiful. We have a nice looking tool tip that has these cool little inline bar charts has text labels is looking quite nice. So what else do we want to do in this lesson ?

    [24:37 - 25:53] We want to tackle two more things. First, we want to transition our tool tip in and out. So it kind of looks nice as it comes into view and as it leaves. Second, we want to prevent our tool tip from going off screen and creating this very unpleasant user experience right here. So let's go ahead and tackle the easier of the two first, which is going to be transitions. The first thing we'll want to do is add a fade and or fly transition into the tool tip element itself. So recall that it just abruptly appears and disappears. What we can do is use felt built in transition modules and import fly and fade from those to render our tool tip nicely in and out. So let's go ahead and right here, we can add transition fly or we can provide specific in and out transitions for each tool tip. So let's give it a Y of 10, a duration of 200 and a delay of 200. So this means that whenever the tool tip first appears, it's going to pop in from 10 pixels below and come into view. That's going to take 200 milliseconds and it's going to happen after 200 milliseconds of hovering. That's the delay.

    [25:54 - 28:27] Then let's just add a simple out property of fade. Now you'll notice that it fades nicely out. And then the final thing that we want to do is transition between elements. So here, we want basically, instead of fading out and fading back in, we want it to move from the previous position to the current one. And we're going to use some CSS transitions for that. But first we need to fix this little bug that I've introduced where the tool tip disappears whenever I leave the circle. We don't want to trigger that until it leaves the entire chart. So here you'll notice that it is triggering anytime I leave a circle and we want to wait until we leave the entire chart, the entire SVG element. So right now I have the mouse leave here. But instead maybe, I thought this would work, but in the event that it doesn't, we can try it up here on the SVG element there. So here, now that it's on the greater SVG parent that contains everything, notice how the tool tip stays in place until I leave the chart. And once I leave the chart, then it will disappear. So that's important, right? And if I go between states, it will just move there. So now we can tackle the second part, which is transitioning between positions. Okay. So this is a singular tool tip item. Remember that like the tool tip itself is only rendered once and it's moving whenever I hover over a new circle. So what we actually want to do is add some CSS rules that will allow us to transition the top and the left properties, right here, smoothly between states. So if data.y were to change from 100 to 200 rather than just abruptly make that transition, what a CSS transition will allow is for it basically to tween between states. So it goes 100, 101, 102, 103 very smoothly over the duration of our transition until it gets to its final new 200 value. So in tool tip, you know, we already have all these rules, we'll add one more rule, which is transition. And we're going to transition the top position. And it's going to take 300 milliseconds within ease and the exact same thing for our left. We'll save that and hover over an element and then move to a new element and see how it smoothly goes from one element to another. So now we have it kind of follows our cursor a bit more dynamically. It actually transitions between circles. So it can really nice until I leave and then it disappears. So we now have some pretty nice transitions between states and in and out of the tool tip view.

    [28:28 - 29:26] The final thing we want to tackle is preventing the tool tip from going off screen to reiterate this issue is what I'm referencing. Not great. Creates a scroll bar. It's not visible at all. You would be able to horizontally scroll to see if that is not ideal. So what do we want to do here? You'll remember that we did this last lesson, our last module with our scatter plot. We want to record the tool tips X and Y position as well as its width and then see if the X position of the tool tip plus the width of the tool tip exceeds the entire width of our page. If it does, we want to move it to the left instead. Okay. So what do we need then? We definitely need the screen width or a chart width in this case. So let's go back into app dots felt and let's add a new prop here. Are we accept width from tool tip or from app dots felt into tool tip? Then let's export let width and verify that it works.

    [29:27 - 29:36] Now if I look at my console and refresh. I think this should work.

    [29:37 - 30:32] There we go. Width is 559. And I don't know why that took a little bit to show up, but we do see width is 559. So that is in fact working. Now what we need to do is keep track of what the tool tip width is, right? Because it changes. Here the width is probably 200 pixels. Here it's only 80. I'm making up those numbers, but you get the idea. And so we need to keep track of what the tool tip width is to see if it ever exceeds this width. And so the way that we're going to do that is with a dimension binding. Remember that we've used this for responsiveness before. It looks like this bind client width to a variable. What do we want to call the variable tool tip width? Right now this doesn't exist. You'll see that it's mad at me because it doesn't exist. Create a new variable called tool tip width , which immediately once tool tip exists will be equal to the width of the tool tip.

    [30:33 - 31:48] So let's look at this. Let's go ahead and console.log tool tip width and see how it changes if and when I hover over new circles 98. 173, right? 158, 138, 117. So we have tool tip width and it's updating in real time to reflect the new width of the tool tip that's being rendered. Now we have all of the pieces that we need to see if we need to move our tool tip left or right. Okay. So let's write some funky fun code to basically get at this. And what you might remember is we did this exact same thing in our scatter plot in module one. So if you want, you can go and copy that code in and change the variables tweak them as needed to achieve the same effect. But just for the muscle memory , I'm going to write it from scratch once again. What we want to do is create a new exposition variable that basically says does the exposition of our tool tip plus the tool tip width exceed the width of the page. If so, we want to render the exposition minus the tool tip width. Put this on a new line so it's more visible.

    [31:49 - 32:45] And if not, we want to render data dot x. Okay. Now instead of rendering data dot x here, let's render exposition. Let's see what happens if I hover over here. Now you'll see that it always offsets right until it reaches a position where that would create an issue. And then it offsets to the left instead. Now we don 't have this horizontal scroll bar issue anymore dynamically updates if and when it needs to. The final thing you could do if you wanted a bit of offset, see how this overlaps with about half of the circle is you could create variables called x nudge and y nudge. So for me, I'll just make a nudge of five in either direction. And then I'll account for these in my x position and in my newly created y position variable. So let's just account for any time we're trying to calculate the x position. Let's also include x nudge. So include x nudge here.

    [32:46 - 33:56] And then, you know, this is the return value, right? Dot x minus tool tip width minus the x nudge. Let's do that. And then if that is in fact not overflowing on the screen, then we just include data dot x plus x nudge. So this will now offset it five pixels to the right or left. And I think that looks a little bit better . So that doesn't overlap with the circle as clearly. And now the exact same logic here, but maybe a bit better, a bit easier to read. Let's go ahead and add a new y position variable, which is just data dot y plus y nudge. So it's going to move it down five pixels, because that is the value of y nudge. And then use y position instead of data dot y, hit save. Now you'll see that it should be offset five pixels to the right, five pixels down from the circle. So now it doesn't overlap with the circle at all, which looks a lot nicer. If I leave my SVG, it disappears. So everything's looking quite good. The tool tips themselves are looking good, at least, and we have finally fixed this annoying issue with the scroll bars.

    [33:57 - 35:20] I think the final thing that we really need to do here is make the hovered circle itself stand out, just like we did in our scatter plot. So we need to go back in app dots felt and give the circles a few more, a little bit of a different treatment, if and when that circle is being hovered over. Let's change two things. Let's change the opacity of the circle that's being hovered, and the stroke of the circle that's being hovered. So rather than stroke always being black, let's make it transparent if the circle is not being hovered over. And for the opacity, let's make it, you know, slightly transparent if the circle is not being hovered over. So first we can do this for the stroke, because we already have a stroke property. What we basically want to do is ask if hovered exists. Okay, so this again is going to use a nested ternary operator with this question mark. So the first condition is, is hovered existent? Is it null or undefined? Then no. Does it exist? If it does exist, then run this ternary operator. Does hovered equal node? If so, then make that circle black. If not, then make that circle transparent. So that is if hovered exists. But what if hovered doesn't exist? If hovered doesn't exist, then we want all of our circles to have the same fill.

    [35:21 - 36:52] Let's go ahead and say it's like CECECECEC. Let's go ahead and save this. So now you see all of these circles have gray until I hover over one, and then all of the strokes disappear except the hovered one. So I actually don't like the gray. So I'm going to change this to like 0, 0, 0, 0, 90. So now they're like a transparent black. And then now you see that they update if and when I hover over a single. So this nested ternary is really important. Remember that basically the logic here is by default they're all going to be this color. But if and when I hover over a single circle, then they're going to look to see if the hovered circle is the current one, if so, make a plaque, if not make a transparent. So that's the logic here. That's why we use this nested ternary operator. So let's go ahead and just honestly copy this and paste it and change stroke to opacity. And then instead of, you know, these colors, if we're playing around with opacity, we basically want to say if it's the focused circle, make it fully visible. If it's not the focused circle, make it 30% transparent. And if it is, if there are no hovered circles, then make them all fully visible. So now with this ternary, same as above basically, just changing the return values, we see that everything fades out other than the hovered circle, if and when I hover over a new one. So this is looking quite good.

    [36:53 - 39:02] These ternarys are pretty fun. You probably want to study what's really happening here. And now what else do we want to do? Well, I think these abrupt transitions could use work. So let's just apply a very simple transition. Down in our style tag, we're going to target all circle elements and apply the following properties. A transition of stroke and of opacity. Let's see if that works. Nice. They fade out and in. Everything looks really good. Let's add a cursor pointer because that's pretty typical for interactable elements. So I think this is looking great. I'm feeling really good. And I guess reading through this lesson again, the last thing that we were going to do, which is as optional, would be to add a reference line. So you can see exactly where we're hovering. You know, basically, if I hover over this Canada element, for example, it will draw a line all the way down in our web page to right here, the 7.025 point. So if you want to do that, again, it's optional. Feel free to skip ahead. But here's how we would do so. So the line itself is going to be an SVG element that lives in app.s felt again, because elements are rendered in the order that you draw them will want to render this element before our each block. So we can access that same variable that we've already accessed called hovered and say, if hovered exists, then render something inside. In our case, it's going to be a line. Now, what are the values going to be? Well, the X one is going to be the hovered values x position. So that circles x position. And the X two is going to be the exact same thing. Now, if we want the reference line to go from basically the bottom of the chart up to the point in which, you know, the hovered circle exists, we want to add a y one of zero and a y two of height. Well, height won't, well, we'll just do this for first, and then we'll get into how we fix it later. Then let's add a stroke.

    [39:03 - 39:41] That's equivalent to the color scale. Remember, we're using these existing variables of the hovered variables continent and then a stroke width of two. Let's close this line and the if block and see what happens if I hover. Now, by default, you see that it spans zero to height because that's precisely what we provided on lines 117 and 118. So what we actually want to do is make it go from the bottom of the chart, which is going to be the inner height up until the point of the y, or the point of the circles y position. Lots of moving parts here.

    [39:42 - 40:27] I apologize. So let's make y one equal to inner height. See how that changes things. Now you'll see that it starts right here. And then where do we want y two to go? We want this to be the hovered circles y position. Save that. And now you'll see it goes right up to where we want the reference line to stop. Beautiful. So honestly, already we've created this really nice line. What else could we add here? Well, we could add some transitions. So we could transition fade. And this doesn't exist at first. So we can import it as well. Import fade from spell transition. See how this changes things. Now you'll see it nicely fades between .

    [40:28 - 41:03] And we could transition like its movement or whatever else. But for the most part, I think we've achieved our objective here, which is we have a nice tool tip. With a focused circle that is primarily visible because everything else is out of focus. And we have a reference line that draws specifically to where that point exists in our chart. So I think these peripheral or these tool tip based interactions are looking really clean. And we have elements around the tool tips which make them look even better. So I hope this lesson was engaging and interesting. I hope it was somewhat fun to dive into some cooler CSS properties .

    [41:04 - 41:23] And in the next lesson, we're going to add some final interactivity to our forced diagram so that the elements can all coalesce on the same Y position and group up and then go back into their continent grouping. So we'll add some additional interactivity and then we'll wrap this module up. I'll see you there in a really exciting.