Skip to content
WANCRAFT

E.170Backgrounds & Effects

Ink Trail

Pointer strokes leave ink that bleeds, drifts and fades like ink dropped in water, cycling through a palette.

NewReactCanvasTailwindadvanced

Overview

Ink Trail is a background you paint on. Strokes deposit coloured ink and push the water along with them; the ink is simulated on a coarse grid of about 15,000 cells — advected along the velocity field, diffused with a five-point blur and faded every fixed 60Hz step — then written to a tiny ImageData and upscaled with smoothing, which is what gives the edges their soft bleed. A slow ambient current keeps settled ink drifting, colours cycle through the palette as you paint, and optional drops fall on their own when nobody is painting, so the field is never empty. Touch paints while the finger is down with passive listeners, so scrolling is never blocked. The loop stops offscreen, in hidden tabs, and once the ink has fully faded.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/ink-trail.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/ink-trail.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/ink-trail.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { InkTrail } from "@/components/ui/ink-trail";

export function InkTrailExample() {
  return (
    <div className="relative h-96 w-full overflow-hidden rounded-xl">
      <InkTrail />
    </div>
  );
}

03Props

PropTypeDefaultDescription
diffusionnumber0.5How quickly ink bleeds into its surroundings, 0–1.
fadenumber0.4How quickly ink clears, 0–1 (0 lingers longest).
brushSizenumber44Brush diameter in px.
palette"accent" | "ink" | "tide" | "spectrum""accent"Colours the brush cycles through as you paint; ink follows the theme.
accentstring"#FF7448"First colour of the accent palette (any CSS colour).
secondarystring"#B6F3D1"Second colour of the accent palette (any CSS colour).
autoDripbooleantrueDrops fall on their own after a couple of idle seconds.
childrenReactNode—Optional content layered above the ink.
...propsHTMLAttributes<HTMLDivElement>—Forwarded to the root, which is absolute inset-0 — place it inside a positioned parent.

04Features

  • 01Low-resolution ink field: semi-Lagrangian advection, five-point diffusion and fade on ~15k cells
  • 02Strokes inject momentum, so ink is dragged along the direction you paint
  • 03Smoothed upscaling for soft, bleeding edges; multiply blend on light themes, screen on dark
  • 04Palette cycling by stroke length; colours resolved through a canvas probe (works with oklch)
  • 05Fixed 60Hz steps (frame-rate independent on 120/144Hz displays); stops offscreen, in hidden tabs and once the ink has faded
  • 06Seeded opening composition so the field is never blank
motion · continuousinput · pointerinput · draginput · viewport

05Accessibility

  • The canvas is aria-hidden and ignores pointer events; content layered on top stays fully interactive.
  • Touch and pen paint only while pressed, through passive listeners, so page scrolling is never blocked.
  • With prefers-reduced-motion there is no animation loop: a still composition is drawn once, and strokes still leave ink that settles instantly.

06Limitations

  • Pointer listeners live on the window while the field is visible, so strokes over overlaid content still paint (by design for backgrounds).