All components
Dual Range Slider
slidersUi-Layouts component.
responsive · 600px
Install
Same command in any shadcn project — React (Vite/CRA), Next.js, Remix, Astro, and more:
$
npx shadcn@latest add https://your-domain/r/slider.jsonUsage
import { DualRangeSlider } from "@/registry/ui-layouts/slider";
export default function Demo() {
return <DualRangeSlider />;
}Component source
'use client';
import { cn } from '@/lib/utils';
import NumberFlow from '@number-flow/react';
import * as SliderPrimitive from '@radix-ui/react-slider';
import { GripVertical } from 'lucide-react';
import * as React from 'react';
interface DualRangeSliderProps extends React.ComponentProps<typeof SliderPrimitive.Root> {
labelPosition?: 'top' | 'bottom' | 'static';
lableContenPos?: 'left' | 'right';
label?: React.ReactNode | ((value: number | undefined) => React.ReactNode);
}
const DualRangeSlider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
DualRangeSliderProps
>(({ className, label, labelPosition = 'top', lableContenPos = 'right', ...props }, ref) => {
const initialValue = Array.isArray(props.value) ? props.value : [props.min, props.max];
return (
<SliderPrimitive.Root
ref={ref}
className={cn('relative flex w-full touch-none select-none items-center', className)}
{...props}
>
<SliderPrimitive.Track className='relative h-6 w-full grow overflow-hidden bg-[linear-gradient(to_right,#e2e2e22c_1px,transparent_1px),linear-gradient(to_bottom,#9c9c9c2c_1px,transparent_1px)] bg-size-[4px_4px] dark:bg-neutral-950 bg-neutral-50 rounded-md dark:bg-[linear-gradient(to_right,#4f4f4f2e_1px,transparent_1px),linear-gradient(to_bottom,#4f4f4f2e_1px,transparent_1px)]'>
<SliderPrimitive.Range className='absolute h-full dark:bg-neutral-100 bg-neutral-950' />
</SliderPrimitive.Track>
<>
{initialValue.map((value, index) => (
<React.Fragment key={value}>
<SliderPrimitive.Thumb className='relative grid h-6 w-3 cursor-grab place-content-center dark:bg-neutral-100 bg-neutral-950 shadow-sm focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-white'>
{label && labelPosition !== 'static' && (
<div
className={cn(
'absolute flex w-full justify-center items-start gap-0.5',
labelPosition === 'top' && '-top-7',
labelPosition === 'bottom' && 'top-4'
)}
>
{lableContenPos === 'left' && (
<>
{typeof label === 'function' ? (
<span className='inline-block -translate-y-0.5'>{label(value)}</span>
) : (
label && <span className='inline-block '>{label}</span>
)}
</>
)}
<NumberFlow
willChange
// @ts-expect-error
value={value}
isolate
opacityTiming={{
duration: 250,
easing: 'ease-out',
}}
transformTiming={{
easing: `linear(0, 0.0033 0.8%, 0.0263 2.39%, 0.0896 4.77%, 0.4676 15.12%, 0.5688, 0.6553, 0.7274, 0.7862, 0.8336 31.04%, 0.8793, 0.9132 38.99%, 0.9421 43.77%, 0.9642 49.34%, 0.9796 55.71%, 0.9893 62.87%, 0.9952 71.62%, 0.9983 82.76%, 0.9996 99.47%)`,
duration: 500,
}}
/>
{lableContenPos === 'right' && (
<>
{typeof label === 'function' ? (
<span className='inline-block -translate-y-1'>{label(value)}</span>
) : (
label && <span className='inline-block '>{label}</span>
)}
</>
)}
</div>
)}
<GripVertical size={16} className='px-0.5 text-primary-foreground' />
</SliderPrimitive.Thumb>
</React.Fragment>
))}
</>
{label && labelPosition === 'static' && (
<>
{initialValue.map((value, index) => (
<div
key={`${value}-${index}`}
className={cn(
'absolute -top-7 w-fit right-0 flex justify-center items-start gap-0.5'
)}
>
{lableContenPos === 'left' && (
<>
{typeof label === 'function' ? (
<span className='inline-block -translate-y-0.5'>{label(value)}</span>
) : (
label && <span className='inline-block '>{label}</span>
)}
</>
)}
<NumberFlow
willChange
// @ts-expect-error
value={value}
isolate
opacityTiming={{
duration: 250,
easing: 'ease-out',
}}
transformTiming={{
easing: `linear(0, 0.0033 0.8%, 0.0263 2.39%, 0.0896 4.77%, 0.4676 15.12%, 0.5688, 0.6553, 0.7274, 0.7862, 0.8336 31.04%, 0.8793, 0.9132 38.99%, 0.9421 43.77%, 0.9642 49.34%, 0.9796 55.71%, 0.9893 62.87%, 0.9952 71.62%, 0.9983 82.76%, 0.9996 99.47%)`,
duration: 500,
}}
/>
{lableContenPos === 'right' && (
<>
{typeof label === 'function' ? (
<span className='inline-block -translate-y-1'>{label(value)}</span>
) : (
label && <span className='inline-block '>{label}</span>
)}
</>
)}
</div>
))}
</>
)}
</SliderPrimitive.Root>
);
});
DualRangeSlider.displayName = 'DualRangeSlider';
export { DualRangeSlider };Dependencies
@number-flow/react@radix-ui/react-slider
Source: Ui-Layouts