a1ui

Spiral Text

Text set on a responsive spiral that tightens under pressure and ripples on release.

Read agent guide

Demo

Press and hold to draw the coils closer. Release to send a wave past its resting shape.

Installation

pnpm dlx shadcn@latest add https://ui.arjayby1.xyz/r/spiral-text.json

Code

import { SpiralText } from "@/components/ui/spiral-text";

export function Poster() {
  return (
    <SpiralText
      text="THE CONTENT ARCHITECTURE · "
      density={1}
      tightenStrength={0.35}
      rippleDuration={1800}
      rotationSpeed={2}
      className="max-w-2xl"
    />
  );
}

API reference

PropTypeDefaultPurpose
textstringRequiredRepeats along the spiral path and names the graphic for assistive technology.
densitynumber1Adjusts the number of resting turns between 0.65 and 1.6.
tightenStrengthnumber0.35Controls how closely the coils draw together, clamped from 0.08 to 0.7.
rippleDurationnumber1800Sets the outward wave duration in milliseconds, with a 300ms minimum.
rotatingbooleantrueRotates the text clockwise. Set to false to pause at the current angle.
rotationSpeednumber1Rotations per minute. Higher values spin faster. Non-positive or non-finite values use the default.
classNamestringNoneSets layout constraints such as width or placement.

The text follows concentric circular rings. Pressing starts gathering the rings immediately, reaching full tension after 450ms. On release, a circular wave travels outward, swelling and fading each ring before it settles. Outer rings stay gathered until the wave reaches them. Repeated presses carry each ring's current position and velocity into the next motion, so you can interrupt a wave without abruptly stopping it. The interaction responds to mouse, touch, and pen input and stays still when the user requests reduced motion.

The text rotates by default while the dotted background stays fixed. Holding pauses rotation; releasing resumes it. Set rotating={false} to pause it independently. Rotation is disabled when the user requests reduced motion.

Use rotationSpeed to control the speed. For example, rotationSpeed={2} completes two turns per minute, while rotationSpeed={0.5} completes one turn every two minutes.

Glyph positions are calculated once per text or density change. Each interactive ring is drawn into a canvas cache after fonts load. The cache refreshes when its size, pixel density, font, or color changes. The Web Animations API transforms and fades these cached pixels without redrawing the text on every frame or press. SVG provides the initial rendering and the static homepage preview. Motion stops while the component is offscreen or the page is hidden.