KQ-1807 · PASTEL/BAND
Pastel Band
A broad ribbon of colour waving across dark pastel paper, drawn per pixel in one WebGL2 pass: the paper has real tooth (fine grain, a felted scale and a faint honeycomb) and pigment lands only where the stick's pressure reaches past it, so the core is dense and the edges grainy, the sticks lie side by side and the grain picks between them where they meet, and diagonal strokes are laid afresh several times a second while the ribbon itself moves smoothly. The pointer bends the ribbon toward it, the pull following on springs.glide and letting go on springs.drift; a drag smudges the pastel softer along its path until fresh strokes replace it, and the first sighting lays the ribbon on from left to right on the enter easing. The keyboard's way in is a button behind the content: arrow keys move a hand that bends the ribbon, Shift with the arrows smudges, Enter or Space smudges where the hand is, Escape lifts it.
Fieldline · soft pastels
Ninety-six colours, one stick at a time.
Drag across the ribbon to smudge it. Arrow keys move your hand and bend the ribbon toward it; Shift with the arrows smudges as you go; Enter or Space smudges where your hand is; Escape lifts your hand.
dusk · tooth 0.60 · drag to smudge
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/pastel-band
Props
- tooth
- number
- default 0.6
- How much tooth the paper has, 0 (smooth, clean edges) to 1 (heavy tooth, grainy edges and specks of bare paper).
- width
- number
- default 0.46
- The ribbon's width as a share of the box's height, 0.2 to 0.8.
- palette
- "dusk" | "meadow" | "ember" | "glacier"
- default "dusk"
- The pastel sticks laid side by side across the ribbon.
- colors
- readonly string[]
- default —
- Your own sticks instead, two to four CSS colours from the ribbon's top edge to its bottom. Pigment: they read the same in either theme.
- paperColor
- string
- default "oklch(0.25 0.02 258)"
- The paper's colour, any CSS colour; a dark sheet in either theme.
- wave
- number
- default 0.5
- How far the ribbon waves, 0 (straight) to 1.
- speed
- number
- default 0.35
- How fast the ribbon moves, 0 (still) to 1.
- boil
- number
- default 8
- How many times a second the strokes are laid afresh, 0 to 15; 0 keeps the first strokes.
- bend
- number
- default 0.6
- How far the ribbon bends toward the pointer, 0 to 1.
- smudge
- number
- default 0.7
- How much a drag softens the pastel it passes over, 0 to 1.
- fade
- number
- default 9
- How long a smudge takes to give way to fresh strokes, in seconds, 2 to 30.
- grain
- number
- default 1
- The scale of the paper's grain, 0.5 (fine) to 2 (coarse).
- children
- React.ReactNode
- default —
- Content above the sheet: a hero line, a heading, a call to action.
- intro
- boolean
- default true
- The first time the sheet is seen, the ribbon is laid on from left to right.
- interactive
- boolean
- default true
- The pointer and keys bend and smudge the ribbon.
- paused
- boolean
- default false
- Hold the ribbon and its strokes still; bending and smudging still answer.
- label
- string
- default "Pastel ribbon"
- Names the sheet for assistive technology.
- seed
- number
- default 3
- Seeds the waves and the strokes, so two sheets never match.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- onSmudge
- () => void
- default —
- Fires when a smudge is made, from the drag or key that made it.
- disabled
- boolean
- default false
- Shows the ribbon but takes no input.
- className
- string
- default "h-56 w-full"
- Sizes the box.
| Prop | Type | Default | Description |
|---|---|---|---|
| tooth | number | 0.6 | How much tooth the paper has, 0 (smooth, clean edges) to 1 (heavy tooth, grainy edges and specks of bare paper). |
| width | number | 0.46 | The ribbon's width as a share of the box's height, 0.2 to 0.8. |
| palette | "dusk" | "meadow" | "ember" | "glacier" | "dusk" | The pastel sticks laid side by side across the ribbon. |
| colors | readonly string[] | — | Your own sticks instead, two to four CSS colours from the ribbon's top edge to its bottom. Pigment: they read the same in either theme. |
| paperColor | string | "oklch(0.25 0.02 258)" | The paper's colour, any CSS colour; a dark sheet in either theme. |
| wave | number | 0.5 | How far the ribbon waves, 0 (straight) to 1. |
| speed | number | 0.35 | How fast the ribbon moves, 0 (still) to 1. |
| boil | number | 8 | How many times a second the strokes are laid afresh, 0 to 15; 0 keeps the first strokes. |
| bend | number | 0.6 | How far the ribbon bends toward the pointer, 0 to 1. |
| smudge | number | 0.7 | How much a drag softens the pastel it passes over, 0 to 1. |
| fade | number | 9 | How long a smudge takes to give way to fresh strokes, in seconds, 2 to 30. |
| grain | number | 1 | The scale of the paper's grain, 0.5 (fine) to 2 (coarse). |
| children | React.ReactNode | — | Content above the sheet: a hero line, a heading, a call to action. |
| intro | boolean | true | The first time the sheet is seen, the ribbon is laid on from left to right. |
| interactive | boolean | true | The pointer and keys bend and smudge the ribbon. |
| paused | boolean | false | Hold the ribbon and its strokes still; bending and smudging still answer. |
| label | string | "Pastel ribbon" | Names the sheet for assistive technology. |
| seed | number | 3 | Seeds the waves and the strokes, so two sheets never match. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| onSmudge | () => void | — | Fires when a smudge is made, from the drag or key that made it. |
| disabled | boolean | false | Shows the ribbon but takes no input. |
| className | string | "h-56 w-full" | Sizes the box. |