StringCursor Module

Translate pointer motion into CSS-driven hover states. StringCursor observes desktop mouse movement, writes normalized coordinates to targets, and keeps a custom cursor element in sync with eased values.

Activation primer: Add string="cursor" to every element you want StringCursor to control. Supply string-id="your-id" when you need a stable handle for events, mirrors, or string-copy-from; otherwise StringTune generates one automatically.

HTML Attributes

AttributeTypeDefaultControlsPractical notes
string-target-disablebooleanfalseOpt the element out of cursor interactions even when flagged with string="cursor"Use on wrappers that should not respond despite inheriting the attribute
string-target-style-disablebooleanfalseSkip writing --x/--y CSS variablesIdeal when you consume only the emitted events
string-cursor-classstring""Class added to the global [string-cursor] element while the target is hoveredUseful for theme-aware pointer styling
string-alignmentenum (start/center/end)centerHow the module normalizes pointer position across the elementcenter yields -1…1, start/end map to 0…1 ranges
string-lerpnumber0.2Lerp factor applied to cursor easing (remapped internally to 0.05–0.65)Larger numbers feel tighter; tweak per element for variety

Global pointer element: add [string-cursor] to the DOM once (optionally alongside [string-cursor-content]). The module automatically feeds it CSS variables --x, --y, --x-lerp, and --y-lerp in pixels.

Module Snapshot

  • Activation attribute: string="cursor"
  • Per-target CSS variables: --x, --y (normalized coordinates)
  • Global cursor variables: --x, --y, --x-lerp, --y-lerp (pixels)
  • Event channels: cursor:start|move|pixel|end:<id>, plus the global cursor
  • Pointer gating: module auto-disables on coarse pointers (touch/pen)
  • Lifecycle helpers: attaches MutationObservers + navigation fallbacks to ensure cleanup on SPAs

Basic Usage

import StringTune, { StringCursor } from '@fiddle-digital/string-tune';

const stringTune = StringTune.getInstance();
stringTune.use(StringCursor);
stringTune.start(60);
<div string-cursor class="custom-cursor"></div>

<button string="cursor" string-cursor-class="-hovering" string-lerp="0.35" class="cta">Hover me</button>
.cta {
  --tx: calc(var(--x, 0) * 12px);
  --ty: calc(var(--y, 0) * 12px);
  transform: translate(var(--tx), var(--ty));
  transition: box-shadow 0.2s ease;
}

.custom-cursor {
  position: fixed;
  inset: 0 auto auto 0;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  pointer-events: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
  transform: translate3d(var(--x, 0) * 1px, var(--y, 0) * 1px, 0);
}

How It Works

  • Hover capture: elements with string="cursor" register mouseenter/leave listeners when they enter the viewport; Safari navigation quirks are handled internally.
  • Center sampling: the module tracks half-width/half-height via CenterCache, allowing coordinates to be normalized even as layouts shift.
  • Smoothing: string-lerp passes through an adaptive curve so small numbers still feel fluid; the state sleeps automatically when movement settles below an epsilon.
  • CSS writes: unless disabled, every frame updates --x/--y (normalized) on the element and all mirrors created with string-copy-from.
  • Global cursor: if [string-cursor] exists, it receives eased pixel coordinates plus lerp deltas for additional styling control.

Event Signals

Channel patternPayloadFired whenCommon uses
cursor:start:<id>nullPointer begins moving over the elementKick off sound cues, toggle hover classes
cursor:move:<id>{ x: number; y: number; } (normalized)Normalized coordinates change beyond epsilonDrive DOM transforms, shaders, or analytics samples
cursor:pixel:<id>{ x: number; y: number; } (pixels relative to element)Smoothed pixel offsets updatePosition tooltips, magnetic highlights
cursor:end:<id>nullPointer stops moving or leaves the elementFade out hover embellishments
cursor{ x: number; y: number; stepX: number; stepY: number; }Global cursor state changesSync the custom pointer, broadcast to a state store
stringTune.on('cursor:move:cta', ({ x, y }) => {
  // x & y are normalized; feed into WebGL uniforms or CSS vars
});

stringTune.on('cursor', ({ x, y }) => {
  // global pixel coordinates relative to the viewport origin
});

StringCursor keeps hover choreography responsive—dial the lerp per component, wire events into motion systems, and let the shared cursor element carry the brand’s personality.