Trail dots
A trail built from staggered follow durations rather than a position history. Every dot is told the same coordinate each frame; they string out because each one converges more slowly than the last.
Live props — bound to the real component
Install
npx shadcn@latest add @pointerui/trail-dots# Copy three folders out of the repo
src/lib/engine/ -> lib/pointerui/engine/
src/registry/provider/ -> components/pointerui/provider/
src/registry/variants/trail-dots/ -> components/pointerui/trail-dots/
# Then fix the two aliases the CLI would have rewritten
# @/lib/engine -> @/lib/pointerui/engine
# ../../provider -> @/components/pointerui/providerimport { createEngine } from "./lib/pointerui/engine";
// The engine has no React imports at all, so it runs anywhere.
const engine = createEngine();
const el = document.createElement("div");
document.body.append(el);
const layer = engine.registerLayer(el, { duration: 0.15, ease: "power3" });
const stop = engine.onTick((state) => {
layer.setX(state.x);
layer.setY(state.y);
});
// TrailDots's own layer setup is the same call with its own options.Usage
import { CursorProvider } from "@/components/pointerui/provider";
import { TrailDots } from "@/components/pointerui/trail-dots";
export default function Page() {
return (
<CursorProvider>
<TrailDots />
<button data-cursor="grow">Hover me</button>
</CursorProvider>
);
}Props
Generated from trail-dots/types.ts and the component's own defaults, so this table cannot drift from the code you are about to copy.
| Prop | Type | Default | Description |
|---|---|---|---|
| count | number | 8 | Number of DOM layers. Each one is an element, so keep this small. |
| base | number | 0.1 | Follow duration of the leading dot, in seconds. |
| step | number | 0.05 | Added to |
| size | number | 7 | Diameter of the leading dot in px. |
| scaleFalloff | number | 0.4 | Diameter of the last dot as a fraction of |
| alphaFalloff | number | 0.3 | Alpha of the last dot. The leading dot is always fully opaque. |
| color | string | "var(--cursor-color, currentColor)" | Any CSS colour. Defaults to |
| ease | string | "power3" | GSAP ease for the follow tween. Any ease string GSAP understands works — This is the shape of the lag, where |
Data attributes
Mark any element with one of these and this variant responds when the pointer enters it. Values it does not understand are ignored.
- data-cursor="hide"
- Fades the whole trail out.
Notes & caveats
- Cost scales with
count, because every dot is an element whose transform the style system resolves each frame. Past roughly a dozen followers, reach fortrail-canvas. - There is no ring buffer and nothing to keep in sync — which is also why the trail collapses to a neat stack when the pointer stops.