KQ-1356 · LENS/WARP
Lens Warp
A headline under a moving glass bead: letters near its centre magnify and are pushed outward with a smooth radial falloff, letters at its rim are squeezed and drawn in, and a faint highlight rides the glass — per-letter offsets and scale only, no filters. Every letter follows its target on its own spring, integrated in one loop: the springs.snap constants while the bead is on the words, so the type tracks it crisply, and a softer under-damped spring when it leaves, so the type relaxes with a wobble. The bead follows a mouse or pen 1:1, comes down under a finger, and makes one pass across the words when the trigger fires; with keyboard focus it lands on the first word, Left and Right walk it word by word on springs.glide, Home/End jump and Escape lifts it.
Gaugeworks · loupes and lenses
Every detail, a little closer
Use Left and Right to move the lens across the words; Escape lifts it.resting · move over the words or tab in
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/lens-warp
Props
- text
- string
- default —
- The headline under the glass.
- as
- "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "div"
- default "h2"
- The text element rendered.
- radius
- number
- default 52
- The bead's radius, px — never more than 1.5 times the type size; the piece reserves room above and below the words for it.
- power
- number
- default 0.55
- Magnification and bulge, 0 to 1.
- specular
- number
- default 0.6
- The highlight riding the bead, 0 to 1.
- rim
- number
- default 0.5
- How much the letters at the bead's rim are squeezed, 0 to 1.
- wobble
- number
- default 0.5
- How much the type wobbles as it relaxes when the bead leaves, 0 (none) to 1.
- bead
- boolean
- default true
- Draw the glass disc itself; off leaves only the letters bending.
- tint
- string
- default "var(--accent-bright)"
- The colour letters lean toward at the bead's centre.
- interactive
- boolean
- default true
- The pointer and the keyboard move the bead.
- trigger
- "mount" | "inView" | "hover" | "manual"
- default "inView"
- When the bead makes its one pass across the words: on mount, when scrolled into view, never (hover only), or when active turns true.
- once
- boolean
- default true
- Make the pass only the first time.
- delay
- number
- default 250
- Wait before the pass, ms.
- duration
- number
- default 1600
- How long the pass takes to cross the words, ms.
- active
- boolean
- default —
- For trigger="manual": true runs the pass.
- onComplete
- () => void
- default —
- Fires when the pass is over and the type has relaxed.
- onWordChange
- (word: string | null) => void
- default —
- Fires when the visitor moves the bead onto another word — by pointer or keys — and with null when it lifts; the automatic pass is not reported.
- className
- string
- default —
- Classes for the wrapper; set the type size, weight and colour here.
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | — | The headline under the glass. |
| as | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "div" | "h2" | The text element rendered. |
| radius | number | 52 | The bead's radius, px — never more than 1.5 times the type size; the piece reserves room above and below the words for it. |
| power | number | 0.55 | Magnification and bulge, 0 to 1. |
| specular | number | 0.6 | The highlight riding the bead, 0 to 1. |
| rim | number | 0.5 | How much the letters at the bead's rim are squeezed, 0 to 1. |
| wobble | number | 0.5 | How much the type wobbles as it relaxes when the bead leaves, 0 (none) to 1. |
| bead | boolean | true | Draw the glass disc itself; off leaves only the letters bending. |
| tint | string | "var(--accent-bright)" | The colour letters lean toward at the bead's centre. |
| interactive | boolean | true | The pointer and the keyboard move the bead. |
| trigger | "mount" | "inView" | "hover" | "manual" | "inView" | When the bead makes its one pass across the words: on mount, when scrolled into view, never (hover only), or when active turns true. |
| once | boolean | true | Make the pass only the first time. |
| delay | number | 250 | Wait before the pass, ms. |
| duration | number | 1600 | How long the pass takes to cross the words, ms. |
| active | boolean | — | For trigger="manual": true runs the pass. |
| onComplete | () => void | — | Fires when the pass is over and the type has relaxed. |
| onWordChange | (word: string | null) => void | — | Fires when the visitor moves the bead onto another word — by pointer or keys — and with null when it lifts; the automatic pass is not reported. |
| className | string | — | Classes for the wrapper; set the type size, weight and colour here. |