Forms
Slider.
Pick a number or a range by dragging square thumbs along a track, or with the arrow keys.
8 chunks
"use client";
import * as React from "react";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
export default function SliderDemo() {
const [value, setValue] = React.useState([8]);
return (
<div className="grid w-full max-w-sm gap-4">
<div className="flex items-center justify-between gap-3">
<Label id="sl-radius-label">Render distance</Label>
<span className="font-mono text-xs text-primary">{value[0]} chunks</span>
</div>
<Slider value={value} onValueChange={setValue} min={2} max={16} step={1} aria-labelledby="sl-radius-label" />
</div>
);
}Installation#
With the CLI
$npx lanterncn add sliderThis also installs the Lantern theme and any Lantern UI components it depends on. The shadcn CLI works directly too: npx shadcn@latest add httptim/lantern-ui/slider. See Installation if your project is not set up yet.
Manually
Install the dependencies
npm install radix-uiCopy the source into your project
components/ui/slider.tsx"use client"; import * as React from "react"; import { Slider as SliderPrimitive } from "radix-ui"; import { cn } from "@/lib/utils"; function Slider({ className, defaultValue, value, min = 0, max = 100, ...props }: React.ComponentProps<typeof SliderPrimitive.Root>) { const values = React.useMemo( () => (Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max]), [value, defaultValue, min, max], ); return ( <SliderPrimitive.Root data-slot="slider" defaultValue={defaultValue} value={value} min={min} max={max} className={cn( "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", className, )} {...props} > <SliderPrimitive.Track data-slot="slider-track" className="relative grow overflow-hidden rounded-sm bg-secondary ring-1 ring-border data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5" > <SliderPrimitive.Range data-slot="slider-range" className="absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full" /> </SliderPrimitive.Track> {Array.from({ length: values.length }, (_, index) => ( <SliderPrimitive.Thumb data-slot="slider-thumb" key={index} className="block size-4 shrink-0 cursor-grab rounded-sm border-2 border-primary bg-background shadow-[2px_2px_0_var(--block-shadow)] transition-[box-shadow] outline-none hover:ring-4 hover:ring-ring/20 focus-visible:ring-4 focus-visible:ring-ring/30 active:cursor-grabbing disabled:pointer-events-none" /> ))} </SliderPrimitive.Root> ); } export { Slider };Update the import paths to match your project
The source imports
cnfrom@/lib/utils.
Usage#
import { Slider } from "@/components/ui/slider";<Slider defaultValue={[8]} min={2} max={16} step={1} />Pass two values to get a range with two thumbs. Give the slider an aria-label or aria-labelledby.
Examples#
Range
06:00 to 18:00
DawnDusk
"use client";
import * as React from "react";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
const fmt = (h: number) => `${String(h).padStart(2, "0")}:00`;
export default function SliderRange() {
const [value, setValue] = React.useState([6, 18]);
return (
<div className="grid w-full max-w-sm gap-4">
<div className="flex items-center justify-between gap-3">
<Label id="sl-window-label">Sync window</Label>
<span className="font-mono text-xs text-primary">
{fmt(value[0])} to {fmt(value[1])}
</span>
</div>
<Slider
value={value}
onValueChange={setValue}
min={0}
max={24}
step={1}
minStepsBetweenThumbs={1}
aria-labelledby="sl-window-label"
/>
<div className="flex justify-between font-mono text-[10px] tracking-[0.2em] text-muted-foreground uppercase">
<span>Dawn</span>
<span>Dusk</span>
</div>
</div>
);
}