iPad Cursor Demo

2 min read Original article ↗

iPad Cursor for Web

A physics-based cursor engine that faithfully recreates the iPadOS interaction model. Zero-config magnetic snapping, auto-radius detection, and scroll-aware tracking.

Interactive Playground

Button Variants

The cursor adapts to the shape and size of interactive elements.

Smart Text Handling

Vertical bar cursor matches line-height and font-size automatically.

Display Heading

Section Title

This is a standard paragraph showing how the cursor flows over body text. It morphs into a thin vertical bar that aids in text selection and readability.

API Documentation

Component

Wrap any interactive element with <CursorTarget /> to enable the effect. The cursor will automatically detect the element's dimensions and border radius.

MyComponent.tsx

<CursorTarget magnetic={true}>
  <button className="...">
    Hover Me
  </button>
</CursorTarget>

Configuration

Global settings can be tweaked in cursorConfig.ts. Adjust physics springs, colors, and spatial padding for a completely custom feel.

Props API

type"block" | "text"

Determines the shape of the cursor.

  • block (default): Morphs into the element's shape.
  • text: Morphs into a vertical beam for text selection.

magneticboolean (default: true)

Enables the "pull" effect where the element physically moves towards the cursor. Disable this for static layouts or when using sticky dragging.

stickinessboolean (default: false)

Increases tracking stiffness to nearly instant levels. Essential for drag-and-drop elements to ensure the cursor stays locked to the item being dragged without spring lag.

How It Works

Motion Spring Physics

The cursor core is built on Motion (formerly Framer Motion). We use independent useSpring hooks for X/Y coordinates, width, height, and radius. This ensures that every state transition—whether entering a button or moving between text lines—is interpolated with fluid, organic momentum (stiffness: 300, damping: 25) rather than linear tweening.

Reconciliation Loop

To handle scroll-aware hit testing without performance overhead, we run a single requestAnimationFrame loop. This loop constantly polls document.elementFromPoint to determine the active target, bypassing the need for thousands of onMouseEnter listeners. This decouples the physics engine from React's render cycle, ensuring 60fps performance even on complex pages.

Magnetic Projection

The magnetic effect isn't just a CSS transform. We calculate the delta between the mouse pointer and the element's center, then apply a clamped spring force. We directly manipulate the DOM element's transform: translate3d(...) property inside the physics frame, allowing the button to "pull" towards the cursor up to a defined limit (e.g., 40% of its size) before breaking free.