Skip to content

Slider

A versatile range slider component with optional increment/decrement buttons, perfect for audio parameter control.

Demo

Interactive Example

Volume75%
Frequency440 Hz
PanC

Features

  • Continuous value control with min/max/step
  • Optional +/- increment buttons
  • Label and value display
  • Custom value formatting
  • Disabled state support
  • Full accessibility (ARIA labels, keyboard support)
  • Completely customizable styling

Import

tsx
import { Slider } from '@mode-7/mod';
import '@mode-7/mod/dist/index.css'; // Optional default styles

Props

PropTypeDefaultDescription
valuenumberRequiredCurrent slider value
onChange(value: number) => voidRequiredValue change callback
minnumber0Minimum value
maxnumber100Maximum value
stepnumber1Step increment
labelstring-Optional label text
unitstring''Unit suffix (e.g., "Hz", "%")
formatValue(value: number) => string-Custom value formatter
showButtonsbooleantrueShow +/- buttons
disabledbooleanfalseDisable the slider
classNamestring''Container class
labelClassNamestring''Label class
valueClassNamestring''Value display class
controlClassNamestring''Control wrapper class
buttonClassNamestring''Button class
inputClassNamestring''Range input class

Usage

Basic Usage

tsx
import { Slider } from '@mode-7/mod';
import { useState } from 'react';

function MyComponent() {
  const [volume, setVolume] = useState(50);

  return (
    <Slider
      value={volume}
      onChange={setVolume}
      min={0}
      max={100}
      label="Volume"
      unit="%"
    />
  );
}

Without Buttons

tsx
<Slider
  value={value}
  onChange={setValue}
  showButtons={false}
  label="Pan"
  min={-1}
  max={1}
  step={0.01}
/>

With Custom Formatting

tsx
<Slider
  value={frequency}
  onChange={setFrequency}
  min={20}
  max={20000}
  step={1}
  label="Frequency"
  formatValue={(val) => {
    if (val >= 1000) {
      return `${(val / 1000).toFixed(1)} kHz`;
    }
    return `${val.toFixed(0)} Hz`;
  }}
/>

Logarithmic Scale

For parameters like frequency that work better on a logarithmic scale:

tsx
import { useState } from 'react';

function LogSlider() {
  const [frequency, setFrequency] = useState(440);

  // Convert linear slider position to logarithmic frequency
  const minLog = Math.log(20);
  const maxLog = Math.log(20000);
  const scale = (maxLog - minLog) / 100;

  const handleChange = (position: number) => {
    const freq = Math.exp(minLog + scale * position);
    setFrequency(freq);
  };

  const position = (Math.log(frequency) - minLog) / scale;

  return (
    <Slider
      value={position}
      onChange={handleChange}
      min={0}
      max={100}
      label="Frequency"
      formatValue={() => `${frequency.toFixed(0)} Hz`}
    />
  );
}

With Tailwind Styling

tsx
<Slider
  value={value}
  onChange={setValue}
  label="Gain"
  unit=" dB"
  className="w-full p-2"
  labelClassName="text-gray-400 text-xs uppercase tracking-wide"
  valueClassName="text-emerald-500 text-xs font-mono"
  buttonClassName="bg-gray-800 hover:bg-gray-700 border-gray-600 text-gray-400 hover:text-emerald-500"
  inputClassName="accent-emerald-500"
/>

Disabled State

tsx
<Slider
  value={value}
  onChange={setValue}
  label="Locked Parameter"
  disabled={true}
/>

Multiple Sliders

tsx
function EQControls() {
  const [low, setLow] = useState(0);
  const [mid, setMid] = useState(0);
  const [high, setHigh] = useState(0);

  return (
    <div className="eq-controls">
      <Slider
        value={low}
        onChange={setLow}
        min={-12}
        max={12}
        step={0.1}
        label="Low"
        unit=" dB"
      />
      <Slider
        value={mid}
        onChange={setMid}
        min={-12}
        max={12}
        step={0.1}
        label="Mid"
        unit=" dB"
      />
      <Slider
        value={high}
        onChange={setHigh}
        min={-12}
        max={12}
        step={0.1}
        label="High"
        unit=" dB"
      />
    </div>
  );
}

CSS Classes

The Slider component uses the following CSS classes:

  • .modui-slider - Container element
  • .modui-slider-header - Header with label and value
  • .modui-slider-label - Label text
  • .modui-slider-value - Value display
  • .modui-slider-control - Control wrapper (input + buttons)
  • .modui-slider-button - Button elements (both + and -)
  • .modui-slider-button-minus - Decrement button
  • .modui-slider-button-plus - Increment button
  • .modui-slider-input - Range input element

Styling Examples

Custom Theme

css
.modui-slider {
  padding: 0.75rem;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 8px;
}

.modui-slider-label {
  color: rgba(255, 255, 255, 0.9);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.modui-slider-value {
  color: white;
  font-weight: bold;
}

.modui-slider-button {
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: white;
}

.modui-slider-button:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.5);
}

.modui-slider-input::-webkit-slider-thumb {
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

Minimal Style

css
.modui-slider {
  width: 100%;
}

.modui-slider-header {
  margin-bottom: 0.25rem;
}

.modui-slider-label,
.modui-slider-value {
  font-size: 10px;
  color: #666;
}

.modui-slider-button {
  display: none; /* Hide buttons for minimal look */
}

.modui-slider-input {
  height: 2px;
  background: #e0e0e0;
  border: none;
}

.modui-slider-input::-webkit-slider-thumb {
  width: 12px;
  height: 12px;
  background: #333;
  box-shadow: none;
}

Accessibility

The Slider component includes:

  • aria-label attributes for screen readers
  • Keyboard support (arrow keys work on the range input)
  • Proper disabled state handling
  • Focus indicators
  • Semantic button elements with type="button"

Released under the MIT License.