Blend
Inverts whatever is beneath it. Grows over anything clickable.
npx shadcn@latest add https://hoverui.fun/ r/ blend.jsonAdds components/cursors/blend.tsx. The CLI also installs the useCursor hook it runs on, once, into your hooks folder. The files are yours from there.
Invert
- Kind
- Lenses
- Hook
- useCursor
- Dependencies
- None
- License
- MIT
How it behaves
A disc that inverts whatever is beneath it and grows over interactive elements.
Usage
import { BlendCursor } from "@/components/cursors/blend";
export function Section() {
return (
<section>
<BlendCursor />
{/* this section now wears Blend */}
</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 the cursor through currentColor, e.g. text-pink-500. To read on any background, pass text-white mix-blend-difference, as this site does.
- size
- The disc's diameter, in px. Default 24.
- speed
- How quickly the disc catches up with the pointer; lower trails further behind. Default 18.
- swell
- How much the disc grows over anything clickable: 2.5 is two and a half times as wide. Default 2.5.
- Hover targets
- a, button, input, select, textarea, label, [role=button], [data-cursor-label]
Source
"use client";
import { useRef } from "react";
import { cursorRoot, useCursor } from "@/hooks/use-cursor";
/** A disc that inverts whatever is beneath it and grows over interactive elements. */
export function BlendCursor({
className = "",
size = 24,
speed = 18,
swell = 2.5,
}: {
className?: string;
/** The disc's diameter, in px. */
size?: number;
/** How quickly the disc catches up with the pointer; lower trails further behind. */
speed?: number;
/** How much the disc grows over anything clickable: 2.5 is two and a half times as wide. */
swell?: number;
}) {
const disc = useRef({ x: 0, y: 0, scale: 1 });
const ref = useCursor((p, el) => {
const d = disc.current;
d.x += (p.x - d.x) * p.ease(speed);
d.y += (p.y - d.y) * p.ease(speed);
d.scale += ((p.down ? 0.8 : p.hover ? swell : 1) - d.scale) * p.ease(14);
(el.firstChild as HTMLElement).style.transform = `translate(${d.x}px, ${d.y}px) scale(${d.scale})`;
});
// mix-blend lives on the root: a child would only blend inside the root's own stacking context.
return (
<div ref={ref} aria-hidden className={`${cursorRoot} mix-blend-difference ${className}`}>
<div className="absolute -translate-1/2 rounded-full bg-white" style={{ width: size, height: size }} />
</div>
);
}
It runs on the useCursor hook, which has its own source and API.
More lenses cursors
- GlassA lens of frosted glass that blurs whatever it passes over. Widens over anything clickable.
- FocusBlurs its area except a sharp circle at the pointer, like a shallow depth of field. Opens up over controls.
- GogglesNight-vision goggles that turn whatever they pass over green. They gain up over controls; a click flashes them.
- MagnifierA magnifying glass that really enlarges the page under it. Closer over controls, closer still while you hold.
- DropletA water drop that refracts the page under it. Swells over controls; a click sends ripples through the page, bending its words.
- LiquidA drop of liquid glass that bends the page at its rim. Over controls it flows out to wrap them in a glass pill; press to squeeze it.
- GlitchThe page round the pointer splits into red, green and blue and tears sideways in fits, with no frame. It takes over controls and glitches harder; a click throws a burst.
Made a cursor of your own? Contributed cursors carry their maker's name on their page.
Contribute a cursor