hover-ui

Register

A printer's registration mark. Exact crosshair; the ring opens and fills over anything clickable.

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

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

You have worn this one since you arrived. Over a control, the ring opens around it.

Link
Kind
Marks
Dependencies
None
License
MIT

How it behaves

A printer's registration mark: exact crosshair, a trailing ring that opens and fills over anything clickable.

Usage

Any element
import { RegisterCursor } from "@/components/cursors/register";

export function Section() {
  return (
    <section>
      <RegisterCursor />
      {/* this section now wears Register */}
    </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.
Hover targets
a, button, input, select, textarea, label, [role=button], [data-cursor-label]

Source

register.tsx
"use client";

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

/** A printer's registration mark: exact crosshair, a trailing ring that opens and fills over anything clickable. */
export function RegisterCursor({ className = "" }: { className?: string }) {
  const ring = useRef({ x: 0, y: 0, scale: 1 });
  const ref = useCursor((p, el) => {
    const r = ring.current;
    const [cross, circle] = el.children as HTMLCollectionOf<HTMLElement>;
    const hot = !!p.hover;
    r.x += (p.x - r.x) * p.ease(22);
    r.y += (p.y - r.y) * p.ease(22);
    r.scale += ((p.down ? 1.4 : hot ? 2.4 : 1) - r.scale) * p.ease(16);
    cross.style.transform = `translate(${p.x}px, ${p.y}px)`;
    circle.style.transform = `translate(${r.x}px, ${r.y}px) scale(${r.scale})`;
    circle.toggleAttribute("data-hot", hot);
  });

  return (
    <div ref={ref} aria-hidden className={`${cursorRoot} ${className}`}>
      <svg viewBox="0 0 24 24" className="absolute size-6 -translate-1/2 overflow-visible">
        <path d="M12 0v24M0 12h24" stroke="currentColor" strokeWidth="1" vectorEffect="non-scaling-stroke" />
      </svg>
      <div className="absolute size-3 -translate-1/2 rounded-full border border-current transition-colors duration-150 data-hot:bg-current/10" />
    </div>
  );
}

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

More marks cursors

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

Contribute a cursor