KQ-1256 · FOCUS/MOON

Focus Moon

A do-not-disturb toggle that eclipses its own sun: pressed, a moon slides across it on springs.snap, whose one overshoot flashes the last bead of sun on the far limb before the corona comes up on snap, the face turns to night and stars twinkle in on snap in a cascade; while focusing and on screen the corona breathes from one phase value. Holding the button extends the end time in grid steps, a tick per step as the changed digits roll on snap, and letting go sets it; pressed off, the moon slides away on an exit tween and the sunlight blooms back, settling on springs.drift. Space and Enter toggle it, the Up and Down arrows move the end a step, and times come only from the now prop.

KQ-1256 · FOCUS/MOON

Mara Okafor

Gaugeworks · review at 16:00

Press to focus for 1 hour; hold to choose how long.

notifications on · press to focus for 60 min

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/focus-moon

Props

pressed / defaultPressed
boolean
default false
Controlled and initial state; true while notifications are held.
onPressedChange
(pressed: boolean) => void
default —
Fires from the tap, the hold or the key that changed it, with the new state.
until / defaultUntil
Date | number
default now plus minutes once it starts
Controlled and initial end of the focus.
onUntilChange
(until: Date) => void
default —
Fires when a tap, a released hold or an arrow key sets a new end time.
now
Date | number
default —
The current time. Pass it from your clock so server and client agree; without it a press reads the clock when it happens.
minutes
number
default 60
How long a tap focuses for, in minutes.
step
number
default 30
What one hold step or arrow key adds, in minutes; steps land on this grid (15:07 to 15:30).
maxMinutes
number
default 480
The furthest a hold can push the end, in minutes from now.
holdDelay
number
default 450
How long a press must be held before it starts extending, in ms.
holdInterval
number
default 420
Time between steps while held, in ms.
stars
number
default 5
How many stars come out around the eclipse, 0 to 8.
glow
number
default 0.6
Strength of the light, 0 to 1: the sun's bloom, the corona and its breathing.
label
string
default "Do not disturb"
The button's accessible name and its words while off.
focusLabel
string
default "Focusing until"
The words before the end time while on.
format
(date: Date) => string
default 24-hour "15:00" in timeZone
How the end time is written.
timeZone
string
default "UTC"
The IANA time zone the default format writes in.
compact
boolean
default false
Icon only; the name stays and the end time moves to the description and title.
size
"sm" | "md" | "lg"
default "md"
Pill height 32, 40 or 48px with a 24, 30 or 36px sky.
sun
string
default oklch(from var(--warn) 0.84 0.13 h)
The sun, the corona and the bloom, any CSS colour.
night
string
default oklch(from var(--accent) 0.27 0.07 h)
The night the face turns while focusing, any CSS colour.
sound
boolean
default false
A chime at totality (lower when it ends) and a rising tick per hold step or arrow key. Only after the visitor acts.
disabled
boolean
default false
Greys the toggle out and ignores presses, holds and keys.
className
string
default —
Extra classes for the root, which wraps the button.