Cursor Lens
rivelle/cursor-lensFreeComponent
A circular pointer magnifier for arbitrary React content.
Install it
npx shadcn@latest add https://rivelle.dev/r/cursor-lens.jsonSource
1"use client";23import * as React from "react";45import { cn } from "@/lib/utils";67type CursorLensProps = React.ComponentProps<"div"> & {8 lensClassName?: string;9 size?: number;10 zoom?: number;11};1213function CursorLens({14 children,15 className,16 lensClassName,17 onPointerEnter,18 onPointerLeave,19 onPointerMove,20 size = 180,21 zoom = 1.75,22 ...props23}: CursorLensProps) {24 const [active, setActive] = React.useState(false);25 const [position, setPosition] = React.useState({ x: 0, y: 0 });26 const [bounds, setBounds] = React.useState({ width: 0, height: 0 });27 const frame = React.useRef<number | null>(null);2829 React.useEffect(30 () => () => {31 if (frame.current !== null) cancelAnimationFrame(frame.current);32 },33 [],34 );3536 return (37 <div38 className={cn(39 "relative isolate cursor-none overflow-hidden rounded-[2rem] border border-foreground/10 bg-card",40 className,41 )}42 data-slot="cursor-lens"43 onPointerEnter={(event) => {44 const rect = event.currentTarget.getBoundingClientRect();45 setBounds({ width: rect.width, height: rect.height });46 setActive(true);47 onPointerEnter?.(event);48 }}49 onPointerLeave={(event) => {50 setActive(false);51 onPointerLeave?.(event);52 }}53 onPointerMove={(event) => {54 const rect = event.currentTarget.getBoundingClientRect();55 const next = {56 x: event.clientX - rect.left,57 y: event.clientY - rect.top,58 };59 if (frame.current !== null) cancelAnimationFrame(frame.current);60 frame.current = requestAnimationFrame(() => setPosition(next));61 onPointerMove?.(event);62 }}63 {...props}64 >65 <div className="h-full">{children}</div>66 <div67 aria-hidden="true"68 className={cn(69 "pointer-events-none absolute left-0 top-0 z-20 overflow-hidden rounded-full border border-background/50 bg-background shadow-[0_18px_70px_-20px_var(--foreground)] transition-opacity duration-200 will-change-transform [backface-visibility:hidden] motion-reduce:hidden",70 active ? "opacity-100" : "opacity-0",71 lensClassName,72 )}73 style={{74 height: size,75 transform: `translate3d(${position.x - size / 2}px, ${position.y - size / 2}px, 0)`,76 width: size,77 }}78 >79 <div80 className="absolute left-0 top-0 will-change-transform [backface-visibility:hidden]"81 style={{82// … truncated
What it pulls in
Other registry items
Files it writes
More from rivelle
All 83 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | rivelle | Components | Free | 2 deps | |
| Alertalert | rivelle | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | rivelle | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | rivelle | Components | Free | 1 dep | |
| Avataravatar | rivelle | Components | Free | 1 dep | |
| Badgebadge | rivelle | Components | Free | 2 deps | |
| Breadcrumbbreadcrumb | rivelle | Components | Free | 2 deps | |
| Buttonbutton | rivelle | Components | Free | 2 deps |
