Skip to content

Slider

A draggable input to control numeric values.

Props


Features

  • 🎹 Keyboard navigation
  • 🧠 Smart focus management
  • 🔄 Horizontal and vertical orientation
  • 💬 Tooltip value display
  • 🌐 RTL support (incoming!)

Usage

<script lang="ts">
import { Slider, type SliderProps } from "melt/builders";
const slider = new Slider();
</script>
<div {...slider.root}>
<div {...slider.thumb}></div>
</div>

Positioning

By default, Melt does not provide styles. This means that you’ll be responsible for positioning the thumb and range of your slider.

To facilitate this, Melt provides some CSS properties, --percentage and --percentage-inv.

<Slider value={30} {...controls}>
{#snippet children(slider)}
<div class="slider" {...slider.root}>
<div class="track">
<div class="range"></div>
<div {...slider.thumb}></div>
</div>
</div>
{/snippet}
</Slider>
<style>
.slider {
width: 300px;
height: 40px;
margin: 0 auto;
padding-block: 16px; /* padding to increase touch area */
}
.slider .track {
background: grey;
height: 100%;
position: relative;
}
.slider .range {
position: absolute;
background: green;
inset: 0;
right: var(--percentage-inv);
}
.slider [data-melt-slider-thumb] {
position: absolute;
background: white;
left: var(--percentage);
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
}
</style>

Transitions

TODO: Write about data-dragging

API Reference

Constructor Props

The props that are passed when calling
new Slider()
    export type SliderProps = {
    /**
    * The minimum value of the slider.
    *
    * @default 0
    */
    min?: MaybeGetter<number | undefined>;
    /**
    * The maximum value of the slider.
    *
    * @default 100
    */
    max?: MaybeGetter<number | undefined>;
    /**
    * The orientation of the slider.
    *
    * @default "horizontal"
    */
    orientation?: MaybeGetter<"horizontal" | "vertical" | undefined>;
    /**
    * The step size of the slider.
    *
    * @default 1
    */
    step?: MaybeGetter<number | undefined>;
    /**
    * The default value for `tabs.value`
    *
    * When passing a getter, it will be used as source of truth,
    * meaning that `tabs.value` only changes when the getter returns a new value.
    *
    * If omitted, it will use the first tab as default.
    *
    * @default undefined
    */
    value?: MaybeGetter<number | undefined>;
    /**
    * Called when the `Slider` instance tries to change the active tab.
    */
    onValueChange?: (active: number) => void;
    };

Properties

The properties returned from
new Slider()
  • min

    number
  • max

    number
  • orientation

    "horizontal" | "vertical"
  • step

    number
  • value

    number
    The value of the slider.
  • root

    {
    readonly "data-dragging": "" | undefined
    readonly "data-value": number
    readonly "data-orientation": "horizontal" | "vertical"
    readonly "aria-valuenow": number
    readonly "aria-valuemin": number
    readonly "aria-valuemax": number
    readonly "aria-orientation": "horizontal" | "vertical"
    readonly style: `--percentage: ${string}; --percentage-inv: ${string}; touch-action: ${string}`
    readonly tabindex: 0
    readonly role: "slider"
    readonly "data-melt-slider-root": ""
    readonly id: string
    readonly onpointerdown: (e: PointerEvent) => void
    readonly onkeydown: (e: KeyboardEvent) => void
    }
    The root of the slider. Any cursor interaction along this element will change the slider's values.
  • thumb

    {
    readonly "data-dragging": "" | undefined
    readonly "data-value": number
    readonly "data-orientation": "horizontal" | "vertical"
    readonly "data-melt-slider-thumb": ""
    readonly tabindex: 0
    }
    The slider's thumb, positioned at the end of the range.