Private beta

Syntho UI Kit

The controls a plugin interface is actually made of — knobs, faders, XY pads, footswitches, assignable CC strips. They draw themselves in SVG and inline styles rather than utility classes, so they carry no Tailwind config and no stylesheet of consequence, and the same components render in a web page and inside an exported VST3 without a second implementation.

Nothing here is a dependency you take on. The CLI copies the source into your project and you own it from then on.

Live demo

A whole front panel, composed from the kit

Everything below is interactive and wired to one piece of React state. Drag a knob, hold Shift for a fine pass, double-click to reset it. Drag a CC chip by its grip to reorder the strip. The parameter line along the bottom is the panel's live state, as an engine would receive it.

Palette
Finish
Filterhausweb · vst348 kHz · 128 smp

Sequence

D5C5B4A4G4F4E4D4C4B3A3G3

Filter

2.20 kHz
35%
28%
C
45% · 60%

Envelope

EQ

Delay

340 ms
42%
Sync
OFF
Drive
ON

MIDI CC

ModBreathFootVolumePanExprBright
Drag a chip onto any knob or fader; Enter picks one up for the keyboard and arrows choose the control. Click a CC badge to set its channel, range and curve, or alt-click any control to learn the next controller that moves.
map: Mod→Cutoff(200..6000 exp)
Out
0.0 dB
Send
30%
Bypass
OFF
cutoff=2200 reso=0.35 drive=0.28 pan=0.00 time=340 fb=0.42 tone=0.45 depth=0.60 out=0.0 bypass=0

Install

One CLI command per control

The kit is published as a shadcn registry. Point your components.json at the @syntho-ui namespace once, then add controls by name. Each one arrives as source in your own tree — no package to version, no build step, and every dependency it needs comes along with it.

$ npx shadcn add @syntho-ui/knob
$ npx shadcn add @syntho-ui/fader @syntho-ui/xy-pad

One-time setup in components.json

components.json
{
  "registries": {
    "@syntho-ui": "https://engine.syntho.app/r/{name}.json"
  }
}

Controls

Everything in the registry

Each card is a live instance. Open one for its full source, props, and install command.

Controls

2.20 kHz
35%
C
60%
60%
60%
60%

Drag or scroll to turn — a diagonal drag counts, so long as it isn't running across the knob's axis. Shift-drag is fine; Shift+arrow advances five steps. Double-click to reset.

Knob

knob

SVG potentiometer with an arc track and a lit value arc.

Viewshadcn add @syntho-ui/knob
default
flat
channel
vintage
minimal
neon
Out
0.0 dB
Send
25%
Mix
50%

Fader

fader

Channel-strip slider, vertical or horizontal.

Viewshadcn add @syntho-ui/fader

Dual Band Selector

dual-band-selector

The Logic-style Low Cut / High Cut band bar.

Viewshadcn add @syntho-ui/dual-band-selector
2.20 kHz · 40%

XY Pad

xy-pad

Two-dimensional drag surface with a trailing glow.

Viewshadcn add @syntho-ui/xy-pad
BellHatBlock

Triangle Pad

triangle-pad

Two normalized controls, three post-computed corner weights.

Viewshadcn add @syntho-ui/triangle-pad
Bypass
ON
Drive
OFF
Sync
ON
flat
vintage
minimal
neon

Toggle Switch

toggle-switch

Rocker, stomp or hardware lever with a satisfying pressed state.

Viewshadcn add @syntho-ui/toggle-switch

Hold the first, latch the second, or use the smaller console faces for vintage hardware panels. Space and Enter work too.

Glow Button

glow-button

Lit performance and console buttons whose glow can follow the music.

Viewshadcn add @syntho-ui/glow-button
CC74
88Cutoff
CC71
34Reso
CC1
12Mod
CC91
56Verb

Turn a knob, or drag a chip by its grip to reorder.

CC Knob Strip

cc-knob-strip

Draggable MIDI CC chips you can turn and reorder.

Viewshadcn add @syntho-ui/cc-knob-strip
50 ms
300 ms
60%
900 ms

default — loose pieces, bring your own panel

50 ms
300 ms
60%
900 ms

frame + variant="compact" — the little black box

Drag a handle and the knobs follow; turn a knob and the shape follows. Both editors edit the same value.

Envelope Editor

envelope-editor

The envelope shape and its four knobs, kept in sync.

Viewshadcn add @syntho-ui/envelope-editor
Low 90 Hz +4.0 dB · Q 0.70Low mid 420 Hz -3.5 dB · Q 1.20Presence 2.60 kHz +3.0 dB · Q 1.60Air 9.00 kHz +5.0 dB · Q 0.70

Drag a handle for frequency and gain, wheel over one for Q, or tab to it and use the arrows — Alt+Left/Right (or [ and ]) for Q, Shift for a fine pass. In bars mode the columns stand at their own frequencies, so the curve behind them is the curve they make.

EQ Editor

eq-editor

Hands on the curve: N draggable bands, two readings.

Viewshadcn add @syntho-ui/eq-editor
CHANNEL VOCODER
Modulator envelopes reshape the incoming carrier
ANALYSIS / MODULATORCARRIER / EXCITER
120 Hz
12.00 kHz
120 Hz
12.00 kHz
4.00
8.00
8.00 ms
80.00 ms
0.0 dB
100%

Vocoder Panel

vocoder-panel

Speech envelopes mapped onto a carrier, with the routing visible.

Viewshadcn add @syntho-ui/vocoder-panel
Run
ON

Tap a cell to toggle it, drag across a row to paint a stroke, drag up or down on a lit cell to ride its velocity (Shift is fine). Velocity is fill height and brightness both; gate is the fill's width. The playhead is a prop — this demo owns the clock, the grid just draws it — and the page follows it.

Step Grid

step-grid

The sequencer grid: tap, paint, ride the velocity.

Viewshadcn add @syntho-ui/step-grid
3
8
0
Run
ON

E(3,8) — gaps 3-3-2. Euclid spreads the pulses as evenly as whole steps allow, which is why the gaps only ever take two values one step apart, and why the defaults here are E(3,8): the 3-3-2 tresillo, a rhythm that already existed long before Bjorklund wrote the algorithm down. Rotate and the polygon spins without changing shape — the pattern is a necklace. The playhead is a prop: this demo owns the clock and advances a fractional step position at 2 steps per second, so the hand sweeps smoothly between nodes and the highlight snaps to the nearest one.

Rhythm Wheel

rhythm-wheel

A bar as a circle, and the shape the pattern makes.

Viewshadcn add @syntho-ui/rhythm-wheel
120BPM
250 ms · 4.00 Hz
1.1.1 bar.beat.16thstep 250.0 msnot armed

The demo owns the clock — an interval integrating beats, which is why dragging the tempo speeds the transport up from where it is instead of rewriting where it has been. The component only ever receives that position as a prop and pulses its light from it, the same rule lfo-visualizer and step-grid follow. Drag the number to set the tempo (Shift for tenths, double-click to reset), or tap the key four times: tap tempo here is pure maths over a list of timestamps, median-averaged so one fumbled tap does not move it. Swing lives in the same lib, built and tested with no face passing it yet — the sequencer that wants it is still coming-soon, the same call step-pattern made about rotateSteps.

Transport Controls

transport-controls

Play, stop, loop, a tempo you can drag, and a division that means something.

Viewshadcn add @syntho-ui/transport-controls
QWERTY keys play · space panics− / = octave 0

Press a key: the velocity comes from how far down the key you land, front loudest, with a floor so an edge tap is quiet rather than silent. Drag along the keys to glissando — the previous note is released as the next is struck — or play from the QWERTY row (space panics, − and = shift the octave). This demo is a scale-locked instrument: strikes outside the scale are declined, and a declined key draws struck-but-silent rather than dark, because a key that produces nothing is otherwise indistinguishable from a broken one. No audio here: the kit emits notes, hosts make the sound.

Piano Keyboard

piano-keyboard

The playable surface: press, glissando, type.

Viewshadcn add @syntho-ui/piano-keyboard
Waveform

The selector owns the choice. The oscillator or LFO receives the value and remains the source of truth.

Waveform Selector

waveform-selector

A visual waveform picker in a compact popover.

Viewshadcn add @syntho-ui/waveform-selector

Viewers

Drag the peak, the knee or the tail. Handles are focusable — arrows step, Shift is finer.

Envelope Display

envelope-display

An ADSR envelope you can draw on.

Viewshadcn add @syntho-ui/envelope-display
L
R
L
R

Synthetic signal for display only — this demo produces no audio.

Level Meter

level-meter

Volume bars with peak hold.

Viewshadcn add @syntho-ui/level-meter
IN
GR
OUT
IN
GR
OUT
GR
IN
GR
OUT

A synthesised programme through a modelled 4:1 compressor — the GR bar hangs from the top and holds its deepest recent bite.

Gain Reduction Meter

gain-reduction-meter

Compressor metering: IN and OUT bars, GR hanging from the top.

Viewshadcn add @syntho-ui/gain-reduction-meter

Four bands, summed from their biquad coefficients — no analyser involved. The travelling dot is the cursor prop: a frequency in, a point on the real curve out, for modulated filters.

EQ Display

eq-display

Filter response curve, computed rather than measured.

Viewshadcn add @syntho-ui/eq-display
-60-60-48-48-36-36-24-24-12-1200INPUT dBOUTPUT dB
GR
--
-24.0 dB
4.0:1
+6.0 dB

The shaded strip is the knee — the soft in soft-knee, drawn as a width rather than implied by a number. The meter is fed a level sweeping through the threshold, read through this same curve.

Dynamics Display

dynamics-display

Transfer curve for a compressor or a gate, plus its GR meter.

Viewshadcn add @syntho-ui/dynamics-display
-1-1-0.5-0.5000.50.511INPUTOUTPUT
40%
Live
ON

The dashed diagonal is the signal untouched; the gap to the curve is the distortion, at true scale. The bright stretch is the part of the curve a swelling tone is exercising, measured from real samples.

Transfer Curve

transfer-curve

What a waveshaper does to a sample, drawn.

Viewshadcn add @syntho-ui/transfer-curve
0 ms500 ms1.00 s1.50 s2.00 s2.50 s
250 ms
55%
40%
120 bpm grid
OFF

11 audible repeats above -60 dB, a 2.89 s tail. Height is level and so is opacity: by the fifth repeat a pip is two units tall, and one cue is not enough to read a tail by. The hollow pip at zero is the dry hit, whose own height is 1 - mix, because the stage crossfades rather than adding a send.

Delay Tap Display

delay-tap-display

A delay's echo train, drawn on a time axis.

Viewshadcn add @syntho-ui/delay-tap-display
tempo
prog
masks
4x
60 ms
128.5
Ghost segments
ON

Segment Display

segment-display

The LED readout off the front of a rack unit.

Viewshadcn add @syntho-ui/segment-display
bitmap
99
99
Scroll long text
OFF
5x8 (descenders)
ON

Dot Matrix Display

dot-matrix-display

The character screen bolted into the front of a rack unit.

Viewshadcn add @syntho-ui/dot-matrix-display
D5C5B4A4G4F4E4D4C4B3C4C5G4F4C4

Playing: the head sweeps and the readout counts bar.beat.sixteenth. Stop it and the cursor and readout vanish — a parked playhead at zero reads as a bug, so it is simply not drawn. Click a note to select it; Shift-click to extend. Turn on Edit to move and stretch notes (experimental — no sequencer consumes edits yet). Every colour is a --uikit-* token, so the roll follows the preview plane's theme — the same channel a host that repaints per team uses.

Piano Roll

piano-roll

The whole loop as a pitch × beat note grid — rendered at once.

Viewshadcn add @syntho-ui/piano-roll
KickSnareHat

Kick, snare and hats over one bar. Push the Swing slider and watch the offbeat hats slide to the right of their sixteenth line — the same movement a step-dot grid hides, because it snaps every hit to the middle of its cell. Each hit is a dot at its real onset; velocity sets its size, so the ghosted offbeat hats read as quieter. The head sweeps and lights whatever hit it is on. Same playhead, active-state and theming as the piano roll — a drum view is that roll with named lanes instead of pitches.

Drum Lane

drum-lane

Named lanes and hits drawn where they land, so swing is visible.

Viewshadcn add @syntho-ui/drum-lane
KICKCLAPPERC
Predicted recovery curve - playhead free-running at 128 BPM, not locked to any host.

The scope draws the grid, the dB gutter, the dashed budget line and the playhead; the cyan curve comes from the demo through the children render slot, using the same layout.xForBeat / layout.yForDb the grid was drawn with — which is why it cannot drift out of alignment with the onset ticks below. Push Swing and the ghosted offbeat percs slide off their sixteenth lines. Tick Host transport and the playhead switches to the stand-in DAW's ppqPosition; the caption follows the clock's reported source rather than claiming a sync it does not have. Stop, and the playhead disappears entirely.

Beat Grid Scope

beat-grid-scope

Bars across, dB downward, and a slot where you draw the signal.

Viewshadcn add @syntho-ui/beat-grid-scope
AuditionHost syncOutput tapnot measuredSourceInternal (fallback)

Four chips, four different claims. Audition and Host sync toggle between lit and off — the facility is there either way. Output tap is the one that matters: when the host publishes no tap it goes dim, not off, because "this host cannot tell me" is a different statement from "measurement is switched off", and a face that draws them the same has told you something false about your session. Source sits on warn: engaged, but not the source you asked for. Only live pulses.

Status Chip

status-chip

Five states a face can tell apart, including the two that matter.

Viewshadcn add @syntho-ui/status-chip
Reduction-14.0dBMeasured from the output tap
Budget-18.0dBHard ceiling
Tempo128BPMHost
GrantsNot reported by this host

Untick the tap and the first readout becomes an em dash with a note saying why — not 0.0 dB, which would be a measurement nobody made. A real zero still prints as zero; that negative case is pinned in the test, because confusing a measured 0.0 with "no reading" is the same bug wearing the other hat. Push the reduction past the budget and the value alone takes the warning accent, while the placeholder readout on the right never lights up at all. Figures are tabular, so the number does not reflow as its digits change.

Value Readout

value-readout

A big honest number: tabular, unitted, and a dash when there is nothing.

Viewshadcn add @syntho-ui/value-readout
L
R
M
S
MID / SIDE0% side
CORRELATION-1 · 0 · +1+1.00
C
35%
Auto-pan
OFF

Two knobs draw, one measures. Pan and Width are the parameter side — the solid cursor and the band around it are what was asked for, animated here by the demo's own interval the way an auto-panner would animate them from its LFO. The hollow diamond is the signal side: where the energy actually landed, which sits at tan(p·π/4) rather than at p, so at half right the knob says 0.50 and the meter says 0.41 and both are correct. Decorrelate slides the right channel's phase; the meter reads the cosine of it (+1.00 at 0°), and panning does not move it at all, because correlation is invariant to per-channel gain — until the very ends, where one channel goes silent and the meter drops to zero rather than claim a phase relationship with nothing. Past 90° the needle crosses into the red half, and that half is the one that matters: material below zero cancels itself the moment anything downstream folds to mono — a phone speaker, a club's sub feed — so at -1 the sound you are mixing simply is not there. For the shape of the image rather than its numbers, put a lissajous-scope beside this; the two are the same signal seen from opposite ends.

Stereo Field

stereo-field

Where the sound sits between the speakers, and whether it survives a mono sum.

Viewshadcn add @syntho-ui/stereo-field
DiagnosticsfailedMock Diagnostics · disconnectedv0.0.0-mock · 0000000 · built 2 hours ago
Healthfailed
Feeds0/11 ok
Buildv0.0.0-mock · 0000000 · built 2 hours ago
HostCodex Mock Host · 48 kHz · 512 smp
Latency0 smp (0 ms)
Linkdisconnected

Report

A ten-line summary for chat, then the full JSON report beneath it.

Runtime

Runtime healthUnreported
First errorUnreported
Build modedevelopment
Connectiondisconnected

Feed health

Per-feed delivery health, measured from arrival timestamps.
FeedExpectedObservedAgeDroppedVerdict
host30 Hz0 Hznever0silent
transport30 Hz0 Hznever0silent
midiIn30 Hz0 Hznever0silent
midiOut30 Hz0 Hznever0silent
meters30 Hz0 Hznever0silent
scope15 Hz0 Hznever0silent
lifecycle30 Hz0 Hz0 ms0starved
counters30 Hz0 Hznever0silent
params30 Hz0 Hznever0silent
presets30 Hz0 Hznever0silent
clock30 Hz0 Hznever0silent

Identity

Buildv0.0.0-mock · 0000000 · built 2 hours ago
ModuleMock Diagnostics
Idcodex.mock.diagnostics
VendorCodex Music
Version0.0.0-mock
Classeffect
Targetdev-runner
SDK0.0.0

Feeds

Subscribedhost, transport, midiIn, midiOut, meters, scope, lifecycle, counters, params, presets, clock
Declaredhost, transport, midiIn, midiOut, meters, scope, lifecycle, counters, params, presets, clock
Max feed rate30 Hz
Dropped0 feed / 0 midi / 0 lifecycle

Every tab on a scripted mock host — seeded, so these are the same frames on every visit. Values come from the snapshot or render as an explicit Unreported cell; nothing here is a default dressed up as a measurement. The Sampler tab appears only because this mock declares a bank table — it is capability-gated, so a synth never shows it. Overview leads with the status strip; Audio puts four viewers on one shared animation frame with a trigger and a single-shot freeze; Events filters by kind, severity and "since last preset load". Under 480 px the rail collapses to glyphs and keeps its labels for screen readers.

Diagnostic Panel

diagnostic-panel

What the host told the plugin, what reached it, and what it produced — in eleven tabs.

Viewshadcn add @syntho-ui/diagnostic-panel

A module face

Right-click anywhere here, or press Ctrl/Cmd+Shift+D, to open the diagnostics modal, and Escape to close it. It stays centered in the viewport, moves focus into the rail on open, and returns it to the face on close. Click outside the panel to dismiss it.

Mounted with policy="always" so the docs page can show it; under the default "development" policy it appears only for a development build, the dev runner, or a face with no host at all.

Diagnostic Overlay

diagnostic-overlay

Right-click a module face to open its diagnostics, and only where that is allowed.

Viewshadcn add @syntho-ui/diagnostic-overlay

Visualizers

Synthetic signal for display only — this demo produces no audio.

Oscilloscope

oscilloscope

Time-domain waveform trace.

Viewshadcn add @syntho-ui/oscilloscope

One mono signal against a 248° phase-shifted copy of itself. The trail decays instead of clearing, so the figure keeps a phosphor tail.

Lissajous Scope

lissajous-scope

A vectorscope figure from a single mono signal.

Viewshadcn add @syntho-ui/lissajous-scope
MSSLR+10-1
Auto-gain
ON
Split L/R
OFF

Kick and bass centred, hats ticking off to the side, a Haas-delayed pad and an uncorrelated reverb tail. The bright vertical spine is the low end; the cloud around it is the pad and the room. Measured width here is 20%.

A 96 BPM mixdown — kick, hats, a Haas-delayed pad and an uncorrelated reverb tail — synthesised a frame at a time and handed over through getStereoData, the same contract an engine tap satisfies, so the component cannot tell this from a live analyser pair. The page stays silent: nothing here builds an AudioContext. The 45° rotation is what makes the reading free — an unrotated X-Y plot puts mono on the diagonal, and lissajous-scope draws exactly that. Here upright is mono, so “is it standing up” and “does it survive a mono sum” are the same question. Turn Auto-gain off and the trace plots at the signal’s own amplitude; the CORR and WIDTH readouts do not move when you do, because they are taken from the raw pair and never from the scaled copy — a meter that moved with the display gain would be lying.Split L/R swaps the rotated diamond for the raw per-channel plot: X is left, Y is right, and mono moves from the vertical to the rising diagonal. It answers a different question — about the channels rather than the image — so a dead channel collapses the figure onto one axis and a level mismatch tilts the diagonal, both of which the diamond hides. For the same signal’s numbers rather than its shape, put a stereo-field beside this.

Goniometer

goniometer

The stereo image as a shape — mono straight up, phase problems flat.

Viewshadcn add @syntho-ui/goniometer

Synthetic spectrum for display only — this demo produces no audio.

Spectrogram

spectrogram

A scrolling time × frequency heatmap.

Viewshadcn add @syntho-ui/spectrogram

Particles settling on the nodal lines, and the same modes rendered as a field on a circular plate. Drag the slider to retune the plate.

Chladni Plate

chladni-plate

The nodal figure sand draws on a driven plate.

Viewshadcn add @syntho-ui/chladni-plate

Drawn from the waveform's closed form, not measured — the cursor rides its own clock at the shown rate.

LFO Visualizer

lfo-visualizer

An LFO's waveform, with a cursor on the live phase.

Viewshadcn add @syntho-ui/lfo-visualizer
CGDAEBF♯C♯G♯D♯A♯F

A C-major histogram on the wheel. The seven notes of the key form one unbroken arc, and the needle points at the tonal centre — sitting just off C, pulled by the relative minor.

Circle of Fifths

circle-of-fifths

A pitch-class histogram on the wheel, with a tonal-centre needle.

Viewshadcn add @syntho-ui/circle-of-fifths
CC♯DD♯EFF♯GG♯AA♯B

Every major triad is the same triangle at a different rotation — step through the chords to watch it turn, and switch the ring order to see the same chord take a different shape.

Pitch Class Clock

pitch-class-clock

Chords as shapes on a twelve-note dial.

Viewshadcn add @syntho-ui/pitch-class-clock

The five accidentals never sound, so they sit at the stub floor. The tick under C marks the tonic; the outlined bars are the chord playing now.

Pitch Class Histogram

pc-histogram

Twelve bars: how much each pitch class sounded.

Viewshadcn add @syntho-ui/pc-histogram
CGAmF

I-V-vi-IV. The thick ties are the two-note relationships — C to Am, Am to F — which is why those swaps feel so smooth. G shares nothing with Am or F, so it sits unconnected to either.

Chord Graph

chord-graph

How the chords in a progression connect, by shared notes.

Viewshadcn add @syntho-ui/chord-graph

C and Cm draw the identical shape — they are inversions of each other, and the vector cannot tell them apart by design. The diminished seventh is all minor thirds and tritones; the whole-tone scale has no minor thirds or fourths at all.

Interval Vector Chart

interval-vector-chart

The harmonic fingerprint of a chord, in six bars.

Viewshadcn add @syntho-ui/interval-vector-chart

Slide to 0 and the row is the key alone — the same seven notes stay lit whatever you hold. Slide to 1 and it tracks only the chord. In between, the notes belonging to both glow brightest.

Consonance Matrix

consonance-matrix

Which of the twelve notes fit what you are playing.

Viewshadcn add @syntho-ui/consonance-matrix
sounding
Cmaj7
major seventh
NotesC, E, G, B
PC set{0, 4, 7, 11}
Chroma100010010001
Set number2193
Forte4-20
Prime form[0158]
Set classMajor-seventh Chord
Consonance
0.51
Mirror

Am/C is the inversion test — C is in the bass, but A is still the root, so it names as Am rather than a rootless C6. The diminished seventh is symmetric: all four rotations are equally valid names, and the alternatives say so.

Chord Readout

chord-readout

Everything analysis can say about what is sounding.

Viewshadcn add @syntho-ui/chord-readout

Synthetic signal for display only — this demo produces no audio.

Spectrum

spectrum

FFT magnitude, as bars or a filled curve.

Viewshadcn add @syntho-ui/spectrum

Foundations

beatxForBeatpiano roll xyForDb(beat dB)
034.0034.008.00
168.7568.7530.33
2.5120.88120.8863.83
3.75164.31164.3191.75
8312.00312.00142.00
0 → y 8.0-6 → y 41.5-12 → y 75.0-18 → y 108.5-24 → y 142.0

The two x columns are the point: the beat grid's xForBeat and the piano roll's are the same numbers, because they are the same function — the grid builds on createLaneLayout rather than growing a second time axis, and the test asserts the agreement at every subdivision. The dB column runs the other way: 0 dB at the top of the plot, reduction downward, and the axis floor labelled −∞ because it is the bottom of what the plot can show rather than a value anyone measured.

Beat Grid Geometry

beat-grid-geometry

The bars-across, dB-down plot as pure maths — sharing the piano roll's x axis.

Viewshadcn add @syntho-ui/beat-grid-geometry
Phase0.000beat 0.00 of 8
Clockfree

Free-running at 120 BPM — a plausible illustration, not the host's position. Tick Host transport and the phase starts coming from a stand-in DAW's ppqPosition; untick Transport playing and it falls back to free-running, because a face frozen on the host's last position looks broken — but note it keeps the host's tempo, since the tempo is real even when the position is not. The source field exists so a caption can state which of those is true instead of implying a sync it does not have.

useBeatClock

beat-clock

Where the playhead is — and whose clock said so.

Viewshadcn add @syntho-ui/beat-clock
Ratio
slot
4:1
Mode
slot
Peak

Control Label

control-label

The caption and readout wrapper the other controls share.

Viewshadcn add @syntho-ui/control-label

Theming

Palette and finish are independent

Palette values cascade through CSS custom properties. Shape and material come from one panel-wide skin provider. Keeping those axes separate lets the same flat finish work with Bone, Midnight, Ember, or any palette you define.

Use the live Palette and Finish controls above to compare the combinations without navigating away or resetting the demo.

panel.tsx
<ControlSkinProvider skin="flat">
  <div
    style={{
      "--uikit-accent": "#f97316",
      "--uikit-surface": "#1b1512",
      "--uikit-cap": "#33241c",
      "--uikit-radius": "3px",
    }}
  >
    <Knob label="Cutoff" min={20} max={20000} defaultValue={2200} />
    <Fader label="Out" min={-60} max={6} defaultValue={0} />
  </div>
</ControlSkinProvider>

The panel is half of it

These controls send values somewhere. The other half is the DSP behind them — written once in TypeScript, compiled to WebAssembly for the browser and to a native library for the plugin.