KQ-1896 · MONOSPACE/POND
Monospace Pond
A paragraph of monospaced text that is also the surface of a pond: the words stay real, selectable DOM text, and a canvas redraws every character from a glyph atlas where the page laid it out, riding a damped wave equation simulated one character wide with walls that reflect. Swells shoulder the letters toward their crests and lift them, the crests turn them into denser glyphs from the ramp in the crest's ink while troughs thin the ink, and when the energy is gone the original text is drawn exactly again. The pointer drags a trough and its wake through the water as hard as it is quick; a click, a tap, Enter or keyboard focus drops a stone that falls, dents the surface and rings outward under a hairline ring while a crown of droplet glyphs hops out, and the arrow keys move a fingertip that glides between characters on springs.snap while Escape smooths the water away on springs.glide.
Coldbrook Reservoir · 06:10
No wind yet. The water holds the far bank so exactly that the pines grow down as well as up, and a heron stands on its own reflection like a pin through a page. Touch it, and the page remembers it is water.
Arrow keys move a fingertip through the text and stir the water as it goes; Enter drops a stone; Escape calms the water.still water · move to stir, click to drop a stone
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/monospace-pond
Props
- text
- string
- default a short reservoir note (MONOSPACE_POND_TEXT)
- The paragraph. Line breaks in it are kept; spaces wrap as usual.
- as
- "p" | "div" | "blockquote"
- default "p"
- The element the paragraph renders as.
- damping
- number
- default 0.35
- How quickly the water settles, 0 (rings for seconds and rebounds off the edges) to 1 (settles like syrup).
- ramp
- "ascii" | "blocks" | "dots" | "marks" | string
- default "ascii"
- The glyphs a crest turns letters into, light to dense: a named ramp or your own string.
- depth
- number
- default 0.5
- How deep the pond is, 0 to 1: deeper water carries waves faster and bends the letters further.
- stir
- number
- default 0.6
- How hard the pointer drags waves through the text, 0 to 1.
- radius
- number
- default 2.5
- The pointer's footprint in characters, 1 to 6.
- stone
- number
- default 0.7
- How big a dropped stone is, 0 to 1.
- crest
- number
- default 0.5
- How readily crests swap letters for ramp glyphs, 0 (only the highest) to 1 (any swell).
- foam
- boolean
- default true
- Word gaps froth with the lightest glyph on strong crests, so a ring reads across them.
- ring
- boolean
- default true
- A hairline ring rides out from every stone with the wavefront.
- color
- string
- default "var(--foreground)"
- The ink of the text at rest.
- crestColor
- string
- default "var(--accent-bright)"
- The ink the crests, the foam and the ring mix toward.
- interactive
- boolean
- default true
- The pointer, touch and keyboard disturb the water.
- paused
- boolean
- default false
- Freeze the water where it is; it ignores the hand until unpaused.
- intro
- boolean
- default true
- One stone drops by itself the first time the paragraph is seen.
- seed
- number
- default 1
- Where the intro stone falls and how a stone's droplets fly.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- label
- string
- default "Stir the water"
- The pond's accessible name.
- onStone
- (at: { line: number; column: number }) => void
- default —
- Fires for every stone a click, a tap, Enter or keyboard focus drops, with its line and column (from 0).
- onCalmChange
- (calm: boolean) => void
- default —
- Fires when the water starts to move (false) and when it is still again (true).
- className
- string
- default —
- Sizes the box and sets its type: the font size is inherited.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | a short reservoir note (MONOSPACE_POND_TEXT) | The paragraph. Line breaks in it are kept; spaces wrap as usual. |
| as | "p" | "div" | "blockquote" | "p" | The element the paragraph renders as. |
| damping | number | 0.35 | How quickly the water settles, 0 (rings for seconds and rebounds off the edges) to 1 (settles like syrup). |
| ramp | "ascii" | "blocks" | "dots" | "marks" | string | "ascii" | The glyphs a crest turns letters into, light to dense: a named ramp or your own string. |
| depth | number | 0.5 | How deep the pond is, 0 to 1: deeper water carries waves faster and bends the letters further. |
| stir | number | 0.6 | How hard the pointer drags waves through the text, 0 to 1. |
| radius | number | 2.5 | The pointer's footprint in characters, 1 to 6. |
| stone | number | 0.7 | How big a dropped stone is, 0 to 1. |
| crest | number | 0.5 | How readily crests swap letters for ramp glyphs, 0 (only the highest) to 1 (any swell). |
| foam | boolean | true | Word gaps froth with the lightest glyph on strong crests, so a ring reads across them. |
| ring | boolean | true | A hairline ring rides out from every stone with the wavefront. |
| color | string | "var(--foreground)" | The ink of the text at rest. |
| crestColor | string | "var(--accent-bright)" | The ink the crests, the foam and the ring mix toward. |
| interactive | boolean | true | The pointer, touch and keyboard disturb the water. |
| paused | boolean | false | Freeze the water where it is; it ignores the hand until unpaused. |
| intro | boolean | true | One stone drops by itself the first time the paragraph is seen. |
| seed | number | 1 | Where the intro stone falls and how a stone's droplets fly. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| label | string | "Stir the water" | The pond's accessible name. |
| onStone | (at: { line: number; column: number }) => void | — | Fires for every stone a click, a tap, Enter or keyboard focus drops, with its line and column (from 0). |
| onCalmChange | (calm: boolean) => void | — | Fires when the water starts to move (false) and when it is still again (true). |
| className | string | — | Sizes the box and sets its type: the font size is inherited. |