All components

Kinetic Type

Typography

Per-glyph variable-font response to pointer proximity — axes swell near the cursor and relax away from it, continuously and reversibly. Glyph boxes are pinned to their resting widths so animating `wght` can't shift neighbours, stale the cached centres, or re-wrap the line; centres are measured once and only re-read on resize or font swap. The accessibility tree reads one clean string.

Type that answers the cursor.

Every glyph measures its own distance from the pointer, springs independently, and resolves to a font-variation-settings string. The boxes are pinned to their resting widths, so nothing reflows and no cached centre ever goes stale — the letters swell in place instead of shoving each other along the line.

Move across the text — zero React re-renders

Radius · 120px
Peak wght · 800
Stiffness · 280

Push peak weight to 900 and drag across a word: the line holds its wrapping exactly. Without the pinned boxes, that is the setting where it starts to jitter and re-wrap under the cursor.

Installation

Terminal
npx shadcn@latest add https://ui.saumyarex.xyz/r/kinetic-type.json

Props

PropTypeDefaultDescription
textstringThe string to render. Split per glyph (by code point, so surrogate pairs stay whole); words stay unbreakable and whitespace is preserved as real text nodes. Requires a variable font on the element — the axes you name must exist in it.
axes{ tag: string; from: number; to: number }[][{ tag: "wght", from: 300, to: 800 }]OpenType axes to drive. `from` is the resting value (and the value reduced-motion pins to), `to` is the value under the pointer. Any axis tag works — `wght`, `wdth`, `slnt`, `opsz` — as long as the loaded font exposes it.
radiusnumber120Radius of influence in pixels.
falloff(distance: number, radius: number) => numberDistance and radius → intensity in 0…1. Defaults to a raised cosine, whose zero derivative at both ends means neither the peak nor the radius boundary shows a crease.
springSpringOptions{ stiffness: 280, damping: 28, mass: 0.5 }Per-glyph spring. Each glyph springs independently, so the ripple across a word is emergent.
as"p" | "span" | "div" | "h1" | "h2" | "h3" | "h4""p"Element to render as.

Dependencies

motionclsxtailwind-merge