Studio
A rotary control built as a UI SDK primitive: drag, arrow keys, log scales, double-click reset, agent actions.
Instruments built from UI SDK behaviors: a knob, a patch bay with cables, a fader, a level meter and a step sequencer. They make creative and audio tools, and they're the clearest demo of what a skin does: put them in the Studio skin and they look and sound like a rack.
pnpm dlx shadcn@latest add superzero11/uiset/knob superzero11/uiset/patch-bay superzero11/uiset/fader superzero11/uiset/level-meter superzero11/uiset/step-sequencerParts
| Part | Item | What it is |
|---|---|---|
Knob | knob | A rotary control, built as a UI SDK primitive: drag, keys, log scales, double-click to reset |
PatchBay, PatchBayJack | patch-bay | Jacks and the cables between them, by drag or by keyboard |
Fader | fader | UI SDK's vertical Slider with its label and readout |
LevelMeter | level-meter | UI SDK's Meter drawn as a ladder of lamps |
StepSequencer | step-sequencer | A row of steps on UI SDK's ToggleGroup, with downbeats and a playhead |
Use
import { useState } from "react"
import { Fader } from "@/components/ui/fader"
import { Knob } from "@/components/ui/knob"
import { LevelMeter } from "@/components/ui/level-meter"
import { PatchBay, PatchBayJack, type Cable } from "@/components/ui/patch-bay"
import { StepSequencer } from "@/components/ui/step-sequencer"
import { UISet } from "@/components/ui/uiset"
export function Synth() {
const [cutoff, setCutoff] = useState(900)
const [cables, setCables] = useState<Cable[]>([])
const [pattern, setPattern] = useState<string[]>(["1", "5", "9", "13"])
return (
<UISet skin="studio" sound>
<PatchBay aria-label="Patch bay" value={cables} onValueChange={setCables}>
<Knob
label="Cutoff"
min={20}
max={20000}
scale="log"
value={cutoff}
onValueChange={setCutoff}
format={(hz) => `${Math.round(hz)} Hz`}
/>
<PatchBayJack port="lfo:out" label="LFO out" />
<PatchBayJack port="filter:in" label="Filter in" />
<Fader label="Master" defaultValue={70} />
<LevelMeter label="Signal" value={60} />
<StepSequencer label="Pattern" value={pattern} onValueChange={setPattern} current={4} />
</PatchBay>
</UISet>
)
}
- Knob takes
valueordefaultValue,min,max,step,largeStep,scale="linear" | "log",format(anIntl.NumberFormatoptions object or a function) andlocale.onValueChangefires as it turns andonValueCommitwhen it settles.hideLabelandhideValuehide the visible label or readout (the label stays the knob's name). - PatchBay owns the cables:
valueordefaultValue({ from, to }[]) andonValueChange. A jack'sportends in:outor:in, and cables run from an out to an in.labelsmaps ports to names for agents and descriptions; jacks' labels fill it in. - Fader is a vertical
Sliderwithlabel; LevelMeter is aMeterwithlabelandvalue. - StepSequencer is a multiple
ToggleGroup:valueis the steps that are on,steps(16 by default),currentthe playhead's index,stepLabel(step)each step's name.
Keys
| Keys | Does |
|---|---|
| Arrow keys | Turn a knob, move a fader, move along the sequencer |
| Page Up, Page Down | Turn a knob by its large step |
| Home, End | A knob's minimum or maximum |
| Double-click | Reset a knob |
| Enter on an out jack | Start a cable; arrows choose an input; Enter plugs it |
| Space | Turn a sequencer step on or off |
Every change reads out to screen readers: a knob says its formatted value, a jack says what it's patched to.
For agents
Knobs offer setValue, increment, decrement and reset; the patch bay offers plug,
unplug and clear, and lists its ports. Faders, meters and the sequencer are UI SDK's
slider, meter and toggle group, with their own actions. The Kits page has
an agent playing the rack from prompts like "make it darker".
Skin and sound
These work in any skin; the Studio skin draws them as hardware (see
Studio's design notes). With sound on the root, turning and
plugging make short mechanical sounds.