Slider
A linear slider component for continuous value adjustment with support for both horizontal and vertical orientations.
The Slider component provides a linear 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, trackless, trackfull, stripless
- Flexible orientation: horizontal and vertical layouts
- Extensive cursor customization: image-based cursors, custom styling, aspect ratio control
- Full theming support: color, roundness, thickness customization
Props
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
value | number | — | Required | Current value of the control |
onChange | (event: AudioControlEvent<number>) => void | — | Optional | Handler for value changes |
min | number | — | Optional | Minimum value (ad-hoc mode) |
max | number | — | Optional | Maximum value (ad-hoc mode) |
step | number | 1 | Optional | Step size for value adjustments |
bipolar | boolean | false | Optional | Whether the component should operate in bipolar mode (centered at zero) |
label | string | — | Optional | Label displayed below the component |
variant | "abstract" | "trackless" | "trackfull" | "stripless" | abstract | Optional | Visual variant of the slider |
orientation | "horizontal" | "vertical" | vertical | Optional | Orientation of the slider |
thickness | number | 0.5 | Optional | Thickness of the slider (normalized 0.0-1.0, maps to 1-50) |
valueAsLabel | "labelOnly" | "valueOnly" | "interactive" | labelOnly | Optional | Controls how the label and value are displayed |
cursorSize | "None" | "Strip" | "Track" | "Tick" | "Label" | — | Optional | Cursor size option - determines which component's width is used for the cursor |
cursorAspectRatio | number | — | Optional | Aspect ratio of the cursor |
cursorRoundness | number | string | — | Optional | Overrides the roundness factor of the cursor. Defaults to `roundness` |
cursorImageHref | string | — | Optional | Optional image URL to display as cursor |
cursorClassName | string | — | Optional | Optional CSS class name for the cursor |
cursorStyle | React.CSSProperties | — | Optional | Optional inline styles for the cursor |
color | string | — | Optional | Component primary color - any valid CSS color value |
roundness | number | — | Optional | Roundness for component corners (normalized 0.0-1.0) |
adaptiveSize | boolean | false | Optional | Whether the component stretches to fill its container |
size | "xsmall" | "small" | "normal" | "large" | "xlarge" | normal | Optional | Size of the component |
parameter | ContinuousParameter | — | Optional | Audio Parameter definition (Model). If provided, overrides min/max/step/label/bipolar from ad-hoc props |
valueFormatter | (value: number, parameterDef: AudioParameter) => string | undefined | — | Optional | Custom renderer for the value display |
interactionMode | "drag" | "wheel" | "both" | both | Optional | Interaction mode |
interactionSensitivity | number | — | Optional | Sensitivity of the control (normalized value change per pixel/unit) |
interactionDirection | InteractionDirection | — | Optional | Direction of the interaction |
Basic Usage
The Slider component requires a value and onChange handler. By default, sliders are vertical:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function BasicSlider() {
const [value, setValue] = useState(50);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
min={0}
max={100}
size="large"
label="Volume"
/>
</div>
);
}
Orientation
Sliders can be oriented horizontally or vertically:
Vertical Slider
The default orientation, suitable for fader-style controls:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function VerticalSlider() {
const [value, setValue] = useState(0.7);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
orientation="vertical"
label="Volume"
min={0}
max={1}
size="large"
/>
</div>
);
}
Horizontal Slider
Useful for pan controls and other horizontal adjustments:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function HorizontalSlider() {
const [value, setValue] = useState(0);
return (
<div className="w-full">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
orientation="horizontal"
label="Pan"
min={-100}
max={100}
bipolar={true}
size="large"
/>
</div>
);
}
Variants
The Slider component supports four visual variants:
Abstract
The default variant with a clean, minimal design:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function AbstractVariant() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
variant="abstract"
label="Volume"
size="large"
/>
</div>
);
}
Trackless
A variant without a visible track:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function TracklessVariant() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
variant="trackless"
label="Gain"
size="large"
/>
</div>
);
}
Trackfull
A variant with a full track visible:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function TrackfullVariant() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
variant="trackfull"
label="Cutoff"
size="large"
/>
</div>
);
}
Stripless
A variant without a value strip:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function StriplessVariant() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
variant="stripless"
label="Resonance"
size="large"
/>
</div>
);
}
Cursor Customization
The Slider component provides extensive options for customizing the cursor appearance:
Cursor Size
The cursorSize prop determines which component's width is used for the cursor:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function CursorSizeExample() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
cursorSize="Strip"
size="large"
label="Strip Cursor"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
cursorSize="Track"
size="large"
label="Track Cursor"
/>
</div>
);
}
Cursor Aspect Ratio
Control the aspect ratio of the cursor:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function CursorAspectRatio() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
cursorAspectRatio={1.0}
size="large"
label="Square Cursor"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
cursorAspectRatio={2.0}
size="large"
label="Tall Cursor"
/>
</div>
);
}
Cursor Roundness
Override the roundness of the cursor independently from the slider:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function CursorRoundness() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
cursorRoundness={0.0}
size="large"
label="Square Cursor"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
cursorRoundness={1.0}
size="large"
label="Fully Rounded"
/>
</div>
);
}
Custom Cursor Image
Use a custom image for the cursor:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function CursorImage() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
cursorImageHref="/images/documentation/svg-primitives-radial-light.png"
size="large"
label="Custom Cursor"
/>
</div>
);
}
Cursor Styling
Apply custom CSS classes or inline styles to the cursor:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function CursorStyling() {
const [value, setValue] = useState(0.5);
return (
<div className="h-48">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
cursorClassName="custom-cursor"
cursorStyle={{ border: "2px solid #3b82f6" }}
size="large"
label="Styled Cursor"
/>
</div>
);
}
Theming
Vector components share common theming features; see Theming Features in the Vector introduction for an overview. The Slider component supports theming through the color and roundness props:
Color Customization
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderColor() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
color="#3b82f6"
size="large"
label="Blue Slider"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
color="#ef4444"
size="large"
label="Red Slider"
/>
</div>
);
}
Roundness
Control the roundness of the slider track and cursor:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderRoundness() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
const [v3, setV3] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
roundness={0.0}
size="large"
label="Square"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
roundness={0.5}
size="large"
label="Rounded"
/>
<Slider
value={v3}
onChange={(e) => setV3(e.value)}
roundness={1.0}
size="large"
label="Fully Rounded"
/>
</div>
);
}
Thickness
Adjust the thickness of the slider track:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderThickness() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
const [v3, setV3] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
thickness={0.2}
size="large"
label="Thin"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
thickness={0.5}
size="large"
label="Medium"
/>
<Slider
value={v3}
onChange={(e) => setV3(e.value)}
thickness={0.8}
size="large"
label="Thick"
/>
</div>
);
}
Bipolar Mode
In bipolar mode, the slider visualizes values relative to a center point. This is ideal for pan controls:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function BipolarSlider() {
const [value, setValue] = useState(0);
return (
<div className="w-full">
<Slider
value={value}
onChange={(e) => setValue(e.value)}
min={-100}
max={100}
bipolar={true}
orientation="horizontal"
size="large"
label="Pan"
/>
</div>
);
}
Value Display
The valueAsLabel prop controls how the label and value are displayed:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderValueDisplay() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
const [v3, setV3] = useState(0.5);
return (
<div className="flex gap-8 h-48">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
valueAsLabel="labelOnly"
size="large"
label="Volume"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
valueAsLabel="valueOnly"
size="large"
label="Volume"
/>
<Slider
value={v3}
onChange={(e) => setV3(e.value)}
valueAsLabel="interactive"
size="large"
label="Volume"
/>
</div>
);
}
Value Formatting
Customize how values are displayed using the valueFormatter prop:
import { useState } from "react";
import { Slider, frequencyFormatter } from "@cutoff/audio-ui-react";
export default function SliderFormatterExample() {
const [frequency, setFrequency] = useState(1000);
const [gain, setGain] = useState(0);
return (
<div className="flex gap-8 items-center flex-wrap h-48">
<Slider
value={frequency}
onChange={(e) => setFrequency(e.value)}
min={20}
max={20000}
label="Frequency"
valueFormatter={(value) => frequencyFormatter(value)}
size="large"
/>
<Slider
value={gain}
onChange={(e) => setGain(e.value)}
min={-60}
max={12}
label="Gain"
valueFormatter={(value) => `${Math.round(value)} dB`}
size="large"
/>
</div>
);
}
Parameter Model
Use a parameter model for integration with audio parameter systems. The following example uses ad-hoc props; with the full library you would use createContinuousParameter and the parameter prop:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderParameterModelExample() {
const [value, setValue] = useState(50);
return (
<div className="h-48">
<Slider
min={0}
max={100}
label="Volume"
value={value}
onChange={(e) => setValue(e.value)}
size="large"
/>
</div>
);
}
Adaptive Sizing
The Slider 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:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderSizing() {
const [v1, setV1] = useState(0.5);
const [v2, setV2] = useState(0.5);
const [v3, setV3] = useState(0.5);
const [v4, setV4] = useState(0.5);
return (
<div className="flex gap-4 items-center flex-wrap h-64">
<Slider
value={v1}
onChange={(e) => setV1(e.value)}
size="small"
label="Small"
/>
<Slider
value={v2}
onChange={(e) => setV2(e.value)}
size="normal"
label="Normal"
/>
<Slider
value={v3}
onChange={(e) => setV3(e.value)}
size="large"
label="Large"
/>
<Slider
value={v4}
onChange={(e) => setV4(e.value)}
size="xlarge"
label="XLarge"
/>
</div>
);
}
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.
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderAdaptiveSize() {
const [wideValue, setWideValue] = useState(0.5);
const [tallValue, setTallValue] = useState(0.5);
const [distortedValue, setDistortedValue] = useState(0.5);
return (
<div className="flex gap-6 items-center flex-wrap h-48">
<div className="w-48 h-16 border rounded-lg p-2">
<Slider
value={wideValue}
onChange={(e) => setWideValue(e.value)}
adaptiveSize={true}
orientation="horizontal"
label="Wide"
/>
</div>
<div className="w-24 h-48 border rounded-lg p-2">
<Slider
value={tallValue}
onChange={(e) => setTallValue(e.value)}
adaptiveSize={true}
label="Tall"
/>
</div>
<div className="w-32 h-20 border rounded-lg p-2">
<Slider
value={distortedValue}
onChange={(e) => setDistortedValue(e.value)}
adaptiveSize={true}
displayMode="fill"
label="Distorted"
/>
</div>
</div>
);
}
Interaction Modes
Control how users interact with the slider:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderInteractionExample() {
const [dragVal, setDragVal] = useState(0.5);
const [wheelVal, setWheelVal] = useState(0.5);
const [bothVal, setBothVal] = useState(0.5);
return (
<div className="flex gap-4 items-center flex-wrap h-48">
<Slider
value={dragVal}
onChange={(e) => setDragVal(e.value)}
interactionMode="drag"
label="Drag Only"
size="large"
/>
<Slider
value={wheelVal}
onChange={(e) => setWheelVal(e.value)}
interactionMode="wheel"
label="Wheel Only"
size="large"
/>
<Slider
value={bothVal}
onChange={(e) => setBothVal(e.value)}
interactionMode="both"
label="Drag & Wheel"
size="large"
/>
</div>
);
}Adjust the sensitivity of interactions:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function SliderSensitivityExample() {
const [lowVal, setLowVal] = useState(0.5);
const [highVal, setHighVal] = useState(0.5);
return (
<div className="flex gap-4 items-center flex-wrap h-48">
<Slider
value={lowVal}
onChange={(e) => setLowVal(e.value)}
interactionSensitivity={0.01}
label="Low Sensitivity"
size="large"
/>
<Slider
value={highVal}
onChange={(e) => setHighVal(e.value)}
interactionSensitivity={0.1}
label="High Sensitivity"
size="large"
/>
</div>
);
}Common Patterns
Volume Fader
A typical vertical volume fader:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function VolumeFader() {
const [volume, setVolume] = useState(70);
return (
<div className="h-48">
<Slider
value={volume}
onChange={(e) => setVolume(e.value)}
orientation="vertical"
variant="trackfull"
min={0}
max={100}
label="Volume"
size="large"
valueFormatter={(value) => `${Math.round(value)}%`}
/>
</div>
);
}Pan Control
A horizontal pan control with bipolar mode:
import { useState } from "react";
import { Slider } from "@cutoff/audio-ui-react";
export default function PanControl() {
const [pan, setPan] = useState(0);
return (
<Slider
value={pan}
onChange={(e) => setPan(e.value)}
orientation="horizontal"
min={-100}
max={100}
bipolar={true}
label="Pan"
size="large"
valueFormatter={(value) => {
if (value === 0) return "C";
return value > 0 ? `R${Math.abs(value)}` : `L${Math.abs(value)}`;
}}
/>
);
}Next Steps
- Explore the Knob component for rotary controls
- Learn about Button and CycleButton for discrete interactions
- Check out FilmStripContinuousControl for bitmap-based sliders
- Visit the playground for interactive examples