Internal · SpaceMusic Design

The Mobile Control Surface

520 controls, eight pages, four levels of hierarchy — and one thumb. The row is the control.

The shape of the problem

SpaceMusic is a real-time visual engine with a control surface to match: eight pages, 520 controls, 1 395 channels. On a desktop that is a sidebar and a wide window. On a phone it is 390 by 844 points, and most of them are already spoken for.

Subtract the two bars and 732 px of body is left. A 200 px preview and two navigation strips take it to about 444 px of list — roughly eight rows. Every page has to resolve into that, and the pages are not evenly shaped: Time carries three controls, Mapping carries 222 across four levels of nesting.

Time · 3 controls
Time · 3 controlsThe shallowest page in the product. No strip at all, so the preview stays open and the whole page fits above the fold.
Mapping · 222 controls
Mapping · 222 controlsThe deepest. Layer, then one of eight sections, then a group, then the control — four levels, all reachable by thumb.

The visual language

Monochrome, flat, dense with information but never busy. Geist for names, Geist Mono for anything technical — values, section titles, paths. Dark first. Lines only where they are structural.

bg#0b0b0c chrome#141418 track#141417 line2#35353c ink3#5d5d66 ink2#96969d ink#ececea fill#dcdcd9

Eleven tokens, no accent colour, and a light theme by swapping their values. The two bars carry --chrome, one step off the page background, because they never move and should not travel with the scroll.

The row is the control

No boxes, no separate widget on the right of a label. The control is the row: its width is the range, its fill is the value, and you drag it where it sits. Nothing has to be opened first.

The kit
The kitEvery kind, in the one row grammar. The row is the control: its width is the range, its fill is the value, and you drag it where it sits.

Centered and not centered

The distinction the earlier drafts missed. A range that starts at its minimum — Gain from 0 to 1 — fills from the left edge, because that is where the value actually starts. A range built around zero — X Translate from −10 to 10 — fills out of the zero tick, left or right.

That matters more than it sounds. Filling every slider from the left made −4.800 look like a positive quarter-turn. Now a negative value reads as negative, and a value of exactly zero draws no fill at all — just the cursor sitting on the tick.

Centered sliders in context
Centered sliders in contextX = 2.400 grows right out of zero. Y = 0.000 draws no fill at all, just the cursor on the tick. Z = −4.800 grows left. Three values, one glance, no reading of numbers.
The same element, another page
The same element, another pageZone strip, instance chips, dividers — identical components in identical order. Only the words change.

Four kinds, one rule

Only the two kinds that have a value to fill ever carry white. A slider fills to its position in range; a toggle that is on fills completely. A dropdown has no quantity to show, so it stays plain and the minus / plus cells at the right edge do the work — the minus dimmed on the first option, the plus on the last. A button has nothing to fill either, so the row stays empty and only its edge cell is live, which is also what stops a stray drag from firing it.

An earlier pass did fill the dropdown to its position in the list. It read as a slider, and on the last option it read as a toggle that was on. Removing it cost nothing and settled both.

Button, toggle, dropdown
Button, toggle, dropdownThe clearest board for telling them apart: the button row is empty with one live cell, the toggle row is the switch, the dropdown row is plain with two cells.
Mixed, in one column
Mixed, in one columnSeven controls of three kinds. Point Size, Density, Twist and Alpha carry ink; Shape, Blend Mode, Cap Style and Sort Order do not. The column reads at a glance.

The screen grammar

Five bands, in the same order, on every page. The top bar is identity and the bottom bar is position — which is why the page name is stated once, in the bottom breadcrumb, and never repeated at the top.

Figure 1 · Screen anatomy and the four control kinds Open full size · print A3 landscape ↗

THE SCREENPREVIEWZONEINSTANCEDIVIDERTop bar · 56 pxlogo · SPACE MUSIC · free slotPreviewclosed / partial / full — the eye cycles itStrips — at most twowhich zone, and which instanceListone full-bleed row per controlBottom bar · 56 pxpreview · PAGE / sub-path · menuFOUR KINDS, DRAWN 1:1 — 390 × 56Gain0.640X Translate2.400Shadowmap SizeMediumRenderONExport AllOnly the two kinds with a value to fill ever carry ink:a slider’s position in range, and a toggle that is on.A dropdown has no quantity to show, so it stays plainand the minus / plus at the edge do the work.

Both bars are 56 px, so the chrome is a constant 112 and the body is whatever is left. A control row is 56 px too, 58 with its gap, so seven or eight of them fill the list. The preview is the slack: a short page opens it wide, a dense one shrinks it to 104.

No strip ever holds more than four word tabs, a rule that turned out to be already true in the data: Mapping’s Layer level has exactly eight sections, which lands as a 4×2 grid, and Material, Position, Rotation, Scale and Pivot each carry exactly four groups. Number chips are the one exception; those may run to eight across.

A page can nest four levels deep, and the tempting move is a strip per level. Three strips eat 132 px and the list has none to spare.

  1. At most two strips. One for the zone, one for which instance. Nothing deeper ever becomes a strip. Input → 1D → plugin 2
  2. Everything below that is a collapsible divider in the scroll. Strips are for levels you switch between constantly; dividers are for levels you open, work in, and close. Two dividers can also be open at once, which a strip can never do. Files · Parameters · Options
  3. A strip exists only when its level has two or more items. The ladder shrinks to fit the page rather than being padded out to a fixed shape. Time shows no strip at all
No strip · Time
No strip · TimeThree controls and nothing to switch between, so there is no strip at all and the bottom bar says so rather than leaving you guessing.
Uneven zones · Environment
Uneven zones · EnvironmentLights and Stages each carry instances; Camera carries none, so its second strip is simply not there. The strip stack is per zone, not per page.
Orphan controls · Placement
Orphan controls · PlacementAdd and Remove Placement belong to no zone, so they get a MAIN tab. The strip is always the first thing under the preview.
Two strips · Input
Two strips · InputZone, then which of six plugins. Four unipolar sliders in a column — reading their fill widths as one shape is what this style does better than any boxed row.

What a hold opens

The list is deliberately quiet. Precision arrives only when you ask for it, and it arrives as a sheet that rises over the page rather than a screen you navigate to. The strips and the preview stay exactly where they were, dimmed, and the bottom bar sits on top of the scrim so the breadcrumb stays readable.

Hold for the sheet
Hold for the sheetA short drag moves the value; a long press opens this. The header says HELD so the gesture is discoverable the first time. The bar, then Min, Max and Reset — nothing else.
The dropdown sheet
The dropdown sheetSix options or fewer step in the row. Longer — or any list the engine builds at runtime, like MIDI devices — opens this with a filter.
Preview, full screen
Preview, full screenEverything except the two bars goes away. The bottom bar keeps the breadcrumb, so you still know where you land when you shrink it back. The image is a real SpaceMusic render from the Library.

Why this shape holds

Everything above reduces to four rules that compose rather than compete: two bars that never move, at most two strips, one full-bleed row per control, and the fill is the value wherever there is a value to fill. A page is then fully described by which zone it has, whether it has instances, and what its dividers are called. Nothing about a new page needs a new decision.

That matters because the pages are not authored here — they are generated from the DNA, and they change. A surface built out of four rules absorbs a new section or a renamed group without a redesign.

Two things this design does not yet solve, stated plainly. Render Mode carries 43 flat controls with no level to split on; that is several screens of scrolling and no navigation scheme fixes it — it probably wants splitting in the DNA. And the render parameter names in these mockups are invented, because the real ones arrive with whichever render mode is loaded at runtime.

Settled

  • Two 56 px bars, top and bottom
  • At most two navigation strips
  • One full-bleed 56 px row per control
  • Centered and unipolar sliders drawn apart
  • Only sliders and toggles carry fill
  • Hold for the sheet, tap a long list for its own

Next

  • Wire the grammar into /mobile
  • Safe-area inset on the top bar
  • Real render-mode parameter names
  • Tune the long-press delay on a real phone

Later

  • Split Render Mode in the DNA
  • Swipe to step a dropdown
  • Drag to resize the preview

Glossary

DNA
The authoring platform at dna.spacemusic.tv that owns the parameter tree. Pages, sections, groups and controls are exported from it — not hand-written in the UI.
Pro UI
The full desktop control surface. The mobile surface is a second view of the same channels, not a cut-down copy of the Pro UI.
zone
The first level under a page. Becomes the top strip. Input’s zones are IO, 1D, 2D, 3D.
instance
A dynamic, numbered item inside a zone — plugin 2, stage 1, layer 3. Becomes the second strip, as number chips.
divider
A collapsible section header in the scrolling list. Every level below the instance is one of these.
strip
A full-width row of tabs or chips directly under the preview. A page has at most two.
channel
The engine-side value a control is bound to. The UI never holds state of its own; it reads and writes channels.
centered
A slider whose range is built around zero, so its fill grows out of the middle. The opposite is a range that starts at its minimum and fills from the left.
sheet
An overlay that rises from the bottom edge over a dimmed page. Used for slider precision, long option lists and the menu.
preview
The live render at the top of the page. Cycles closed, partial and full screen from the eye icon in the bottom bar.
render mode
The engine plug-in that draws a mapping layer. It supplies its own parameter names at runtime, which is why the ones drawn here are placeholders.
SpaceMusic · Mobile control surface Designed for A3 landscape print ← back to the document

Figure 1 · Screen anatomy and the four control kinds

THE SCREENPREVIEWZONEINSTANCEDIVIDERTop bar · 56 pxlogo · SPACE MUSIC · free slotPreviewclosed / partial / full — the eye cycles itStrips — at most twowhich zone, and which instanceListone full-bleed row per controlBottom bar · 56 pxpreview · PAGE / sub-path · menuFOUR KINDS, DRAWN 1:1 — 390 × 56Gain0.640X Translate2.400Shadowmap SizeMediumRenderONExport AllOnly the two kinds with a value to fill ever carry ink:a slider’s position in range, and a toggle that is on.A dropdown has no quantity to show, so it stays plainand the minus / plus at the edge do the work.