Skip to content

Mixer

beta

Balancing several signals against each other. Two arrangements: a console that shows every channel at once, and a studio that shows one in depth.

Also called Console, Channel Strip, Fader Bank, Level Mixer — in this system all of them are Mixer.

Live preview

Everything below is the real component. Change the controls, tab through it, and turn on Inspector Mode to read any value off the screen.

Console

Mixer

Media

Gain-1.4 dB

Storyboard

Gain-8.5 dB

Narration

Gain0.0 dB

Music

Gain-4.2 dB

SFX

Gain-2.1 dB

Master

Stereo out

0.0 dB

Limiter

One channel strip

The unit that repeats. Number and colour for identity, a waveform to recognise the clip, the gain readout as text, pan, mute and solo, then the fader and its meter side by side.

Media

Gain-1.4 dB

Solo dims what it silenced

Channel 4 is soloed, so channels 1, 2 and 3 are inaudible without any of their own controls having moved. Dimming them is what stops the user concluding the mixer is broken.

Media

Gain-1.4 dB

Storyboard

Gain-8.5 dB

Narration

Gain0.0 dB

Music

Gain-4.2 dB

Master

Stereo out

0.0 dB

Limiter

The studio arrangement

A track list on the left, and everything to the right is the selected track. This is what you build once a track needs more than a fader — volume, pan, presence, an enhance pass and a noise gate will not fit five abreast. The trade is real: you can work in depth, and you can no longer see the balance.

Mix Studio

Tracks

  • Voice
  • Music
  • Effects
  • Ambience
  • Clips

Voice controls

The everyday four: how loud, where in the stereo field, how present, and whether it is heard at all.

Volume
0.0 dB
Pan
Centre
Presence
+2.0 dB

Auto mix

VoiceMusic

Auto mix ducks music beneath narration wherever there is speech.

Master

Output
0.0 dB

-14.6 LUFS

Target -14 · on target

True peak -1.0 dBTP

Everyday controls: volume, pan, presence, mute, solo, voice enhancement and noise cleanup.

The four depths of one track

The section tabs are not four tools — they are the same track at increasing specificity. Basic is what everyone touches; EQ is by pitch; Dynamics is consistency over level; Automation is change over time. A user works down that list as their problem gets more specific, which is why the order is fixed and Basic is first.

Voice EQ

Turns parts of the sound up or down by pitch. Each control below is one point on the graph.

+12+60-6-1212345
Low cut
80 Hz
24 dB/oct
Warmth
180 Hz
-2.6 dB
Clarity
3.0 kHz
+2.4 dB
Presence
6.0 kHz
+1.8 dB
Air
12 kHz
+1.6 dB

Frequency response: low cut below 80 hertz, warmth down 2.6 decibels at 180 Hz, clarity up 2.4 decibels at 3.0 kHz, presence up 1.8 decibels at 6.0 kHz, air up 1.6 decibels at 12 kHz.

Remove rumble and improve speech clarity.

Voice dynamics

Evens out volume that jumps around — quiet words lifted, loud ones held back, hiss removed between phrases.

Input (before)Output (after)Gate threshold

Voice leveler

Keeps your voice at a consistent level throughout.

Compressor

Controls loud peaks for a smoother, steadier sound.

Gain reduction-3.4 dB

De-esser

Tames sharp S sounds without dulling the whole track.

Reducing harsh S sounds by 40%

Noise gate

Silences background noise when nobody is speaking.

-45 dB
Prevents distortion and protects your audio.
Safe output

Smooth uneven narration and control harsh peaks.

The shell never changes height

All four panels render into the same box at the same height, set once by the tallest of them. That is a hard requirement, not a nicety: these tabs are switched between constantly while listening, and a shell that grows or shrinks moves the tab strip, the track list and the master meters under the pointer every time — so the control you were about to click is somewhere else, and the meters you were watching jump.

Every panel fills a 560px box. The dashed edge is the box.

Music automation

Changes level over time instead of one setting for the whole track — fades, ducking under narration, and lifting individual quiet phrases.

100%
+120 dB-12-24
Point 1 of 4
0:00
0.0 dB

Music auto-duck

Fade in

Bring the track up from silence at the start.

Fade out

Take the track down to silence at the end.

Level quiet sections

Automatically lift phrases that were recorded too quietly.

Create music ducking

Duck the music beneath narration automatically, wherever there is speech.

Level quiet phrases and duck music beneath narration.

An automation lane that works without a mouse

Dragging a dot on a canvas is the fast path, and it is unreachable by keyboard — a canvas cannot take focus and has no value semantics. So selecting a point opens an editor with a real time field, a real level field and a real curve select, and the lane is a picture of that state rather than a separate interface. This is the part most tools skip.

Voice automation

Changes level over time instead of one setting for the whole track — fades, ducking under narration, and lifting individual quiet phrases.

100%
+120 dB-12-24
Point 1 of 7
0:00
-12.0 dB

Music auto-duck

Fade in

Bring the track up from silence at the start.

Fade out

Take the track down to silence at the end.

Level quiet sections

Automatically lift phrases that were recorded too quietly.

Create music ducking

Duck the music beneath narration automatically, wherever there is speech.

Level quiet phrases and duck music beneath narration.

Choosing between them

Ask what the user is doing. Setting levels against each other is a console job — eight caps read as one shape. Fixing one track is a studio job, and the console cannot give it the room. A tool that does both usually ships the console as the main view and opens the studio on double-click.

Console — comparison

Every channel visible. One shared scale. The balance is the picture.

Media

Gain-1.4 dB

Storyboard

Gain-8.5 dB

Narration

Gain0.0 dB

Music

Gain-4.2 dB

Master

Stereo out

0.0 dB

Limiter

Studio — depth

One track, five controls, room to label them. The balance is now invisible.

Voice · controls

Volume
0.0 dB
Pan
Centre
Presence
+2.0 dB

Compact, for a sidebar

Waveforms and the printed dB scale are the first things to go. The controls keep their size — shrinking a fader to fit is how you get a control nobody can land on.

Media

Gain-1.4 dB

Storyboard

Gain-8.5 dB

Narration

Gain0.0 dB

Music

Gain-4.2 dB

Master

Stereo out

0.0 dB

Limiter

Why the taper

The same eight values on a tapered scale and a linear one. On the linear track unity gain sits near the top and the useful range is squeezed into the last centimetre.

Tapered — usable
Linear — unusable near unity

Interaction states

Every state a user can put this component into, rendered side by side. If a state is missing here, it is missing in production too.

Unity (0 dB)
Attenuated
Boosted
Off (-∞)
Disabled
Pan centre
Pan hard left
Muted
Soloed
Meter, nominal
Meter, clipping

Anatomy

Every part, every measurement, and the reason it is that number.

Media

Gain-1.4 dB

One strip. Every element sits at the same vertical position on every channel, which is what lets eight of them be read as one picture.

  1. IdentityNumber + colour + name

    Three redundant signals for the same fact. Colour alone fails for a colour-blind user and fails again the moment there are more channels than distinguishable hues.

  2. Waveform32px, decorative

    Recognising a clip by shape is faster than reading its name. It carries nothing the name does not, so it is aria-hidden.

  3. Gain readoutMono, tabular

    The number as text. An engineer writes this down; a fader position cannot be written down. Tabular figures so it does not jitter while dragging.

  4. Pan44px rotary

    A range input presented as a rotation, because a pan value is a position between two speakers. Double-click recentres.

  5. Mute / Solo28px, aria-pressed

    The two controls that change what you hear without moving anything, so they are the two with a lit indicator rather than only a colour change.

  6. Fader26 × 40px cap

    The cap is deliberately large and gripped. It is the control the user reaches for most and the one they aim at while listening rather than looking.

  7. ScaleMeaningful stops

    +12 down to -60, with 0 dB given a physical detent line. Printing every step would make it measuring equipment.

  8. Meter8px, aria-hidden

    Output. Segmented so a level is read as a quantity rather than a colour, with the top of the scale red by position as well as by hue.

  9. Identity bar4px

    A solid block at a fixed position is the fastest index across a row of strips.

Design tokens used

Values are read live from the running stylesheet, so this table can never drift from the code. Click any value to copy it.

Color

TokenValueUsed for
Surfaces
--ds-surface-inset—The console body behind the strips
--ds-surface—Channel strip
--ds-surface-raised—Master strip, and the top of the fader cap gradient
--ds-sunken—Fader rail and meter well — the recessed parts
Interaction
--ds-layer-hover—Mute and solo hover state layer
--ds-focus-ring—Focus halo on the fader cap and pan knob
--ds-border-strong—Cap border, grip lines, unity detent
Meter
--ds-success—Meter segments up to about -12 dB
--ds-warning—Meter approaching full scale, and solo
--ds-danger—Clipping segments, and mute
Channel
Channel hue rampPer-channel identity. Not semantic tokens — these are identity hues, the same category as chart series.

Spacing

TokenValueUsed for
strip widthNarrow enough for eight, wide enough for a 44px pan knob
hit areaInvisible target around the fader rail and the knob

Radius

TokenValueUsed for
--radius-md—Channel strip

Shadow

TokenValueUsed for
--shadow-e2—Fader cap, so it reads as sitting on the rail

Typography

TokenValueUsed for
tabular-nums—Every dB readout and scale label

Motion

TokenValueUsed for
75ms—Meter segment fade. Never the fader position.

Recommended sizes

Pick a size from this table. Do not invent a new one — a fourth height is how a design system starts dying.

SizeHeightMin widthMax widthTouch targetWhen to use
Strip—112px160px—Below 112px the pan knob drops under the 44px target. Above 160px a full desk stops fitting a laptop.
Fader travel150px min, 210px default———Under 150px the taper stops buying anything and the useful range collapses.
Fader cap40px26px—44px hit areaLarge on purpose — it is aimed at while listening, not while looking.
Pan knob44px——44pxThe knob is the target; there is no separate hit area to grow.
Mute / Solo28px———Two per strip, side by side. Below 28px the pair becomes a mis-click risk on the one control that silences audio.
Meter—8px——Segments must stay square-ish. A meter narrower than 6px reads as a line, not a measurement.
Master strip—132px——Wider than a channel, because it carries two meters and must not be mistaken for channel nine.

Do

<input type="range" style="writing-mode: vertical-rl; direction: rtl" />
Build every control on a native inputThe fader and the pan knob are input[type=range] with a painted face. That is the whole keyboard model, the value semantics and forced-colors support for free — and it is the difference between a mixer a keyboard user can operate and a wall of undraggable divs.
Gain-4.2 dB
Print the value as text next to the controlA fader position cannot be read out, written down or copied. The readout is what makes the mixer usable by someone who is not looking at it, and it is where a screen reader user gets the number.
Give 0 dB a detentUnity gain is the one position an engineer looks for without reading the scale. A line on the rail — and a double-click that snaps to it — turns "find zero" from a task into a gesture.

Voice · controls

Name the selection in the inspectorIn the studio arrangement, everything on the right belongs to whatever is highlighted on the left. Without a heading saying which track that is, the panel is a set of anonymous knobs and the user is relying on memory of what they clicked.

Rumble filter

Everything below this is removed: traffic, air conditioning, desk bumps.

Explain the panels in the user’s language"Dynamics" and "EQ" mean nothing to someone editing a video, and they are exactly the two panels that person needs. Every control here carries a plain sentence — "everything below this is removed: traffic, air conditioning, desk bumps" beats "high-pass filter, 90 Hz" for the audience that actually opens it.
curve = f(bands) — one direction only
Derive the curve from the controlsThe EQ curve, the compression transfer curve and the automation lane are all pictures of values that live elsewhere. Let a user edit the picture independently and you have two sources of truth for one filter, which drift the first time either is set another way.

-14.0 LUFS

Target -14 · on target

Say what the loudness number means"-14 LUFS" is meaningless to most people editing a video, and it is the number the whole studio arrangement is steering towards. Print the target beside it and say which side of it you are on.
Dimmed
Solo
Make solo visibly silence the othersSolo changes what the user hears without changing any control they can see. Dim the strips it silenced, or field the "channel 3 is broken" report forever.

Don't

ch1: -60…0 · ch2: -100…+20 → the shape means nothing
Do not give channels different rangesThe comparison is the component. The moment a cap at the same height means -6 dB on one channel and -20 on another, the row of faders is decoration and the user has to read eight numbers instead.
transition: bottom 200ms → the cap trails the finger
Do not animate the fader positionThe cap must sit under the pointer. Any transition on its position makes the whole console feel like it is lagging behind the hand — and on a mixer the user is dragging almost continuously.
no text = nobody knows it clipped
Do not put information only in the meterIt is aria-hidden, it never takes focus, and it is invisible to anyone not watching that pixel at that moment. Clipping in particular has to be a message that persists, not a red LED that already went out.
Console | StudioBasic | EQ
Do not put two tab strips with the same weight on one screenThe studio has section tabs (Basic, EQ, Dynamics) that change what you edit on the selected track. If the arrangement switcher looks the same and sits nearby, neither reads as more significant than the other and every click is a guess. Give them different shapes and different places.
tallshort
Do not let the panel resize when the tab changesThese tabs are switched between constantly while listening. If each panel sizes to its own content, the tab strip, the track list and the master meters all move — so the control you were reaching for is somewhere else, and the meters you were watching jump. Fix the height once, to the tallest panel, and let the others fill it.
drag the dot, or… nothing. No keyboard route in.
Do not make the curve the only way to editA draggable EQ curve or automation lane is a canvas. It cannot take focus, it has no value semantics and it is unreachable by keyboard — so every value it holds needs a real control somewhere too. The picture is the fast path, never the only path.
threshold + ratio, no meter → tuning by superstition
Do not leave a compressor with no visible effectThreshold and ratio are two sliders whose combined result is invisible without a gain-reduction readout. The user cannot tell whether the compressor is doing nothing or crushing the track, so they turn knobs until it sounds wrong.
click voice → read → click music → read → guess
Do not use the studio arrangement to set a balanceBalancing is comparing, and the inspector shows one track at a time. The user ends up clicking between tracks trying to hold two numbers in their head — which is precisely the job the console does in one glance.
Do not shrink the controls to fit more channelsSixteen strips at 60px each is a mixer nobody can operate. Scroll horizontally and keep the targets — a control you cannot reliably hit is not a smaller control, it is a broken one.

Accessibility

Not a checklist to run at the end. These are the requirements the component was built from.

1.4.1Use of ColorA1.4.11Non-text ContrastAA2.1.1KeyboardA2.5.7Dragging MovementsAA2.5.8Target Size (Minimum)AA4.1.2Name, Role, ValueA

Contrast

  • The travelled portion of the rail must reach 3:1 against the untravelled portion — that boundary is the value.
  • The fader cap must reach 3:1 against both the rail and the strip behind it, which is why it is a bordered object with its own elevation rather than a coloured block.
  • Channel colour is identity, not status, so it is never the only carrier: the number and the name say the same thing.
  • Meter segment colours are a convention, not a message. Clipping must also be text.
  • Every dB readout is content and owes 4.5:1 — including the coloured one, which is why the channel hue is lightened for text use.

Keyboard

TabMoves through one strip at a time in visual order: pan, mute, solo, fader. Predictable order across strips matters more than any single shortcut.
↑ / ↓Moves the focused fader by one step. ← / → move a pan knob.
Page Up / Page DownLarger increment — conventionally 6 dB on a fader.
Home / EndJumps to the minimum or maximum of the focused control.
Double-clickResets a fader to unity and a pan knob to centre. Provide a keyboard equivalent — this must not be the only way.
↑ / ↓ in the track listMoves the selection in the studio arrangement, which changes everything in the inspector. Tab leaves the list rather than walking it.

Screen readers

  • Announce as "Narration fader, slider, -4.2 dB". The channel name is part of the label, not context the user is expected to remember.
  • Never announce meter levels. They change continuously and carry nothing actionable.
  • Announce mute and solo as pressed states, and announce the consequence when it is not obvious: "Solo on, 7 channels silenced".
  • Group each strip so navigating by group moves channel to channel rather than control to control.

Focus & touch

  • The ring sits on the fader cap and the knob face, because those are the parts that move. It must stay visible at both ends of the travel, which means the strip needs padding the halo can occupy — a cap at 0 dB with its focus ring clipped by the strip edge is a keyboard user losing their place.
  • The fader rail is 6px but its target is the full 44px strip width; the pan knob is 44px square. On touch the fader is the only control that should respond to a drag — a pan knob that rotates on drag competes with page scroll, so on touch it moves in steps on tap instead.
AttributeApplied toNotes
role="slider"Faders and pan knobsImplicit on input[type=range]. This is the reason to build on it rather than on a div.
aria-valuetextFaders and pan knobs"-4.2 dB", "L22", "Centre". Without it a pan knob announces "-22" and a fader announces a position on an internal 0–1000 scale that means nothing.
aria-orientation="vertical"FadersChanges which arrow keys are announced as increasing.
aria-labelEvery controlScoped by channel — "Narration fader", not "fader". Eight identically-named sliders is the most common failure in this component.
aria-pressedMute and soloThey are toggle buttons, not links or checkboxes. The pressed state is the whole meaning.
aria-hiddenMeters, waveforms, identity barsOutput and decoration. None of them may be the only source of a fact.
role="status"The clipping indicatorA polite live region, so clipping is announced once rather than sixty times a second.
role="listbox" / role="option"The studio track listSelection is the navigation model of that arrangement — everything in the inspector belongs to the selected option — so it needs real single-select semantics and roving tabindex, not a row of buttons.
aria-selectedTrack rowsThe selected track must be announced as selected, not merely styled as such. A highlight is invisible to a screen reader.

Code

Example usage

Two arrangements over the same state. Keep the channel list in one place and let each view render it — a console and a studio holding separate copies is how the two drift apart.

tsx
1// Console — every channel at once, for setting a balance2<ConsoleMixer3  channels={channels}4  master={master}5  onChannelChange={(id, patch) => update(id, patch)}6  onMasterChange={setMaster}7/>89// Studio — one selected track in depth, for working on it10<StudioMixer11  tracks={channels}12  selectedId={selectedId}13  onSelect={setSelectedId}14  onTrackChange={(patch) => update(selectedId, patch)}15/>1617// One strip, if you need it alone18<ChannelStrip19  channel={{ id: '1', name: 'Narration', db: 0, pan: 0, mute: false, solo: false }}20  index={0}21  level={peak}22  audible={!muted}23  onChange={(patch) => update('1', patch)}24/>

CSS

The vertical fader. `appearance: slider-vertical` is deprecated and never shipped in Firefox; writing-mode is the replacement, and `direction: rtl` is what puts the minimum at the bottom.

css
.fader input[type="range"] {
  writing-mode: vertical-rl;
  direction: rtl;          /* minimum at the BOTTOM */
  inline-size: 100%;       /* the 44px target */
  block-size: 100%;
  opacity: 0;              /* the face is painted behind it */
  cursor: pointer;
}

/* Never transition the cap's position — it must sit under the pointer. */
.fader__cap {
  transition: box-shadow var(--duration-fast);
}

Component API

StudioMixer

PropTypeDefaultDescription
tracks*Track[]—The track list. Same source of truth the console reads — two views holding separate copies is how they drift apart.
selectedId*string—Which track the inspector is showing. Controlled, so the host can select a track from elsewhere.
onSelect*(id: string) => void—Selection is this arrangement’s whole navigation model.
onTrackChange(patch: Partial<Track>) => void—Edits apply to the selected track. No id — the selection already says which.
targetnumber-14Loudness target in LUFS. Printed beside the measured value, because the number alone means nothing to most users.

ConsoleMixer

PropTypeDefaultDescription
channels*Channel[]—One entry per strip. Order is the display order.
master*number—Master bus gain in dB.
onChannelChange(id: string, patch: Partial<Channel>) => void—Called for every control on a strip. Patches rather than whole objects, so a fader drag does not have to know about mute.
onMasterChange(db: number) => void—Master fader.
compactbooleanfalseDrops the waveform and the printed dB scale. Never shrinks the controls.
levelsnumber[]—Live meter levels, 0–1. Omit and the meters stay dark — they are display only.

Channel

PropTypeDefaultDescription
id*string—Stable identity. Not the index — strips get reordered.
name*string—Used in every aria-label on the strip.
db*number—Gain, -60 to +12. -60 is treated as -∞.
pan*number—-100 (hard left) to +100 (hard right). 0 is centre.
mute*boolean—Silences this channel.
solo*boolean—Silences every channel that is not soloed. A mode — surface it.

Notes

Professional tips

  • Double-click to reset is the hardware convention and worth honouring — unity on a fader, centre on a pan knob. Give it a keyboard equivalent; it must never be the only route.
  • Solo should be exclusive by default and additive with a modifier. Most users want "just this one"; power users want "these three".
  • Keep the master strip visually distinct and at the end. A master that looks like channel nine will be dragged as one.
  • Peak-hold on the meter — a mark that lingers for a second at the highest recent level — is the single most useful addition, because clipping is over before the eye catches it.

Performance

  • Meter updates are the whole performance story. Drive them from one animation frame loop for the entire mixer, not one interval per channel.
  • Never route meter levels through the same state as the controls. Sixty updates a second through a store that also owns fader values will re-render every strip.
  • Write meter heights directly to the node — a transform or a width — rather than through React state, the way a progress bar does under a drag.
  • The waveform thumbnail should be generated once and cached per clip. Recomputing peaks on render is invisible with eight channels and fatal with thirty-two.

Common mistakes

  • Eight sliders labelled "slider". The channel name has to be in every aria-label or the whole console is unnavigable by keyboard.
  • A meter with no text equivalent, so clipping is invisible to anyone who was not looking at that pixel.
  • Solo with no visible consequence — the most reliable source of "the mixer is broken" reports.
  • A linear dB scale, which makes the useful range of the fader about a centimetre long.
  • Transitioning the fader position, which makes every drag feel broken.
  • Colour as the only channel identity, which fails for a colour-blind user and fails for everyone once there are more channels than distinguishable hues.

Real-world recommendations

  • Most real tools ship both arrangements: the console as the main view, the studio opened by double-clicking a strip. The console answers "is the balance right", the studio answers "what is wrong with this track", and neither question is rare enough to make the other view optional.
  • The studio arrangement is what appears in video editors, where the user is not an audio engineer and there are five tracks rather than forty. It steers towards a loudness target instead of asking for a balance, because "-14 LUFS for this platform" is a decision the tool can make and the user cannot.
  • Every hardware console ever built puts the fader at the bottom and the meter beside it. That is not nostalgia — it is because the hand rests low and the eye tracks the meter while the hand moves.
  • Broadcast desks give solo its own colour and its own light because an accidental solo on air is a serious failure. The visual weight is proportional to the cost of the mistake.
  • DAWs let a strip collapse to a fader and a name and nothing else. That is the honest compact mode: drop information, never target size.