import React from 'react'; import { FlatKnob, logTaper } from 'dreamknob'; import { CodeBlock } from '../components/CodeBlock'; const Step: React.FC<{ n: number; title: string; children: React.ReactNode }> = ({ n, title, children, }) => (
Everything below is copy-pasteable. The only rule to remember: every control needs
an aria-label (or a visible label wired via aria-labelledby).
Zero runtime dependencies, ESM + CJS, full TypeScript types. No CSS file to import — everything is SVG and inline styles.
Pass defaultValue and the knob manages its own state.{' '}
defaultValue is also the double-click reset target.
For app state, pass value + onChange. The second
argument tells you what caused the change — useful later for undo/automation.
The default is grab-and-rotate (the pointer angle drives the value). Prefer the up/down plugin feel, or MIDI-style pickup? One prop each. Users always get scroll-wheel, arrow keys, Shift-fine, Escape-cancel and double-click reset for free.
step snaps and sets display precision (float-safe — no{' '}
0.30000000000000004). For audio ranges, use a taper:{' '}
logTaper gives equal ratios per turn, so 20 Hz–20 kHz feels right.
format controls display without touching the emitted value.
Use base="light" on light backgrounds. Per-instance color props
always win over the theme.
① Always pass aria-label. ② logTaper needs{' '}
min > 0 (it falls back to linear otherwise). ③ Controlled mode
means you own the value — if you don't call setState in{' '}
onChange, the knob won't move. ④ Hovering captures the scroll
wheel by default; pass wheelRequiresFocus if your UI scrolls. ⑤
The knob is a div, not an input — use name="…" if you
need it in a plain <form> post.