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-sequencer

Parts

PartItemWhat it is
KnobknobA rotary control, built as a UI SDK primitive: drag, keys, log scales, double-click to reset
PatchBay, PatchBayJackpatch-bayJacks and the cables between them, by drag or by keyboard
FaderfaderUI SDK's vertical Slider with its label and readout
LevelMeterlevel-meterUI SDK's Meter drawn as a ladder of lamps
StepSequencerstep-sequencerA row of steps on UI SDK's ToggleGroup, with downbeats and a playhead

Use

tsx
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 value or defaultValue, min, max, step, largeStep, scale="linear" | "log", format (an Intl.NumberFormat options object or a function) and locale. onValueChange fires as it turns and onValueCommit when it settles. hideLabel and hideValue hide the visible label or readout (the label stays the knob's name).
  • PatchBay owns the cables: value or defaultValue ({ from, to }[]) and onValueChange. A jack's port ends in :out or :in, and cables run from an out to an in. labels maps ports to names for agents and descriptions; jacks' labels fill it in.
  • Fader is a vertical Slider with label; LevelMeter is a Meter with label and value.
  • StepSequencer is a multiple ToggleGroup: value is the steps that are on, steps (16 by default), current the playhead's index, stepLabel(step) each step's name.

Keys

KeysDoes
Arrow keysTurn a knob, move a fader, move along the sequencer
Page Up, Page DownTurn a knob by its large step
Home, EndA knob's minimum or maximum
Double-clickReset a knob
Enter on an out jackStart a cable; arrows choose an input; Enter plugs it
SpaceTurn 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.