Replies

Oct 5, 2024 1 year ago
Keith
is sweet
User Avatar
Eradication

It might not seem like it but that action when you hover over a username around the site takes a lot of work to make sure it happens without a problem. We're pulling multiple data sources, and have to make an important decision: do we load the page with the data in it, or do we load the page and load the data when you hover?

We've gone back and forth over the years!

Right now on subeta.net you wait to load the data - which was the right decision at that time. Waiting for the page to load by fetching all of the user information present on the page was impossible - we'd wait hours. The site just wasn't fast enough, and we didn't the ability to know before the page loaded what information we needed.

Now we do! We can use a combination of techniques to have everything we need (avatar details, user information, medals, etc) for each user hover and have it inserted at the bottom of each page (like this one, you can view source and see them generated at the bottom) from cache, and have it be much faster than loading the details when you hover over a username.

The next steps is getting the item hover using the same piece of technology, and then I can ship the improvements I've made to both (including a little choice in what shows up 😜)

💖 ✨ 🤗

Oct 6, 2024 1 year ago
Keith
is sweet
User Avatar
Eradication

(psst this post will look much nicer on the kumos forums)

And technically, it's really easy how it works 😍 The <popover> API is relatively new (stable in all browsers earlier this year) so it's as simple as:

<a href='/user/{{$user->username}}' popovertarget='user-userid'>{{$user->icon}} {{$user->username}}</a>
<div id='user-userid' popover>
popover details here.
</div>

And it's accessible and very easy to manipulate with the API. It's not meant to be triggered by JS by default, so that takes a little bit of work:

const userPopovers = document.querySelectorAll(".popover-user");

userPopovers.forEach((userPopover) => {
  const target = userPopover.getAttribute("data-popover");
  const targetElement = document.getElementById(target);

  userPopover.addEventListener("mouseover", () => {
    const rect = userPopover.getBoundingClientRect(); // Get link's position
    targetElement.showPopover();
		// Position it to where the user is hovering, where the link is. this might take some revision
    targetElement.style.top = `${rect.bottom + window.scrollY}px`; 
    targetElement.style.left = `${rect.left + window.scrollX}px`; 
  });

  userPopover.addEventListener("mouseout", () => {
    if (targetElement.matches(":popover-open")) {
      targetElement.hidePopover();
    }
  });
});

And all of this together means we don't need to import a heavy library, which is what we've done in the past.

💖 ✨ 🤗

Oct 6, 2024 1 year ago
Keith
is sweet
User Avatar
Eradication

😮‍💨 gotta fix that code example on kumos

💖 ✨ 🤗

Oct 6, 2024 1 year ago
Keith
is sweet
User Avatar
Eradication

🐛 Noticed a bug - they don't persist on pages where I've used wire:navigate :(

💖 ✨ 🤗

Please log in to reply to this topic.