Introduction
Shadcn/ui, which is a UI Library that provides a set of pre-styled, accessible React UI components built on top of Radix UI.
However, the slider component does not appear to support the range features provided by the Radix slider. There’s an issue open that points out that the Radix Slider should be able to support ranges with multiple handles. We’ve modified the shadcn/ui slider component to implement range features provided by Radix (or we’ve tried our best and it seems to be working). We’ve also added label support for the multiple handles.
So far shadcn/ui is a very impressive UI library that we’re exited to investigate and share with others.
Steps to modify the shadcn/ui slider
1. Review the original slider component code
The original shadcn Slider component (at the time of this article) is as follows:
import * as React from "react"
import * as SliderPrimitive from "@radix-ui/react-slider"
import { cn } from "@/components/app/shadcn/lib/utils"
const Slider = React.forwardRef(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn("relative flex w-full touch-none select-none items-center", className)}
{...props}>
<SliderPrimitive.Track
className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
))
Slider.displayName = SliderPrimitive.Root.displayName
export { Slider }
Code language: JavaScript (javascript)
2. Add range support & label support
The idea is to change the value
prop from a single number to an array [min, max]
as well as allow us to pass labels that show the min and max values selected by each handle:
import React, { useState } from 'react';
import * as SliderPrimitive from '@radix-ui/react-slider';
import { cn } from '@/components/app/shadcn/lib/utils';
const Slider = React.forwardRef(({ className, min, max, step, formatLabel, value, onValueChange, ...props }, ref) => {
const initialValue = Array.isArray(value) ? value : [min, max];
const [localValues, setLocalValues] = useState(initialValue);
const handleValueChange = (newValues) => {
setLocalValues(newValues);
if (onValueChange) {
onValueChange(newValues);
}
};
return (
<SliderPrimitive.Root
ref={ref}
min={min}
max={max}
step={step}
value={localValues}
onValueChange={handleValueChange}
className={cn('relative flex w-full touch-none select-none items-center', className)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
{localValues.map((value, index) => (
<React.Fragment key={index}>
<div className="absolute text-center" style={{ left: `calc(${((value - min) / (max - min)) * 100}% + 0px)` , top: `10px`}}>
<span className="text-xs">{formatLabel ? formatLabel(value) : value}</span>
</div>
<SliderPrimitive.Thumb
className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50"
/>
</React.Fragment>
))}
</SliderPrimitive.Root>
);
});
Slider.displayName = SliderPrimitive.Root.displayName;
export { Slider };
Code language: JavaScript (javascript)
3. Usage
You can use the enhanced shadcn Slider in your component as follows:
import { Slider } from "./path-to-enhanced-slider"; // Adjust the import path accordingly
const MyComponent = () => {
const [range, setRange] = useState([0, 24]);
const handleRangeChange = (value) => {
setRange(value);
};
return (
<Slider
defaultValue={[0, 24]}
max={48}
min={0}
step={1}
value={range}
onValueChange={handleRangeChange}
formatLabel={(value) => `${value} hrs`}
/>
);
};
Code language: JavaScript (javascript)
Conclusion
By extending the original shadcn/ui slider component, we’ve added the ability to select a range with two handles and display labels below them.
Please consider we’ve stripped down code to help with presentation. If you have any comments, please ask here or even better in the shadcn/ui github issue mentioned earlier.
Happy coding!
Support our work
Support the GBTI network by becoming a member of our private community.