KQ-1572 · PAUSE/BLOOM
Pause Bloom
A sheet of wet watercolour paper behind your content that the cursor paints only when it stops: rest the pointer and a drop of pigment falls at its tip and blooms into the paper as a stack of fractal-edged translucent layers, growing on a critically damped curve (the drift spring's character, stretched to growTime) that is quick at first and slows as the paper drinks it. Move on and the bloom coasts to a stop and dries where it lies — a tide line gathers at its rim and the pigment granulates into the paper's tooth — the next rest takes the next pigment, overlapping blooms mingle, and the paper slowly dries clean. Touch blooms on a long press; with the keyboard, arrows move the brush, Space or Enter held lets a drop bloom and Delete blots the paper.
Fernworks Paper Co.
Cold-pressed, 300 gsm, all cotton.
Pause, and let it bloom.
Rest the pointer to drop colour. Arrow keys move the brush; hold Space or Enter to let a drop bloom; Delete blots the paper clean.
rest to paint · ultramarine first
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/pause-bloom
Props
- children
- React.ReactNode
- default —
- The content laid on the paper: a headline, a card, a call to action. It stays fully interactive.
- palette
- "garden" | "harbour" | "ember" | "ink"
- default "garden"
- The pigments the drops step through, one per drop.
- colors
- string[]
- default —
- Two to eight CSS colours that replace palette.
- bloomSize
- number
- default 72
- How far a bloom spreads if you rest until it is done, px (16 to 200; held under 45% of the box).
- dryTime
- number
- default 12
- How long a dried bloom keeps its colour before the paper is clean, seconds (1 to 60).
- restDelay
- number
- default 260
- How long the pointer must rest before a drop falls, ms.
- growTime
- number
- default 1800
- How long a bloom takes to reach bloomSize while you rest, ms.
- raggedness
- number
- default 0.5
- How ragged a bloom's edge is, 0 (a soft round pool) to 1 (cauliflower).
- edge
- number
- default 0.5
- How dark the tide line gathers at a bloom's edge as it dries, 0 to 1.
- granulation
- number
- default 0.4
- How much the pigment settles into the paper's tooth as it dries, 0 to 1.
- strength
- number
- default 0.7
- How much pigment each drop carries, 0 (a tint) to 1 (a full wash).
- maxBlooms
- number
- default 24
- Blooms kept on the paper; past this the oldest dries clean at once.
- defaultBlooms
- number
- default 3
- Dried blooms already on the paper when it first shows, 0 to 6.
- longPress
- number
- default 380
- How long a finger must hold still on touch before a drop falls, ms.
- paper
- string
- default "var(--card)"
- The paper's colour, any CSS colour; light paper mixes pigments like paint, dark paper like light.
- interactive
- boolean
- default true
- Resting the pointer paints.
- paused
- boolean
- default false
- Hold the paper as it is: nothing grows, dries or falls.
- clearKey
- string | number
- default —
- Any change blots the paper clean.
- seed
- number
- default 1
- Seeds the bloom shapes and the paper's first blooms.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- label
- string
- default "Wet paper"
- The paper's accessible name, for the keyboard's way in.
- onBloom
- (count: number, pigment: number) => void
- default —
- A drop fell: how many so far, and which pigment of the palette it carried.
- onClean
- () => void
- default —
- The last bloom has dried clean.
- disabled
- boolean
- default false
- Nothing paints and the keyboard's way in is off.
- className
- string
- default "h-56 w-full"
- Sizes the paper.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | — | The content laid on the paper: a headline, a card, a call to action. It stays fully interactive. |
| palette | "garden" | "harbour" | "ember" | "ink" | "garden" | The pigments the drops step through, one per drop. |
| colors | string[] | — | Two to eight CSS colours that replace palette. |
| bloomSize | number | 72 | How far a bloom spreads if you rest until it is done, px (16 to 200; held under 45% of the box). |
| dryTime | number | 12 | How long a dried bloom keeps its colour before the paper is clean, seconds (1 to 60). |
| restDelay | number | 260 | How long the pointer must rest before a drop falls, ms. |
| growTime | number | 1800 | How long a bloom takes to reach bloomSize while you rest, ms. |
| raggedness | number | 0.5 | How ragged a bloom's edge is, 0 (a soft round pool) to 1 (cauliflower). |
| edge | number | 0.5 | How dark the tide line gathers at a bloom's edge as it dries, 0 to 1. |
| granulation | number | 0.4 | How much the pigment settles into the paper's tooth as it dries, 0 to 1. |
| strength | number | 0.7 | How much pigment each drop carries, 0 (a tint) to 1 (a full wash). |
| maxBlooms | number | 24 | Blooms kept on the paper; past this the oldest dries clean at once. |
| defaultBlooms | number | 3 | Dried blooms already on the paper when it first shows, 0 to 6. |
| longPress | number | 380 | How long a finger must hold still on touch before a drop falls, ms. |
| paper | string | "var(--card)" | The paper's colour, any CSS colour; light paper mixes pigments like paint, dark paper like light. |
| interactive | boolean | true | Resting the pointer paints. |
| paused | boolean | false | Hold the paper as it is: nothing grows, dries or falls. |
| clearKey | string | number | — | Any change blots the paper clean. |
| seed | number | 1 | Seeds the bloom shapes and the paper's first blooms. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| label | string | "Wet paper" | The paper's accessible name, for the keyboard's way in. |
| onBloom | (count: number, pigment: number) => void | — | A drop fell: how many so far, and which pigment of the palette it carried. |
| onClean | () => void | — | The last bloom has dried clean. |
| disabled | boolean | false | Nothing paints and the keyboard's way in is off. |
| className | string | "h-56 w-full" | Sizes the paper. |