crucıble

Glassblow

Image card whose surface behaves like molten glass: a low-res viscous height field (heavy damping, ~1.5s relaxation) sinks a broad soft dent under the pointer, stretches an elongated pull on fast swipes, and blows stacking bubbles that swell for 400ms and pop into a relaxing ring. The image refracts through the slopes with one soft specular, faint caustics in the hollows and a thin chromatic split on steep slopes — slow and heavy, never watery. Idle ghost press, slump-flat intro, press/blow handle, seeded sea-glass plate. OGL, DPR-clamped, offscreen-paused, reduced-motion-safe.

oglpro

Installation

CLI

npx shadcn@latest add @crucible/glassblow

Manual — install dependencies, then copy the source

npm install ogl

Props

PropTypeDefaultDescription
srcstringImage URL shown through the glass, cover-fit to the card. Loaded with crossOrigin="anonymous", so cross-origin hosts must send CORS headers — if it fails to load, the built-in procedural plate stays up. Omit to show the procedural plate: a seeded sea-glass dusk over layered dunes.
altstringAccessible description of the image.
refractionnumber0.5How strongly the glass bends the image along its slopes, 0–1. 0 shows the image undistorted (highlights only).
viscositynumber0.6Thickness of the molten glass, 0–1. Higher sinks more slowly under the pointer and takes longer to relax flat (0.6 ≈ 1.5s).
interactivebooleantruePointer and keyboard input: hovering sinks a dent, fast swipes pull the glass, click / Enter / Space blows a bubble, arrow keys press. The idle ghost press keeps running either way.
pausedbooleanFreeze the glass on its current frame.
colors[string, string, string]a teal sea-glass duskProcedural-plate palette [deep, sea, light]: zenith + near dunes, horizon haze + far dunes, sun + crest light. Ignored when src is shown.
seednumber11Seed for the procedural plate layout and the glass's resting waviness.
childrenReact.ReactNodeNon-interactive overlay (captions, labels), rendered above the glass with pointer events disabled so input still reaches the surface.
refReact.Ref<GlassblowHandle>React 19 ref prop → {@link GlassblowHandle}.
Also accepts all props of Omit<React.ComponentPropsWithoutRef<"div">, "children"> — they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, pauses offscreen and on hidden tabs, and passes className through.