Zaidan

Command Palette

Search for a command to run...

GitHub69

Slider

An input where the user selects a value from within a given range.

Installation

CLI

Manual

Copy and paste the following code into your project.

import type { PolymorphicProps } from "@kobalte/core/polymorphic";
import {
type SliderFillProps,
Slider as SliderPrimitive,
type SliderRootProps,
type SliderThumbProps,
type SliderTrackProps,
useSliderContext,
} from "@kobalte/core/slider";
import {
type ComponentProps,
createMemo,
For,
mergeProps,
splitProps,
untrack,
type ValidComponent,
} from "solid-js";
import { cn } from "~/lib/utils";
type SliderProps<T extends ValidComponent = "div"> = PolymorphicProps<T, SliderRootProps<T>> &
Pick<ComponentProps<T>, "class">;
const Slider = <T extends ValidComponent = "div">(rawProps: SliderProps<T>) => {
const props = mergeProps({ minValue: 0, maxValue: 100 } as SliderProps<T>, rawProps);
const [local, others] = splitProps(props as SliderProps, ["class", "defaultValue", "value"]);
const values = createMemo(() => {
if (Array.isArray(untrack(() => local.value))) return untrack(() => local.value);
if (Array.isArray(local.defaultValue)) return local.defaultValue;
return [others.minValue, others.maxValue];
});
return (
<SliderPrimitive
data-slot="slider"
defaultValue={local.defaultValue}
value={local.value}
class={cn(
"relative z-slider flex w-full touch-none select-none items-center data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col data-disabled:opacity-50",
local.class,
)}
{...others}
>
<SliderTrack>
<SliderFill />
</SliderTrack>
<For each={values()}>{() => <SliderThumb />}</For>
</SliderPrimitive>
);
};
type SliderTrackComponentProps<T extends ValidComponent = "div"> = PolymorphicProps<
T,
SliderTrackProps<T>
> &
Pick<ComponentProps<T>, "class" | "children">;
const SliderTrack = <T extends ValidComponent = "div">(props: SliderTrackComponentProps<T>) => {
const [local, others] = splitProps(props as SliderTrackComponentProps, ["class", "children"]);
const context = useSliderContext();
return (
<SliderPrimitive.Track
data-slot="slider-track"
data-orientation={context.state.orientation()}
class={cn(
"relative z-slider-track grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=vertical]:h-full data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-1.5",
local.class,
)}
{...others}
>
{local.children}
</SliderPrimitive.Track>
);
};
type SliderFillComponentProps<T extends ValidComponent = "div"> = PolymorphicProps<
T,
SliderFillProps<T>
> &
Pick<ComponentProps<T>, "class">;
const SliderFill = <T extends ValidComponent = "div">(props: SliderFillComponentProps<T>) => {
const [local, others] = splitProps(props as SliderFillComponentProps, ["class"]);
const context = useSliderContext();
return (
<SliderPrimitive.Fill
data-slot="slider-range"
data-orientation={context.state.orientation()}
class={cn(
"absolute z-slider-range data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full",
local.class,
)}
{...others}
/>
);
};
type SliderThumbComponentProps<T extends ValidComponent = "span"> = PolymorphicProps<
T,
SliderThumbProps<T>
> &
Pick<ComponentProps<T>, "class">;
const SliderThumb = <T extends ValidComponent = "span">(props: SliderThumbComponentProps<T>) => {
const [local, others] = splitProps(props as SliderThumbComponentProps, ["class"]);
return (
<SliderPrimitive.Thumb
data-slot="slider-thumb"
class={cn(
"z-slider-thumb block shrink-0 select-none disabled:pointer-events-none disabled:opacity-50",
local.class,
)}
{...others}
>
<SliderPrimitive.Input />
</SliderPrimitive.Thumb>
);
};
export { Slider };

Props

The Slider component uses Kobalte's Slider primitive under the hood. Here are the main props:

PropTypeDefaultDescription
valuenumber[]-The controlled value of the slider
defaultValuenumber[]-The default value of the slider
onChange(value: number[]) => void-Handler called when value changes
onChangeEnd(value: number[]) => void-Handler called after dragging ends
minValuenumber0The minimum value
maxValuenumber100The maximum value
stepnumber1The stepping interval
orientation"horizontal" | "vertical""horizontal"The orientation of the slider
disabledbooleanfalseWhether the slider is disabled

Examples

Here are the source code of all the examples from the preview page:

Basic

import { Slider } from "~/components/ui/slider";
function SliderBasic() {
return (
<Example title="Basic">
<Slider defaultValue={[50]} maxValue={100} step={1} />
</Example>
);
}

Range

import { Slider } from "~/components/ui/slider";
function SliderRange() {
return (
<Example title="Range">
<Slider defaultValue={[25, 50]} maxValue={100} step={5} />
</Example>
);
}

Multiple Thumbs

import { Slider } from "~/components/ui/slider";
function SliderMultiple() {
return (
<Example title="Multiple Thumbs">
<Slider defaultValue={[10, 20, 70]} maxValue={100} step={10} />
</Example>
);
}

Vertical

import { Slider } from "~/components/ui/slider";
function SliderVertical() {
return (
<Example title="Vertical">
<div class="flex items-center gap-6">
<Slider defaultValue={[50]} maxValue={100} step={1} orientation="vertical" class="h-40" />
<Slider defaultValue={[25]} maxValue={100} step={1} orientation="vertical" class="h-40" />
</div>
</Example>
);
}

Controlled

import { createSignal } from "solid-js";
import { Label } from "~/components/ui/label";
import { Slider } from "~/components/ui/slider";
function SliderControlled() {
const [value, setValue] = createSignal([0.3, 0.7]);
return (
<Example title="Controlled">
<div class="grid w-full gap-3">
<div class="flex items-center justify-between gap-2">
<Label for="slider-demo-temperature">Temperature</Label>
<span class="text-muted-foreground text-sm">{value().join(", ")}</span>
</div>
<Slider
id="slider-demo-temperature"
value={value()}
onChange={(v) => setValue(v)}
minValue={0}
maxValue={1}
step={0.1}
/>
</div>
</Example>
);
}

Disabled

import { Slider } from "~/components/ui/slider";
function SliderDisabled() {
return (
<Example title="Disabled">
<Slider defaultValue={[50]} maxValue={100} step={1} disabled />
</Example>
);
}