SIG—20 Signature system
Knob
A rotary control for instruments rather than forms: drag up or down, Shift for fine, arrows to step, double-click to return home — with log tapers for frequencies and times.
Live — this one is real
Drag knobs and faders up or down (Shift for fine), press anywhere on the pad, or use the arrow keys; double-click or Backspace returns a control home. The synth really plays while you hold the button — the meters and scope read its audio.
onValueCommitNothing yet
Usage
"use client";
import { useState } from "react";
import { Knob } from "mizu-ui";
export function Example() {
const [cutoff, setCutoff] = useState(1200);
return (
<Knob
label="Cutoff"
min={40}
max={16000}
taper="log"
value={cutoff}
onValueChange={setCutoff}
format={(v) => (v >= 1000 ? `${(v / 1000).toFixed(1)} kHz` : `${v} Hz`)}
/>
);
}
It starts with "use client" because it keeps state or passes functions to components, so it pastes into a Next.js page as it is. Other React setups ignore the directive.
This code, running — no configuration beyond the data
Keyboard
- ↑→↓←
- Step up or down
- Shift+arrowsPageUpPageDown
- A tenth of the range
- HomeEnd
- Minimum or maximum
- BackspaceDelete
- Return home
Source & setup
Add this component to your project with the shadcn CLI. The command copies its source into your configured UI directory, with base.css, Mizu’s tokens, and the stylesheets that hold its rules. Each rule lives in one stylesheet, so components you add together never repeat CSS. In a project without a components.json, run npx shadcn@latest init 0xuser64bit/mizu/preset first: plain init installs shadcn’s theme into your global CSS. Then load the fonts.
npx shadcn@latest add 0xuser64bit/mizu/knobEvery component imports from its own path, its name in kebab case. Its source, signature/Controls.tsx, also holds Fader and XYPad. Each has its own command and path; adding one after this copies only its small entry file. To paste the example, replace its mizu-ui import with:
import { Knob } from "@/components/ui/mizu/knob";For npm imports, import mizu-ui/styles.css once. Fonts are optional via mizu-ui/fonts.css. Override --mizu-* tokens or use className for local styling. Requires React and Motion. A Client Component: its source starts with “use client”.
Inspect signature/Controls.tsx
Source is included in the npm package under src/signature/Controls.tsx.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label / value / defaultValue / onValueChange | string / number | — | The control's name and value. |
| onValueCommit | (value) => void | — | When a drag, key press or reset finishes: the moment to save or send. |
| min / max / step / taper | number / linear | log | — | Range (0–100) and step (1); a log taper spreads ratios evenly and needs a positive min. |
| format / resetValue | (value) => string / number | — | Readout text, and where a reset returns (defaultValue). |
| bipolar / size | boolean / number | — | Fill from the centre, for pans and offsets; diameter (64). |
| name / disabled | string / boolean | — | Submit with a form; switch off. |
Accessibility
Behind the drawing is a native range input: it takes focus, answers the arrow, Page, Home and End keys, reads its value as formatted text, and submits with a form when named. Shift steps by a tenth of the range, Backspace or Delete returns home, and focus shows in the accent.
Motion
The value arc and pointer spring to changes from keys, resets and code, and follow the hand directly while dragging; bipolar knobs fill from the centre. Reduced motion jumps instead of springing.