v0.1.0React 19Tailwind v4available on npmbrowse the source →
A calendar obsessed with micro-perfection.
Hand-tuned drag physics, a design mode that annotates its own craft, and a command palette that reaches everything. One React component — available on npm and as source files.
install from npm or add the source through the registry · browse the source →
- Drag an event somewhere else. The point you grabbed stays under the pointer — it never drifts.
- Pull its bottom edge. The hit zone is 8 px, bigger than the pixels you can see.
- Press Esc mid-drag. It springs home.
- Press ⌥D. The calendar annotates its own craft.
01physics
Every drag has a spring.
Nothing lerps. Settle, cancel and nudge run through WAAPI on a damped spring sampled into a CSS linear() easing. The curves below are drawn from the engine’s own springSamples() — play one.
Drag settle
k 380 · c 30 · 320 ms
Resize overshoot
k 300 · c 19 · 320 ms
Keyboard nudge
k 700 · c 36 · 180 ms
these three live in lib/springs.ts — retune them in design mode, then keep itsee the source →
- intent
- 4 px of movement before a drag exists. A click is never a drag.
- snap
- 15-minute steps, ⌥ for 5. Magnetism is eased in, not teleported.
- the weld
- The point you grabbed stays under the pointer for the whole gesture.
- origin ghost
- A 40 % ghost holds the old slot until you drop.
- handles
- 8 px resize zones straddle the block edge — bigger than the pixels you see.
- auto-scroll
- Ramped at the grid edges, so the page never lurches.
- promotion
- Drag a timed draft into the all-day lane and it becomes all-day mid-gesture.
- failure
- The server says no → the block springs home and shakes. Sync that owns its mistakes.
- escape
- Mid-drag, Esc springs it back where it came from.
- reduced motion
- Designed alternatives, not
animation: none. - the render
- Transforms go straight to DOM nodes. React sees nothing until drop.
- the bus
- Every frame publishes velocity to a zero-render pub/sub — the inspector reads it, and so can you.
02quick add · ⌘K
Write it in English.
One line becomes a draft. The parser reports the exact source offsets of every phrase it consumed, so the field underlines what it understood as you type. Below is the real ⌘K surface, not a mock.
The ⌘K quick-add screen, as shipped. Type into it — or just watch.
Move it in English — the same screen, for a selected event.
03keyboard
Everything has a key.
About fifty bindings and one table behind them. The dispatcher and the ? sheet read the same rows, so a remapped key can never make the sheet lie.
- Scoped. An embedded calendar claims no key it hasn’t earned — nothing fires until you’ve clicked inside it, and never in a text field.
- Remappable. Mnemonics take a
keymapprop. The ⌘ conventions and the arrows are fixed on purpose. - Announced. Every move, resize, colour and undo is read out once, on completion — not per frame.
pick a modifier — or hold the real one — to see its layer
the table itself is lib/keymap.ts — add a binding, not just remap onesee the source →
- tBack to today
- dDay view
- 33-day view
- wWeek view
- mMonth view
- yYear view
- aSchedule view
- cNew event at the next hour
- 1 – 5Recolor the selected event
- ↵Open the selected event
- escClose the panel, then clear the selection / cancel a drag
- ⌫Delete the selection
- ← →Previous / next range — or walk the selection
- ↑ ↓Walk selection between events
04scale
Ten thousand events. Nine milliseconds a frame.
Zero React renders during a gesture — transforms go straight to the DOM from one rAF loop — and views that stay quick when the store gets big.
10,000
events seeded into one store
9.2ms
average frame, scrolling and switching views
8.3ms
median frame
0
React renders per drag frame
p95 9.2 ms · worst 109 ms · 537 frames. The demo takes the same seed, so you can watch it yourself.
05views · themes
Six views. Nineteen themes. One component.
Day, n-day, week, month, agenda and year behind one prop, with a FLIP morph between them. Nineteen themes, each in light and dark.
Coss · light-first
one prop — theme="coss" — this calendar only; setTheme() when you want the whole site
a theme is one token block in styles/kloq.css — ship a twentieth with your brandsee the source →
06install
Install the package. Or bring in the source.
npm gives you the compiled, typed build with every feature and theme. The shadcn registry copies the calendar into your repo as files you can edit. Same component and API; choose where the code lives.
npm
- npm install kloq
- All six views, nineteen themes, ⌘K, design mode
- Updates with npm update
Source
- Engine, views, themes, ⌘K and design mode as source
- A spring tweak is a line; a custom slot is a file
- Add-on blocks: calendar, timeline, utc-gutter, zone-gutter
- Update when you choose to re-run the CLI
$ npm install kloqimport "kloq/styles.css";import { Kloq, KloqToolbar } from "kloq";
export default function Page() {
return (
<div className="h-dvh">
<Kloq>
<KloqToolbar />
</Kloq>
</div>
);
}Compiled and typed, in node_modules. React 19 and Tailwind v4 assumed. Updates with npm update.
Put it on your calendar.
Install from npm in about a minute, or add the source when you want to shape every detail.