KQ-1362 · DEPTH/OF/FIELD

Depth of Field

A line shot through a fast lens: every word starts soft, a little smaller and faded, and a focal plane sweeps along the line kicking each word sharp on a spring that runs from snap to recoil with breath, so focus breathes past the word before it settles, with a focus-peaking edge flashing as it lands. Pointing at a word racks focus to it — the plane itself travels on a glide-weight spring, so a long pull passes through the words between and the rest fall off with distance — and leaving stops the lens down again. A keyboard handle racks word to word with Left and Right, Escape brings everything into focus and Enter plays the pull again.

KQ-1362 · DEPTH/OF/FIELD

Fieldline 35 mm · f/1.4 prime

Every frame finds its subject.

Left and Right rack the focus from word to word, Escape brings everything into focus, Enter plays the focus pull again.

Point at a word to pull focus to it.

f/2.8 · racking focus

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/depth-of-field

Props

children
string
default —
The line, as a string. Wins over text.
text
string
default —
The line, when it is not given as children.
as
"h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div"
default "p"
The element that carries the line.
aperture
number
default 2.8
The f-number, 1 to 16: lower is a wider aperture and softer out-of-focus words.
sweep
number
default 1100
How long the focal plane takes to cross the line, ms.
breath
number
default 0.5
How far focus breathes past each word: 0 lands dead on (snap), 1 breathes twice (recoil).
depth
number
default 1.5
Depth of field on a re-rack: words either side of the focused one that stay partly sharp.
shrink
number
default 0.04
Lens breathing: how much smaller a fully soft word reads, 0 to 0.12.
fade
number
default 0.4
How much opacity a fully soft word loses, 0 to 1.
peaking
boolean
default true
Flash a focus-peaking edge on a word as it comes sharp.
peakColor
string
default "var(--accent-bright)"
The peaking colour, any CSS colour.
interactive
boolean
default true
Pointing at a word, tapping it or the arrow keys rack focus to it.
rest
"deep" | "hold"
default "deep"
What leaving the line does: stop down so every word is sharp, or keep the pull.
value / defaultValue
number | null
default null
The focused word's index; null is everything in focus.
onValueChange
(index: number | null) => void
default —
Fires from the hover, tap or key that moved the focus.
trigger
"mount" | "inView" | "hover" | "manual"
default "inView"
When the sweep plays.
once
boolean
default true
Play once, or again each time it re-enters view or is hovered.
delay
number
default 0
Wait before the sweep, ms.
play
boolean
default false
With trigger "manual": true plays the sweep, false returns the line to soft.
onComplete
() => void
default —
The sweep has settled.
className
string
default —
Classes for the root; the type size and colour are inherited from here.