Slider
Range input styled to the tokens, with an optional value label and formatter.
import { Slider }from "@/components/ui"
Volume & threshold
60%
25
Full source
The complete component, read from src/components/ui/slider.tsx.
slider.tsx
"use client";
import { useId } from "react";
import { cn } from "@/lib/utils";
interface SliderProps {
label?: string;
value: number;
onChange: (value: number) => void;
min?: number;
max?: number;
step?: number;
disabled?: boolean;
showValue?: boolean;
format?: (value: number) => string;
className?: string;
}
export function Slider({
label,
value,
onChange,
min = 0,
max = 100,
step = 1,
disabled,
showValue,
format = (v) => String(v),
className,
}: SliderProps) {
const id = useId();
const pct = ((value - min) / (max - min)) * 100;
return (
<div className={cn("w-full", className)}>
{(label || showValue) && (
<div className="mb-1.5 flex items-center justify-between text-[13px]">
{label && <label htmlFor={id} className="font-medium text-text">{label}</label>}
{showValue && <span className="tabular-nums text-text-secondary">{format(value)}</span>}
</div>
)}
<input
id={id}
type="range"
min={min}
max={max}
step={step}
value={value}
disabled={disabled}
aria-label={label}
onChange={(e) => onChange(Number(e.target.value))}
className={cn("ui-slider w-full", disabled && "cursor-not-allowed opacity-50")}
style={{
background: `linear-gradient(to right, var(--color-accent) ${pct}%, var(--color-bg-active) ${pct}%)`,
}}
/>
</div>
);
}Dependencies
To use Slider you also need the following. Copy these into your project alongside it.
Recommended folder structure
project structure
src/components/ui/ └─ slider.tsx src/lib/ └─ utils.ts