Cursor Comet
motiq/cursor-cometFreeComponent
A canvas particle comet that reads pointer velocity, not just position: a tight ember when you drift, a long azure-to-cyan plume with coral sparks when you flick. Idle, the particles coil into an ambient orbit ring. Fixed particle pool, pre-rendered sprites with additive blending, DPR capped at 2x, one rAF loop, offscreen-paused, static orbit frame under reduced motion.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/cursor-comet.jsonSource
1"use client";23import * as React from "react";45import { cn } from "@/lib/utils";6import { useReducedMotion, useVisibilityPause } from "@/lib/motiq";78/* -------------------------------------------------------------------------- */9/* Types */10/* -------------------------------------------------------------------------- */1112export interface CursorCometProps extends React.HTMLAttributes<HTMLDivElement> {13 /** Fixed particle pool size (clamped 24–800). No allocation happens per frame. */14 particleBudget?: number;15 /** 0–1 fraction of pointer velocity each particle inherits, reversed. */16 velocityGain?: number;17 /** Exponential drag coefficient, per second. */18 drag?: number;19 /** Head/young-particle color — any CSS color, resolved from tokens by default. */20 headColor?: string;21 /** Tail/old-particle color. */22 tailColor?: string;23 /** Ionization spark color — the rare signature moment. */24 sparkColor?: string;25 /** Pointer speed (px/s) above which coral sparks ignite at the head. */26 sparkThreshold?: number;27 /** Coil the particles into an ambient orbit ring when the pointer is away. */28 idleOrbit?: boolean;29 /** Deterministic seed for the particle jitter (SSR-stable markup). */30 seed?: number;31 /** Stop the rAF loop when scrolled offscreen or the tab is hidden. */32 pauseWhenHidden?: boolean;33 /** Force the static, motion-free variant regardless of system preference. */34 reducedMotion?: boolean;35}3637/* -------------------------------------------------------------------------- */38/* Helpers */39/* -------------------------------------------------------------------------- */4041const clamp = (v: number, a: number, b: number) => (v < a ? a : v > b ? b : v);4243/** mulberry32 — deterministic jitter, no Math.random at render or module scope. */44function makeRng(seed: number) {45 let a = seed >>> 0;46 return () => {47 a = (a + 0x6d2b79f5) | 0;48 let t = Math.imul(a ^ (a >>> 15), 1 | a);49 t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;50 return ((t ^ (t >>> 14)) >>> 0) / 4294967296;51 };52}5354/** Resolve any computed CSS color string (rgb/rgba/#hex) to an [r,g,b] triple. */55function parseRgb(input: string): [number, number, number] {56 const c = input.trim();57 if (c.startsWith("#")) {58 let h = c.slice(1);59 if (h.length === 3) h = h.split("").map((d) => d + d).join("");60// … truncated
What it pulls in
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
