KQ-1122 · DAY/STRIP
Day Strip
A horizontal strip of days you throw under a still centre lens. It follows the finger 1:1 and rubber-bands past the first and last day; on release the throw is projected with a deceleration set by friction to the day it would rest on, and the strip decays onto exactly that day with the throw's own momentum, then the lens catches it with a small swell on the recoil spring. The lens magnifies as a fisheye, a tick sounds for every day that passes it (a ratchet that slows as the throw dies), and taps glide a day to the lens on the glide spring. It is a listbox: Left and Right move a day, PageUp and PageDown a week, Home and End the ends, with the same flight and sounds.
October 2026
Tue 6 · 2 events
tue 6 oct · 2 events · Design review 10:00
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/day-strip
Props
- start
- string
- default —
- The first day on the strip, as an ISO date (2026-09-28). Dates are handled in UTC arithmetic, so the server and the browser draw the same days.
- days
- number
- default 35
- How many days the strip holds.
- value / defaultValue
- string
- default today if it is on the strip, else start
- The ISO date under the lens. Controlled or uncontrolled; a refused change flies back.
- onValueChange
- (day: string) => void
- default —
- Fires from the throw, tap, key or wheel that chose a day, with its ISO date — at release, before the strip has landed.
- events
- Readonly<Record<string, number>>
- default —
- Event counts by ISO date: up to three dots are drawn under a day, and the count shows in the header and the day's accessible name.
- today
- string
- default —
- The ISO date to mark as today: its date is drawn in the accent and its name says so.
- label
- string
- default "Day"
- The strip's accessible name.
- friction
- number
- default 0.5
- How quickly a throw dies, 0 to 1: a light strip coasts through a couple of weeks from a hard flick, a heavy one stops in a few days.
- lens
- number
- default 1.3
- The lens's magnification, 1 to 1.6. The day under it swells and its neighbours part to make room; at 1 the frame marks the day and nothing swells. The strip grows taller to fit.
- visible
- number
- default 7
- How many days fit across the strip, 3 to 15.
- dots
- boolean
- default true
- Dots under days with events, and the event count in the header.
- sound
- boolean
- default false
- A tick for every day that passes the lens, higher and louder the faster it goes, and a detent as a day lands. Nothing plays, and no audio context exists, unless this is on.
- disabled
- boolean
- default false
- Dims the strip, takes it out of the tab order and stops every throw, tap, key and wheel.
- className
- string
- default —
- Merged onto the outer wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| start | string | — | The first day on the strip, as an ISO date (2026-09-28). Dates are handled in UTC arithmetic, so the server and the browser draw the same days. |
| days | number | 35 | How many days the strip holds. |
| value / defaultValue | string | today if it is on the strip, else start | The ISO date under the lens. Controlled or uncontrolled; a refused change flies back. |
| onValueChange | (day: string) => void | — | Fires from the throw, tap, key or wheel that chose a day, with its ISO date — at release, before the strip has landed. |
| events | Readonly<Record<string, number>> | — | Event counts by ISO date: up to three dots are drawn under a day, and the count shows in the header and the day's accessible name. |
| today | string | — | The ISO date to mark as today: its date is drawn in the accent and its name says so. |
| label | string | "Day" | The strip's accessible name. |
| friction | number | 0.5 | How quickly a throw dies, 0 to 1: a light strip coasts through a couple of weeks from a hard flick, a heavy one stops in a few days. |
| lens | number | 1.3 | The lens's magnification, 1 to 1.6. The day under it swells and its neighbours part to make room; at 1 the frame marks the day and nothing swells. The strip grows taller to fit. |
| visible | number | 7 | How many days fit across the strip, 3 to 15. |
| dots | boolean | true | Dots under days with events, and the event count in the header. |
| sound | boolean | false | A tick for every day that passes the lens, higher and louder the faster it goes, and a detent as a day lands. Nothing plays, and no audio context exists, unless this is on. |
| disabled | boolean | false | Dims the strip, takes it out of the tab order and stops every throw, tap, key and wheel. |
| className | string | — | Merged onto the outer wrapper. |