Is there a better way to conditionally show a hover info box in liveview?

I have a list of items and want to show a small info panel when an item is hovered. To make it behave quickly with no round-trip to the backend, I’m using JS’s show and hide functions on hidden info panels (one per item in the list.)

Pros:

  • very responsive, immediately shows or hides items with no network delay
  • liveview doesn’t have to maintain state for the hovered item

Cons:

  • heavier initial load, since I’m creating all of these items ahead of time and they may never be used
  • it’s easy for the info panel to get “stuck” open. Eg. temporary network loss, or the hovered item being removed can cause the mouse leave event to never be fired.

I’m curious how others would handle something like this. My biggest issue currently is the aforementioned “stuck” info panels, though I’d love a lighter weight solution as well.

Thanks!

You could just use CSS.

<button class="with-tooltip" aria-describedby="my-tooltip">
  hover me
  <div role="tooltip" id="my-tooltip">
   <p>more info</p>
  </div>
</button>
.with-tooltip {
  position: relative;
}

.with-tooltip > [role="tooltip"] {
  display: none;
}

.with-tooltip:hover > [role="tooltip"],
.with-tooltip:focus > [role="tooltip"] {
  display: block;
  position: absolute;
  // ...
}

Here, the tooltip is shown on both hover and focus, so that it will also be shown when the element is focused with the keyboard.

5 Likes

Nice, I didn’t know about describedby. Thanks for the great explanation, that’s good to add to my toolset. You can achieve a similar effect with tailwind groups too.

Sadly I oversimplified the explanation of my problem, so I don’t think either would work. The user can actually hover two different places (a list and a map) to get the hover. So I can’t use children elements for the hover unless I duplicate them in both places. Also the map is using web components so it won’t work there either.