KQ-1586 · GEL/CLING
Gel Cling
A thick gel window cling on any surface, drawn as a 72-node soft body: press it and it squishes away from the finger and rings back; grab it and peel, and the part in your fingers comes away 1:1 while the rest clings, the peel front running across it as the pull grows and strings of tack stretching between the glass and the lifted gel until each snaps into a bead. Pull far enough and it lets go — the last strings snap in a run — and hangs from your finger, its far side catching up on its springs; let go and it falls on springs.snap, spreads as it meets the surface and pulls back with two small bounces, and clings. The decal is a real button: Enter peels it from the edge with the most room, the arrow keys carry it on springs.snap, Enter or Space sticks it down and Escape puts it back.
Starfish cling
Reusable gel, sticks to any glass.
Coldbrook Aquarium · window clings
stuck · 50% across, 50% down
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/gel-cling
Props
- children
- React.ReactNode
- default —
- The surface the decal clings to (a window, a card, a photo), drawn under the gel.
- shape
- "star" | "heart" | "flower" | "drop"
- default "star"
- The decal's outline.
- size
- number
- default 112
- The decal's width, px; held to 60% of the box's smaller side.
- thickness
- number
- default 0.5
- How thick the gel is, 0 to 1: a deeper rim and side wall, a longer shadow, a softer, slower wobble.
- tack
- number
- default 0.5
- How hard it clings, 0 to 1: how far you pull before it lets go, and how many strings of tack hold on and how long they stretch.
- tint
- "cherry" | "lime" | "sky" | "honey" | string
- default "cherry"
- The gel's colour: a named pigment (the same in both themes) or any CSS colour.
- gloss
- number
- default 0.7
- Strength of the glossy highlight, 0 to 1.
- wobble
- number
- default 0.5
- How long the gel jiggles after a press or a landing, 0 (dead) to 1 (ringing).
- position / defaultPosition
- [number, number]
- default [0.5, 0.5]
- Where the decal's centre sits, as [x, y] fractions of the box. A controlled change lifts it, glides it there and lays it down; a refused move glides it back.
- onPositionChange
- (position: [number, number]) => void
- default —
- Fires when the decal is stuck down somewhere new, with its centre as fractions (3 dp).
- onPeel
- (amount: number) => void
- default —
- Fires while a corner is peeled, with how far it is toward letting go, 0 to 1 in steps of 0.05.
- onLift
- () => void
- default —
- Fires when the decal lets go of the surface.
- onStick
- (position: [number, number]) => void
- default —
- Fires when it lands and clings again, with where.
- label
- string
- default "Gel decal"
- The decal's accessible name.
- sound
- boolean
- default false
- A gloop when it lets go and when it lands, a plip as each string of tack snaps, a blup when squished.
- disabled
- boolean
- default false
- The decal stays stuck: no press, peel or keys.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- className
- string
- default "h-56 w-full"
- Sizes and shapes the surface; the decal never leaves it.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | — | The surface the decal clings to (a window, a card, a photo), drawn under the gel. |
| shape | "star" | "heart" | "flower" | "drop" | "star" | The decal's outline. |
| size | number | 112 | The decal's width, px; held to 60% of the box's smaller side. |
| thickness | number | 0.5 | How thick the gel is, 0 to 1: a deeper rim and side wall, a longer shadow, a softer, slower wobble. |
| tack | number | 0.5 | How hard it clings, 0 to 1: how far you pull before it lets go, and how many strings of tack hold on and how long they stretch. |
| tint | "cherry" | "lime" | "sky" | "honey" | string | "cherry" | The gel's colour: a named pigment (the same in both themes) or any CSS colour. |
| gloss | number | 0.7 | Strength of the glossy highlight, 0 to 1. |
| wobble | number | 0.5 | How long the gel jiggles after a press or a landing, 0 (dead) to 1 (ringing). |
| position / defaultPosition | [number, number] | [0.5, 0.5] | Where the decal's centre sits, as [x, y] fractions of the box. A controlled change lifts it, glides it there and lays it down; a refused move glides it back. |
| onPositionChange | (position: [number, number]) => void | — | Fires when the decal is stuck down somewhere new, with its centre as fractions (3 dp). |
| onPeel | (amount: number) => void | — | Fires while a corner is peeled, with how far it is toward letting go, 0 to 1 in steps of 0.05. |
| onLift | () => void | — | Fires when the decal lets go of the surface. |
| onStick | (position: [number, number]) => void | — | Fires when it lands and clings again, with where. |
| label | string | "Gel decal" | The decal's accessible name. |
| sound | boolean | false | A gloop when it lets go and when it lands, a plip as each string of tack snaps, a blup when squished. |
| disabled | boolean | false | The decal stays stuck: no press, peel or keys. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| className | string | "h-56 w-full" | Sizes and shapes the surface; the decal never leaves it. |