KQ-1382 · BREATH/TYPE
Breath Type
A word that breathes toward the pointer: letters within the radius open their tracking and grow along the inherited font's width, weight or optical size, while letters further away compress, and the line's width is conserved, so the space the near letters take is given up by the far ones and the word draws breath toward the cursor. The breath fills on springs.glide and empties on the slower springs.drift, its point trails the pointer on a critically damped spring, and on its trigger one breath passes along the line. Mouse hovers, touch presses and drags, and the keyboard breathes in at the middle on focus, walks the breath with Left and Right, jumps with Home and End and lets it go with Escape.
Coldbrook · Evening session
Breathe in, slowly.Move along the text, or use Left and Right, to move the breath; Escape lets it go.
resting · move across the words
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/breath-type
Props
- children
- string
- default —
- The text; it is read once and stays copyable.
- as
- "span" | "div" | "p" | "h1" | "h2" | "h3" | "h4"
- default "span"
- The root element.
- radius
- number
- default 2.5
- How far the breath reaches from its point, em.
- falloff
- "linear" | "smooth" | "sharp"
- default "smooth"
- The curve from the breath point out to the radius.
- axis
- "width" | "weight" | "optical"
- default "width"
- What breathes besides the tracking; the font's own axis when it has one, a transform or stroke when not.
- depth
- number
- default 0.7
- How deep the breath is, 0 to 1.
- spread
- number
- default 0.1
- Extra tracking at the breath point, em.
- lag
- number
- default 0.35
- How far the breath trails the pointer, 0 (none) to 1.
- trigger
- "mount" | "inView" | "hover" | "manual"
- default "inView"
- When the intro breath plays; hover means never, manual means on breathKey.
- once
- boolean
- default true
- Play the intro breath only the first time it is seen; otherwise again each time it comes back into view.
- delay
- number
- default 250
- Wait before the intro breath, ms.
- duration
- number
- default 1800
- Length of the intro breath, ms.
- breathKey
- string | number
- default —
- Each change plays the intro breath: the host's own trigger.
- breathing
- boolean
- default false
- A slow resting breath while on screen and untouched.
- focusable
- boolean
- default true
- A tab stop with a keyboard path: arrows move the breath, Escape lets it go.
- disabled
- boolean
- default false
- Ignore the pointer and the keys.
- onBreathChange
- (index: number | null) => void
- default —
- The letter at the breath point changed (grapheme index); null once exhaled.
- onComplete
- () => void
- default —
- The intro breath finished.
- className
- string
- default —
- Classes for the root; the letters inherit its font, size and weight.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | string | — | The text; it is read once and stays copyable. |
| as | "span" | "div" | "p" | "h1" | "h2" | "h3" | "h4" | "span" | The root element. |
| radius | number | 2.5 | How far the breath reaches from its point, em. |
| falloff | "linear" | "smooth" | "sharp" | "smooth" | The curve from the breath point out to the radius. |
| axis | "width" | "weight" | "optical" | "width" | What breathes besides the tracking; the font's own axis when it has one, a transform or stroke when not. |
| depth | number | 0.7 | How deep the breath is, 0 to 1. |
| spread | number | 0.1 | Extra tracking at the breath point, em. |
| lag | number | 0.35 | How far the breath trails the pointer, 0 (none) to 1. |
| trigger | "mount" | "inView" | "hover" | "manual" | "inView" | When the intro breath plays; hover means never, manual means on breathKey. |
| once | boolean | true | Play the intro breath only the first time it is seen; otherwise again each time it comes back into view. |
| delay | number | 250 | Wait before the intro breath, ms. |
| duration | number | 1800 | Length of the intro breath, ms. |
| breathKey | string | number | — | Each change plays the intro breath: the host's own trigger. |
| breathing | boolean | false | A slow resting breath while on screen and untouched. |
| focusable | boolean | true | A tab stop with a keyboard path: arrows move the breath, Escape lets it go. |
| disabled | boolean | false | Ignore the pointer and the keys. |
| onBreathChange | (index: number | null) => void | — | The letter at the breath point changed (grapheme index); null once exhaled. |
| onComplete | () => void | — | The intro breath finished. |
| className | string | — | Classes for the root; the letters inherit its font, size and weight. |