npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

super-hover

v0.1.2

Published

A super tiny library that hit-tests hover every frame. Unlike native :hover, it keeps tracking whatever sits under your pointer while you scroll or when things move on screen.

Readme

Super Hover

A super tiny library that hit-tests hover every frame. Unlike native :hover, it keeps tracking whatever sits under your pointer while you scroll or when things move on screen.

Why use this?

Well, you probably shouldn't. While scrolling, browsers mostly skip updating :hover to prioritize other important rendering work, which in most cases is the desired behavior. But Super Hover recomputes a hover-like hit every frame, which opens up the possibility of some fun creative effects and interactions.

Install

pnpm add super-hover
# or npm / yarn

The core super-hover package entry is framework-free. super-hover/react, super-hover/vue, and super-hover/svelte add small helpers. React and Vue are optional peer dependencies.

Usage

Wrap the area you care about, then mark the things that should act hoverable.

The active element gets data-super-hover-active, which is usually enough if you only want styling.

import { createSuperHover } from "super-hover";

const root = document.querySelector<HTMLElement>("#list")!;

const superHover = createSuperHover({ root });

// later
superHover.destroy();
<ul id="list">
  <li data-super-hover>Inbox</li>
  <li data-super-hover>Projects</li>
  <li data-super-hover>Settings</li>
</ul>

Events

If styling is not enough, you can run code when the active element changes. Super Hover dispatches three custom events:

  • superhoverenter when an element becomes active
  • superhoverleave when an element stops being active
  • superhovermove while an element is active
import {
  createSuperHover,
  type SuperHoverEventDetail,
} from "super-hover";

const root = document.querySelector<HTMLElement>("#list")!;

root.addEventListener("superhoverenter", (event) => {
  const e = event as CustomEvent<SuperHoverEventDetail>;
  console.log("entered", e.detail.current);
});

const superHover = createSuperHover({ root });

superhovermove is on by default in the core library. If you do not need move events, pass moveEventType: false.

Framework helpers

React:

import { useSuperHoverRef } from "super-hover/react";

export function Example() {
  const rootRef = useSuperHoverRef({
    onEnter(event) {
      console.log(event.detail.current);
    },
  });

  return <ul ref={rootRef}>{/* data-super-hover items */}</ul>;
}

Vue:

<script setup lang="ts">
  import { useSuperHover } from "super-hover/vue";

  const rootRef = useSuperHover({
    onEnter(event) {
      console.log(event.detail.current);
    },
  });
</script>

<template>
  <ul ref="rootRef"><!-- data-super-hover items --></ul>
</template>

Svelte:

Requires Svelte 5.29 or newer.

<script lang="ts">
  import { superHover } from "super-hover/svelte";

  const hover = superHover({
    onEnter(event) {
      console.log("entered", event.detail.current);
    },
    onLeave(event) {
      console.log("left", event.detail.previous);
    },
  });
</script>

<ul {@attach hover}>
  <li data-super-hover>Inbox</li>
  <li data-super-hover>Projects</li>
  <li data-super-hover>Settings</li>
</ul>

Framework helpers only listen for move events when onMove is passed. If neither onMove nor moveEventType is passed, they disable move events for you.

How it works

The library is very simple and short, so please read the source code for the full details.

In short, Super Hover keeps track of the last pointer and when the pointer moves, the page scrolls, or the viewport changes, it schedules a hit-test with requestAnimationFrame. Multiple updates in the same frame are coalesced, so they only produce one hit-test.

On that frame, Super Hover calls elementFromPoint(x, y), finds the closest element matching [data-super-hover], and updates the active element.

If the active element changes, Super Hover removes data-super-hover-active from the old element, adds it to the new one, and dispatches the custom events.

API

SuperHoverOptions

| Option | Default | Purpose | | --- | --- | --- | | enabled | true | When false, starts paused and waits for resume(). | | pointerTypes | ["mouse", "pen"] | Pointer types allowed to update the tracked pointer position. Touch is off by default so finger scrolling does not create hover state. | | disableWhilePointerDown | false | When true, clears hover state while an allowed pointer is pressed, such as during text selection, and resumes hit-testing after release. | | root | omit, whole document | Optional boundary: the matched element must be inside this subtree. Can be a Document or Element, including same-origin iframe documents/elements. | | selector | [data-super-hover] | CSS selector passed to element.closest from the hit-tested node. Independent of root. | | activeAttribute | data-super-hover-active | Attribute toggled on the active matched element while active. | | enterEventType | superhoverenter | CustomEvent type dispatched on the matched element when it becomes active. | | leaveEventType | superhoverleave | CustomEvent type dispatched on the matched element when it stops being active. | | moveEventType | superhovermove | CustomEvent type dispatched on each scheduled hit-test while an element is active. Set to false to disable. |

SuperHoverController

| Method | Purpose | | --- | --- | | pause() | Pauses hit-testing and clears the active element. | | resume() | Resumes hit-testing and schedules a fresh hit-test. | | refresh() | Schedules a fresh hit-test without changing the paused or destroyed state. | | destroy() | Removes listeners, cancels pending animation frames, and clears the active element. |

Event detail

For superhoverenter and superhoverleave, event.detail has:

  • x and y: the last pointer position, in viewport coordinates
  • previous: the element that was active before this change, or null
  • current: the element that is active after this change, or null

For superhovermove, event.detail has:

  • x and y: the last pointer position, in viewport coordinates
  • current: the currently active element

Links

License

MIT — see LICENSE.