Knob

A rotary control component for continuous value adjustment with multiple visual variants and full theming support.

The Knob component provides a circular control for continuous value adjustment. It shares the same layout, parameter model, interaction, and accessibility as other vector components; see the Vector introduction.

  • Multiple visual variants: abstract, simplest, plainCap, iconCap
  • Full theming support: color, roundness, thickness customization

Props

NameTypeDefaultRequiredDescription
valuenumberYesCurrent value of the control
onChange(event: AudioControlEvent<number>) => voidNoHandler for value changes
minnumberNoMinimum value (ad-hoc mode)
maxnumberNoMaximum value (ad-hoc mode)
stepnumber1NoStep size for value adjustments
bipolarbooleanfalseNoWhether the component should operate in bipolar mode (centered at zero)
labelstringNoLabel displayed below the component
variant"abstract" | "simplest" | "plainCap" | "iconCap"abstractNoVisual variant of the knob
thicknessnumberNoThickness of the knob's stroke (normalized 0.0-1.0, maps to 1-20)
opennessnumber90NoOpenness of the ring in degrees (0-360º; 0º closed, 90º 3/4 open, 180º half-circle)
rotationnumber0NoOptional rotation angle offset in degrees
rotaryOverlaybooleanfalseNoWhether to use RotaryImage (true) or RadialImage (false) for iconCap overlay. Only applies when variant is "iconCap" and children is provided.
childrenReact.ReactNodeNoSVG content to display as overlay in iconCap variant. Typically an icon component that will be rendered at the center of the knob.
valueAsLabel"labelOnly" | "valueOnly" | "interactive"labelOnlyNoControls how the label and value are displayed
colorstringNoComponent primary color - any valid CSS color value
roundnessnumberNoRoundness for component corners (normalized 0.0-1.0)
adaptiveSizebooleanfalseNoWhether the component stretches to fill its container
size"xsmall" | "small" | "normal" | "large" | "xlarge"normalNoSize of the component
parameterContinuousParameterNoAudio Parameter definition (Model). If provided, overrides min/max/step/label/bipolar from ad-hoc props
valueFormatter(value: number, parameterDef: AudioParameter) => string | undefinedNoCustom renderer for the value display
interactionMode"drag" | "wheel" | "both"bothNoInteraction mode
interactionSensitivitynumberNoSensitivity of the control (normalized value change per pixel/unit)
interactionDirectionInteractionDirectionNoDirection of the interaction

Basic Usage

The Knob component requires a value and onChange handler. In ad-hoc mode, you provide min and max to define the value range:

BasicKnob.tsx

Variants

The Knob component supports four visual variants, each with a distinct appearance:

Simplest

A simplified version with minimal visual elements:

SimplestVariant.tsx

Abstract

The default variant with a clean, minimal design. Displays the current value as text in the center:

AbstractVariant.tsx

PlainCap

A variant with a plain cap design:

PlainCapVariant.tsx

IconCap

The iconCap variant allows you to display custom SVG content (typically icons) at the center of the knob. The icon can rotate with the knob value or remain static:

IconCapVariant.tsx

The rotaryOverlay prop controls whether the icon rotates with the knob value (true) or remains static (false). The icon inherits color via currentColor, so it adapts to light/dark mode automatically. The example above matches the LFO knob from the AudioUI playground (iconCap with SquareWaveIcon); the playground provides sine, triangle, square, and saw wave icons you can reuse.

Theming

Vector components share common theming features; see Theming Features in the Vector introduction for an overview. The Knob component supports theming through the color and roundness props, or via the global theme system:

Color Customization

You can customize the knob's primary color using the color prop:

CustomColor.tsx

Roundness

Control the roundness of the knob's corners:

RoundnessExample.tsx

Note:

Value strip roundness: For the knob's value strips (the arc that shows the current value), roundness behaves in an on/off way: roundness={0.0} uses a square linecap, and any other value uses a round linecap. The correct behaviour has been achieved internally but does not pass our performance requirements, so the current binary behaviour is used.

Thickness

Adjust the stroke thickness of the knob ring:

ThicknessExample.tsx

Ring Configuration

Openness

The openness prop controls how much of the ring is visible. It accepts values in degrees (0-360º):

  • : Closed ring (full circle)
  • 90º: 3/4 open (default)
  • 180º: Half-circle
  • 270º: 1/4 open
OpennessExample.tsx

Rotation

The rotation prop allows you to offset the starting angle of the ring:

RotationExample.tsx

Value Display

The valueAsLabel prop controls how the label and value are displayed:

  • "labelOnly": Always shows the label (default)
  • "valueOnly": Always shows the value
  • "interactive": Shows label normally, but temporarily swaps to value during interaction
ValueDisplayExample.tsx

Bipolar Mode

In bipolar mode, the knob visualizes values relative to a center point rather than from minimum to maximum. This is useful for controls like pan or balance:

BipolarExample.tsx

Value Formatting

You can customize how values are displayed using the valueFormatter prop. AudioUI provides built-in formatters for common audio parameters:

FormatterExample.tsx

Parameter Model

Instead of using ad-hoc props (min, max, label), you can provide a full parameter model via the parameter prop. This is useful when integrating with audio parameter systems:

ParameterModelExample.tsx
import { Knob, createContinuousParameter } from "@cutoff/audio-ui-react";
 
const cutoffParam = createContinuousParameter({
  paramId: "cutoff",
  label: "Cutoff",
  min: 20,
  max: 20000,
  unit: "Hz",
  scale: "log",
  defaultValue: 1000,
});
 
export default function ParameterModelExample() {
  const [value, setValue] = useState(1000);
 
  return (
    <Knob
      parameter={cutoffParam}
      value={value}
      onChange={(e) => setValue(e.value)}
    />
  );
}

Adaptive Sizing

The Knob component supports both fixed sizes and adaptive sizing. By default, the size of the component is driven by the Size System and their size attribute:

SizingExample.tsx

Adaptive sizing allows the component to adapt to the size of its parent container, adjusting its dimensions intelligently without causing distortion (scaleToFit display mode). The fill display mode makes the component fill the entire container, potentially distorting it.

AdaptiveSize.tsx

Interaction Modes

Control how users interact with the knob:

InteractionExample.tsx

You can also adjust the sensitivity of interactions:

SensitivityExample.tsx

Common Use Cases

Audio Filter Control

FilterControl.tsx

Volume Control

VolumeControl.tsx

Pan Control

PanControl.tsx

Next Steps