Dual Range Slider
An enhanced slider component that allows users to select a range between two values.
2575
tsx
import { DualRangeSlider } from '@/components/ui/dual-range-slider'
export function DualRangeSliderDemo() { return ( <DualRangeSlider defaultValue={[25, 75]} showLabel /> )}
Installation
CLI
bash
npx fivui add dual-range-slider
Manual
Copy and paste the following code into your project.
bash
npm install @radix-ui/react-slider
components/ui/dual-range-slider.tsx
"use client"
import * as React from "react"import * as SliderPrimitive from "@radix-ui/react-slider"import { cn } from "@/lib/utils"
export interface DualRangeSliderProps extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> { formatLabel?: (value: number) => string showLabel?: boolean}
const DualRangeSlider = React.forwardRef< React.ElementRef<typeof SliderPrimitive.Root>, DualRangeSliderProps>(({ className, formatLabel, showLabel = true, ...props}, ref) => { const [values, setValues] = React.useState<number[]>(props.defaultValue as number[] || [25, 75])
const handleValueChange = (newValues: number[]) => { setValues(newValues) if (props.onValueChange) { props.onValueChange(newValues) } }
const renderLabel = (value: number) => { if (!showLabel) return null return formatLabel ? formatLabel(value) : value.toString() }
return ( <div className="relative w-full"> {showLabel && ( <div className="absolute -top-6 left-0 right-0 flex justify-between"> <span className="text-sm">{renderLabel(values[0])}</span> <span className="text-sm">{renderLabel(values[1])}</span> </div> )} <SliderPrimitive.Root ref={ref} className={cn( "relative flex w-full touch-none select-none items-center", className )} onValueChange={handleValueChange} {...props} > <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary"> <SliderPrimitive.Range className="absolute h-full bg-primary" /> </SliderPrimitive.Track> <SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" /> <SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" /> </SliderPrimitive.Root> </div> )})
DualRangeSlider.displayName = "DualRangeSlider"
export { DualRangeSlider }
Examples
Default
2575
tsx
<DualRangeSlider defaultValue={[25, 75]} />
With Custom Label
$20$80
tsx
<DualRangeSlider defaultValue={[20, 80]} formatLabel={(value) => '$' + value}/>
With Custom Range
$1000$5000
tsx
<DualRangeSlider defaultValue={[1000, 5000]} min={0} max={10000} step={100} formatLabel={(value) => '$' + value}/>
With Step
0100
tsx
<DualRangeSlider defaultValue={[0, 100]} step={10}/>
Disabled
3070
tsx
<DualRangeSlider defaultValue={[30, 70]} disabled/>
API Reference
DualRangeSlider
Prop | Type | Default | Description |
---|---|---|---|
defaultValue | number[] | [25, 75] | Initial values for the range |
formatLabel | (value: number) => string | - | Function to format the label values |
showLabel | boolean | true | Whether to show value labels |
min | number | 0 | Minimum value |
max | number | 100 | Maximum value |
step | number | 1 | Step increment value |
disabled | boolean | false | Whether the slider is disabled |