DOCS / UI REFERENCE
Components
Five primitives cover the render surface. All of them accept className, style, and the pointer props listed in Events & gestures.
<View>
The flexbox container — the div of VSReacT. Backgrounds, borders, rounded corners, shadows, opacity, scroll containers, and knob arcs are all drawn on Views.
<View className="flex-1 flex-row items-center gap-4 p-6
bg-zinc-900 rounded-xl border hover:bg-zinc-800">
{children}
</View><Text>
Draws strings and numbers. Font size, weight, family (font-mono), letter-spacing, line-height, alignment, and color come from classes or style. Text nodes measure themselves into the Yoga layout, so a Text sizes its container like you expect.
<Text className="text-2xl font-bold tracking-tight text-center">
{gainDb.toFixed(1)} dB
</Text><Image src>
Paints an image from a file path or a data: URI, scaled to its layout box.
<Image src={logoDataUri} className="w-24 h-24 rounded-full" /><TextInput>
A real, chrome-stripped juce::TextEditor positioned by Yoga — real caret, selection, and IME, while VSReacT paints the box, border, and focus ring around it.
| PROP | TYPE | NOTES |
|---|---|---|
value / defaultValue | string | Controlled or uncontrolled, exactly like the DOM. |
placeholder | string | Color via the placeholderColor style key. |
disabled | boolean | Blocks focus and input. |
onChange / onSubmit | (value: string) => void | Submit fires on Enter. |
onFocus / onBlur | () => void | Pair with focus: class variants for focus rings. |
<TextInput
placeholder="Paste a link…"
className="w-full p-3 rounded-lg bg-zinc-900 border
focus:border-lime-400"
style={{ caretColor: "#C6F135", placeholderColor: "#6b7280" }}
onSubmit={(url) => native.call("download:start", { url })}
/>Built-in controls
Beyond the primitives, the SDK ships the classic VST controls, natively painted and drag-driven. Each takes a normalized 0..1 value (or an index) plus color/size props, and each has a Param* twin bound to a host parameter — see Audio parameters.
| CONTROL | FOR | NOTES |
|---|---|---|
<Knob> | Continuous values | Natively painted arc, vertical drag, wheel nudge, double-click reset to defaultValue; bipolar sweeps from 12 o’clock for pan-style params. |
<Slider> | Continuous values | Horizontal by default; vertical makes it a fader (drag up for more, fill rises from the bottom). |
<Toggle> | Bypass, on/off, A/B | Spring-animated thumb; click to flip. |
<XYPad> | Two values at once | 2D drag pad with crosshair — cutoff/resonance, pan/depth. y = 1 is the top. |
<Segmented> | Exclusive choices | A row of options — oscillator shapes, filter modes. |
<Select> | Long choice lists | A dropdown — the menu renders in the overlay layer, positioned under the trigger via onLayout, scrolls past maxMenuHeight, click-away closes. |
<Meter> | Levels | Hot zone + peak-hold line with decay; feed it 0..1 values (typically pushed from C++ via useNativeEvent). |
<GenericEditor> | Whole plugins | One knob per APVTS parameter — a complete UI in one line. |
<MacroPad> | Centerpiece macros | A circular 2D pad with value-reactive concentric rings — x spreads them, y drives intensity. ParamMacroPad drives two host parameters from one drag. |
<HardwareKnob> | Hardware feel | Skeuomorphic cap with a glowing pointer notch at the rim and a faint tick track; same DAW gestures as Knob. |
<Crossfader> | Mix controls | The DRY/WET strip — wide track, grippy rectangular handle, double-click recenters. |
<PulseOrb> | Presence | A value-reactive orb: glowing core with echo rings that emit faster and brighter as the level rises. |
<NumberBox> | Fine values | The draggable number — BPM, ms, semitones. Drag, wheel-step, double-click reset; ParamNumberBox shows the host’s formatted text. |
<Checkbox> / <RadioGroup> | Settings panels | Checkbox rows and vertical exclusive options; Param twins map bool and choice parameters. |
<ProgressBar> / <Spinner> | Feedback | Determinate progress with optional percent (or an indeterminate sweep); indeterminate spinner painted with the native arc keys. |
<PianoKeyboard> | Performance | The playable keyboard — note-on on press, note-off on release, glissando by dragging across keys; heldNotes paints host MIDI in. |
<StepSequencer> | Patterns | The rows × steps grid: click cells on and off, downbeat tinting, a playhead column the host drives. Fully controlled. |
<ADSREnvelope> | Envelopes | The four-corner envelope editor — drag the attack peak, the decay/sustain corner, and the release corner; ParamADSREnvelope drives four host parameters. |
<PitchBend> / <ModWheel> | Wheels | The performance wheels: pitch springs back to center on release, mod stays where you leave it; Param twins for both. |
<Tabs> / <Disclosure> | Structure | The page switcher with an underline tab bar, and the collapsible settings row — both controlled or uncontrolled. |
<EQCurve> | Filters | The real summed biquad response (RBJ cookbook) with a draggable node per band — drag for freq/gain, wheel for Q. Pure math exported. |
<RingMeter> | Levels | A circular level meter on the native arc keys: hot zone, optional center readout via format. |
<Button> | Actions | solid / outline / ghost variants, three sizes, hover/active baked in. |
<Bars> | Spectra | Bottom-anchored bar visualizer with a hot zone — one bar per array entry. |
<Waveform> | Waveforms & envelopes | Centre-mirrored bars; pair with useRollingBuffer for scrolling history. |
<Tooltip> | Hover help | Wraps any child; shows the tip below it after a hover dwell (delayMs), via the overlay layer. |
<Modal> | Dialogs | Centered panel over a click-away backdrop — confirms, settings, about boxes. |
<Toggle on={bypassed} label="BYPASS" onChange={setBypassed} />
<Slider vertical height={140} value={mix} onChange={setMix} />
<XYPad x={cutoff} y={resonance} onChange={(x, y) => { setCutoff(x); setResonance(y); }} />
<Segmented options={["SINE", "SAW", "SQR"]} index={shape} onChange={setShape} />
function OutputMeter() {
const [level, setLevel] = useState(0);
useNativeEvent("meter", (m) => setLevel(m.level));
return <Meter value={level} length={140} label="OUT" />;
}
<Tooltip label="Double-click resets to 0 dB">
<ParamKnob paramId="gain" />
</Tooltip>
<Modal open={showAbout} onClose={() => setShowAbout(false)} title="ABOUT">
<Text className="text-[12] text-zinc-400">MyPlugin 1.0 — built with VSReacT.</Text>
</Modal><NativeView nativeId>
The escape hatch: mounts any juce::Component you registered in the NativeRegistry inside the React layout. React owns its position and size; JUCE owns its painting. Perfect for waveform displays, meters fed from the audio thread, or any legacy component you are not ready to rewrite.
// C++ — register a factory
vsreact::NativeRegistry registry;
registry.registerFactory ("waveform", [this] {
return std::make_unique<WaveformDisplay> (processor);
});
// TSX — position it with flexbox
<NativeView nativeId="waveform" className="flex-1 rounded-lg overflow-hidden" />