KQ-1793 · POLE/TRAILS

Pole Trails

A long exposure of the northern sky above a dark ridge: while the shutter is open every star traces an arc round the celestial pole at 15° per hour of sky, gathered at `exposure` minutes a second and tinted faintly by its temperature, while skyglow gathers on the horizon and an occasional meteor scores a straight streak that stays in the picture. A click, tap, Enter or Space closes the shutter — a curtain drops on springs.flick, the exposure clears and it lifts away on springs.glide over a fresh sky of points — and dragging moves the pole 1:1 so every arc re-centres live, a throw gliding on with its release velocity. Arrow keys move the pole and Home brings it back.

KQ-1793 · POLE/TRAILS

Fieldline · dark-sky reserve

Tonight from the north ridge

f/2.8 · iso 800 · 14 mm

exposing · tap for a fresh frame, drag to move the pole

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/pole-trails

Props

exposure
number
default 10
How fast the exposure builds, in minutes of sky per second of real time (1 to 60).
density
number
default 0.5
How many stars, 0 (a hazy night) to 1 (a dark-sky site).
horizon
"ridge" | "hills" | "pines" | "sea"
default "ridge"
The ground under the sky: a jagged ridge, rolling hills, a hill with a treeline of pines, or a flat sea horizon.
maxHours
number
default 6
Hours of sky an exposure gathers before it holds (1 to 12).
loop
boolean
default true
A finished exposure closes the shutter and starts a fresh one after `hold`.
hold
number
default 5000
How long a finished exposure is held before it loops, ms.
meteors
number
default 4
Meteors per minute of real time while the shutter is open; 0 for none.
pole / defaultPole
readonly [number, number]
default [0.64, 0.3]
The celestial pole as fractions of the frame, [x, y]; controlled or uncontrolled. Home returns to defaultPole.
onPoleChange
(pole: [number, number]) => void
default —
Fires from the drag release or the key that moved the pole, with where it lands.
skyColor
string
default "oklch(from var(--accent) 0.19 0.055 h)"
The night sky, any CSS colour; a pigment at fixed lightness so the print reads the same in both themes.
groundColor
string
default "oklch(from var(--accent) 0.085 0.018 h)"
The ridge silhouette, any CSS colour.
starColors
readonly [string, string, string]
default —
Star tints [hot, neutral, cool]; every star sits between them by its temperature.
glow
number
default 0.5
Skyglow along the horizon, 0 to 1; it gathers as the exposure builds.
interactive
boolean
default true
Drag moves the pole; a click, Enter or Space closes the shutter.
paused
boolean
default false
Holds the exposure where it is.
seed
number
default 7
Seeds the stars, the ridge and the meteors.
dpr
number
default 2
Cap on the canvas's device pixel ratio, at most 2.
onShutter
() => void
default —
A fresh exposure opened (the shutter closed and reopened).
onComplete
(hours: number) => void
default —
The exposure reached maxHours, with the hours gathered.
label
string
default "Night sky"
The sky's name; the button reads "<label>: start a new exposure".
disabled
boolean
default false
No drag, no shutter: the exposure keeps running and the button is aria-disabled.
className
string
default "h-56 w-full"
Sizes and shapes the frame.