# Compact nodes and shared interface components

> This document answers how Patch nodes are sized, how interface components are placed in Patch and Frame Design from one palette, which control faces and displays exist, and the cap

Source: https://docs.tune.toys/contributors/interface-components/

This document answers how Patch nodes are sized, how interface components are placed in Patch and Frame Design from one palette, which control faces and displays exist, and the capture/media bounds behind Scope and Screen.

**Status:** implemented in the browser editor and shared renderer with shared source conformance across browser/WASM/native. Browser fixtures qualify local software interactions, not external WebViews, codecs or DAWs. Native UI signal capture is unqualified. Live video Screens and the paint, curve, switcher and readout faces run in the browser; native hosts show their unavailable states ([video](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/video.md)). Arbitrary rendering scripts and imported 3D models remain planned.

Components may sit anywhere on the Patch. An empty-space palette drop creates a loose `Definition.widgets` entry at the pointer; dropping inside a Frame creates a `Frame.widgets` member. Dragging into or out of a Frame transfers ownership with converted coordinates in one Undo step. Both use the same shared renderer and Properties fields. Loose components persist through save/reload, support negative positions and do not appear in public playback until explicitly placed in a Frame.

## Node sizing

Patch defaults to 190px audio nodes, with undoable 140–640px instance widths. Drag the right edge, or focus its resize handle and use arrows (10px; Shift 1px). Visual component cards resize in both axes from their corner. Pointer and held-key gestures preview locally, commit once, and cancel on Escape, blur or source replacement. Parameter rows keep exact numeric editing without embedded sliders; full parameter sliders stay in Properties.

## One palette, two surfaces

Patch → Interface and Frame Design use the same component palette. **Components are explicit members of a Frame belonging to the current definition**; the first insertion creates that Frame when necessary. Patch positions use namespaced editor metadata keyed by Frame/widget identities. Existing Frame members can be placed from the palette's Existing components group. Frame-only members stay out of Patch until placed; closing a Patch card hides that view while retaining its Frame member. Changing a card's size edits its portable widget bounds. `WidgetView` projects the same member through the shared Frame board, including instance-relative public bindings, themes and asset receipts. Components do not pretend to be DSP nodes or acquire signal ports. The card's pencil opens its owning Frame for binding and appearance editing. Hidden Frame members stay hidden in Patch.

## Controls and displays

| Component                                                      | Binding                                                                                   | Notes                                                                                                                                                                                                                                                         |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Knob                                                           | One public numeric control                                                                | See [knob feedback](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/appearance.md#editor-preferences-and-controls)                                                                                                                                                                                            |
| Slider                                                         | One public numeric control                                                                | Rectangular fill/bar; automatic, horizontal or vertical orientation                                                                                                                                                                                           |
| Button, momentary button, trigger pad                          | One public numeric control                                                                | See [playable controls](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/playable-inspection.md#playable-controls)                                                                                                                                                                                             |
| Checkbox, Switch                                               | One public numeric control                                                                | Toggle appearances                                                                                                                                                                                                                                            |
| Switches                                                       | One public numeric control                                                                | Named segmented selector; values stay public numeric bindings                                                                                                                                                                                                 |
| XY pad, Joystick                                               | Two distinct public controls                                                              | Joystick defaults to spring return at the normalized center, including logarithmic domains; Properties change its face and spring behavior                                                                                                                    |
| Scope                                                          | One actual input/output/node source                                                       | Modes: oscilloscope, Hann FFT, rolling spectrogram, synchronized XY/phase and tuner, with channel choice and Freeze/Resume. The authored default mode is portable; changing a live mode does not edit the sound                                               |
| Screen                                                         | A verified attached asset or built-in scene                                               | Verified image, verified muted video with play/pause/seek, or a built-in interactive 3D cube/pyramid on canvas (drag/arrows orbit, +/- zoom, Home resets). Media mode, asset, fit and scene are authored in Properties; video decoding depends on host codecs |
| Live Screen                                                    | A video output of the definition                                                          | `mode: 'live'` with `source` and an optional `stream`; the host's video engine paints the canvas. Without one: "Video needs a host with a video engine". See [video](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/video.md#screens)                                                                        |
| Paint, Curve, Switcher, Readout                                | A `video.paint`, `std.wavetable` or `video.switch` node, or one parameter or control lane | Node faces; see [Frames](https://docs.tune.toys/contributors/frames/#widget-kinds), [video](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/video.md#screens) and [MIDI, control and mixing](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/midi-and-control.md#wavetable-and-the-curve-editor)                                                                                                |
| Piano, filter/ADSR editors, text, icons, panels, nested Frames | As documented elsewhere                                                                   | Distinct vector icons identify each face                                                                                                                                                                                                                      |

Checkbox/Switch are toggle appearances and Joystick is an XY appearance; they reuse existing numeric transactions, ownership, cancellation and MIDI/automation behavior and introduce no event engine. Screen and Scope are portable widget kinds admitted by the generated schema with shared browser/native/WASM semantics. Clipboard and reusable-component closure, asset remapping and node/asset deletion include their references.

Scope has an audio inlet on the Patch, accepting one 1–32-channel bundle. A cable writes the component's `source` and exact `port`; it does not add a DSP processor or alter audio routing. Properties offers the same audio-only endpoints. New Scopes start disconnected; Delete, the cut tool or **Disconnect audio** clears the binding, and Undo restores it. Scope mode fills the component's current width and height; XY retains equal axis scaling. Compact Scopes show no text beneath the plot.

## Capture and media bounds

Engine capture remains one selected source at a time and retains two synchronized 2048-sample lanes: the selected channel and the next channel, wrapping to channel zero (mono pairs with itself). Selection resets both rings, and storage counts toward preparation admission. The additive `tt_trace_secondary_value` ABI accessor exposes the paired lane. Sampling is allocation-free; the worklet serializes bounded arrays in its observation handler outside `process()`. Older pinned engines show paired-capture unavailability. Live inspectors share the most recent lease and restore earlier leases on close; this is not an unlimited simultaneous capture engine. See [signal inspection](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/playable-inspection.md#signal-inspection).

| Bound               | Value                                                                     |
| ------------------- | ------------------------------------------------------------------------- |
| Spectrogram history | 1024 × 512 UI canvas; FFT and drawing run on the UI thread                |
| Image               | 16 MiB encoded                                                            |
| Video (MP4/WebM)    | 16 MiB                                                                    |
| Decoded dimensions  | 8192 per axis and 16 megapixels                                           |
| Verification        | Byte length, SHA-256, declared type and decoded dimensions before display |

Freeze retains the actual snapshot. Blob URLs are reference counted and released on replacement/teardown. Videos pause on hidden pages and teardown. No credentials, local URLs or device bindings enter portable source.

The Slider's rectangular fill/bar and aspect-driven orientation were behavior references from the sibling Hotwire `ControlFace.svelte`. The React implementation and fixtures are original; no source or sibling build dependency was imported.

## Verification

Shared source conformance covers each Scope mode, control appearance, slider orientation and Screen asset admission across browser/WASM/native. Runtime signal fixtures check synchronized ring chronology, resets, isolation and invalid indices against actual WASM. Palette and clipboard tests exercise admitted members, independent identities, assets and atomic Undo (`apps/web/test/frame-palette.test.mjs`, `apps/web/test/interface-components.browser.mjs`). Root `npm run check` remains required.

## Implementation

- [`packages/frame-runtime`](https://github.com/joshstovall/TuneToys/blob/main/packages/frame-runtime/README.md) — control faces, Scope, Screen, `WidgetView`
- [`apps/web`](https://github.com/joshstovall/TuneToys/blob/main/apps/web/README.md) — component palette, Patch cards, Properties
- [`crates/engine`](https://github.com/joshstovall/TuneToys/blob/main/crates/engine/README.md) and [`crates/engine-ffi`](https://github.com/joshstovall/TuneToys/blob/main/crates/engine-ffi/README.md) — paired capture rings and `tt_trace_secondary_value`

## Related

- [Frames](https://docs.tune.toys/contributors/frames/) and [appearance](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/appearance.md)
- [Playable inspection](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/playable-inspection.md) and [performance widgets](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/performance-reuse.md#frame-widgets-and-tuning)
- [Patch editor](https://docs.tune.toys/contributors/patch-editor/) and [app shell palettes](https://github.com/joshstovall/TuneToys/blob/main/docs/architecture/settings-library.md)
