hover-ui

Glass

A lens of frosted glass that blurs whatever it passes over. Widens over anything clickable.

npx shadcn@latest add https://hoverui.fun/r/glass.json

Adds components/cursors/glass.tsx. The CLI also installs the useCursor hook it runs on, once, into your hooks folder. The files are yours from there.

Move through the preview, then hover the controls and press.

Kind
Lenses
Dependencies
None
License
MIT

How it behaves

A lens of frosted glass that blurs whatever it passes over; it widens over anything clickable and presses in on click.

Usage

Any element
import { GlassCursor } from "@/components/cursors/glass";

export function Section() {
  return (
    <section>
      <GlassCursor />
      {/* this section now wears Glass */}
    </section>
  );
}

Put it inside <body> in your root layout to wear it on every page. Nested cursors take over inside their own element.

Props

className
Colors any outline and the pointer dot through currentColor, e.g. text-pink-500. Keep blend modes and filters off it: either would cut the lens off from the page it sees.
Hover targets
a, button, input, select, textarea, label, [role=button], [data-cursor-label]

Source

glass.tsx
"use client";

import { useRef } from "react";
import { cursorRoot, useCursor } from "@/hooks/use-cursor";

/** A lens of frosted glass that blurs whatever it passes over; it widens over anything clickable and presses in on click. */
export function GlassCursor({ className = "" }: { className?: string }) {
  const s = useRef({ x: 0, y: 0, size: 1 });
  const ref = useCursor((p, el) => {
    const st = s.current;
    st.x += (p.x - st.x) * p.ease(16);
    st.y += (p.y - st.y) * p.ease(16);
    st.size += ((p.down ? 0.85 : p.hover ? 1.5 : 1) - st.size) * p.ease(12);
    const [lens, dot] = el.children as HTMLCollectionOf<HTMLElement>;
    lens.style.transform = `translate(${st.x}px, ${st.y}px) scale(${st.size})`;
    dot.style.transform = `translate(${p.x}px, ${p.y}px)`;
  });

  // No blend mode or filter on the root: either would cut the lens off from the page it blurs.
  return (
    <div ref={ref} aria-hidden className={`${cursorRoot} ${className}`}>
      <div className="absolute size-16 -translate-1/2 rounded-full border border-current/25 bg-white/10 shadow-[inset_0_1px_1px_rgb(255_255_255/0.5)] backdrop-blur-[5px] backdrop-saturate-150" />
      <div className="absolute size-1.5 -translate-1/2 rounded-full bg-current" />
    </div>
  );
}

It runs on the useCursor hook, which has its own source and API.

More lenses cursors

Made a cursor of your own? Contributed cursors carry their maker's name on their page.

Contribute a cursor