Morphos
Inputs

Slider

A range input slider with orientation support and a CSS custom property for custom track styling.

Interactive example

Installation

npm install @morphos/inputs
pnpm add @morphos/inputs
yarn add @morphos/inputs
bun add @morphos/inputs

Import

import { Slider } from '@morphos/inputs'

Usage

@Component()
class MyComponent extends StatefulComponent {
  @State() volume = 50

  render() {
    return (
      <Slider
        value={this.volume}
        min={0}
        max={100}
        step={1}
        onValueChange={(v) => (this.volume = v)}
        aria-label="Volume"
      />
    )
  }
}

Uncontrolled

@Component()
class MyComponent extends StatefulComponent {
  render() {
    return (
      <Slider
        defaultValue={25}
        min={0}
        max={100}
        step={5}
        name="brightness"
        aria-label="Brightness"
      />
    )
  }
}

Custom filled track

// CSS
// .slider-track {
//   position: relative;
// }
// .slider-track::before {
//   content: '';
//   position: absolute;
//   inset-block: 0;
//   inset-inline-start: 0;
//   width: var(--slider-value);
//   background: currentColor;
//   border-radius: inherit;
// }

@Component()
class MyComponent extends StatefulComponent {
  @State() price = 200

  render() {
    return (
      <Slider
        class="slider-track"
        value={this.price}
        min={0}
        max={1000}
        step={10}
        onValueChange={(v) => (this.price = v)}
        aria-label="Max price"
      />
    )
  }
}

Vertical orientation

@Component()
class MyComponent extends StatefulComponent {
  @State() eq = 0

  render() {
    return (
      <Slider
        value={this.eq}
        min={-12}
        max={12}
        step={0.5}
        orientation="vertical"
        onValueChange={(v) => (this.eq = v)}
        aria-label="EQ gain (dB)"
      />
    )
  }
}

Props — Slider

PropTypeDefaultDescription
valuenumberControlled current value
defaultValuenumberUncontrolled initial value
minnumber0Minimum value
maxnumber100Maximum value
stepnumber1Increment between values
disabledbooleanfalseDisables the slider
namestringForm field name for submission
orientation"horizontal" | "vertical""horizontal"Slider orientation
onValueChange(value: number) => voidFires when the value changes
classstringAdditional CSS classes on the root element
idstringHTML id attribute, applied to the inner <input type="range">
aria-labelstringAccessible label (required when no visible label is present)
aria-labelledbystringID of an element that labels the slider
aria-describedbystringID of an element that describes the slider

CSS custom properties

PropertyValueDescription
--slider-value0%100%Current value expressed as a percentage of the range

data-* attributes

AttributeElementWhen present
data-orientationRootAlways — value is "horizontal" or "vertical"
data-disabledRootdisabled is true
data-valueRootAlways — contains the current numeric value as a string

Accessibility

The Slider renders a <div role="presentation"> wrapper containing a native <input type="range">. The native range input handles all keyboard interaction, ARIA semantics (aria-valuenow, aria-valuemin, aria-valuemax, aria-orientation), and form participation without extra ARIA work. The wrapper div exists only to expose data-orientation, data-disabled, and data-value for styling.

Use the --slider-value CSS custom property with a ::before pseudo-element on the root element to build a custom filled portion of the track. The percentage is computed as (value - min) / (max - min) * 100.

Styling example

.morphos-slider > input[type="range"] {
  background: linear-gradient(
    to right,
    var(--morphos-color-accent) var(--slider-value, 0%),
    var(--morphos-color-border) var(--slider-value, 0%)
  );
}

.morphos-slider[data-orientation="vertical"] {
  writing-mode: vertical-lr;
  direction: rtl;
}

.morphos-slider[data-disabled] {
  opacity: 0.5;
}

On this page