import { Slider } from "@/components/ui/slider"
export default function SliderDemo() {
return <Slider defaultValue={[50]} max={100} step={1} className="w-[60%]" />
}Installation
npx logic2b@latest add sliderWorking with an AI assistant? Copy this prompt into Claude Code, Cursor or Copilot — it carries the install steps, a no-CLI fallback and a verification checklist.
Add the "slider" item from the logic2b ui registry (https://ui.logic2b.com) to this project. Follow every step and verify at the end. ## Steps 1. If the project has no `components.json` yet, set up logic2b ui first: ```bash npx logic2b@latest init ``` 2. Install the item (the CLI resolves registry dependencies automatically): ```bash npx logic2b@latest add slider ``` 3. Install any npm dependencies the command prints. ## If the CLI is not available Do it manually from the registry payload: 1. Fetch https://ui.logic2b.com/r/slider.json. 2. Write every entry in `files[]` to its mapped project path (see below). 3. Repeat (recursively) for each name in `registryDependencies`. 4. Install every package listed in `dependencies` across those payloads. ## Registry reference - Index of every item: https://ui.logic2b.com/r/index.json - Item payload (full source): https://ui.logic2b.com/r/<name>.json - Usage examples per item: https://ui.logic2b.com/r/demos/index.json → https://ui.logic2b.com/r/demos/<demo>.json - Docs index for agents: https://ui.logic2b.com/llms.txt (full docs: https://ui.logic2b.com/llms-full.txt) - Every docs page is Markdown when you append `.md` to its URL. Registry file paths map to project paths like this: - `ui/*` → `@/components/ui/*` - `blocks/<name>/*` → `@/components/*` - `charts/*` → `@/components/charts/*` - `hooks/*` → `@/hooks/*` - `lib/utils.ts` → `@/lib/utils.ts` - `theme.css` → next to the project's Tailwind entry stylesheet ## Conventions (do not break these) - Tailwind CSS v4 (CSS-first config; no tailwind.config.js needed) and React 19. - All colors go through semantic tokens (`bg-primary`, `text-muted-foreground`, `border-border`, …). Never hardcode hex/oklch values in components. - Dark mode is class-based: toggle `.dark` on `<html>`. - Icons come from lucide-react. ## Verify before finishing 1. The dev server starts and the app renders without console errors. 2. TypeScript compiles (`tsc --noEmit` or the framework's check). 3. Components use the theme: a `<Button>` shows the primary token color, and toggling `.dark` on `<html>` switches the palette.
Install the dependencies:
npm install radix-uiCopy into 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={cn(
"bg-muted relative grow overflow-hidden rounded-full 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={cn(
"bg-primary absolute 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="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
/>
))}
</SliderPrimitive.Root>
)
}
export { Slider }Usage
import { Slider } from "@/components/ui/slider"
<Slider defaultValue={[50]} max={100} step={1} />
API
Built on Radix Slider.Root. Values are always arrays, so a single-thumb
slider uses [value] and a range uses [start, end].
| Prop | Type | Default |
|---|---|---|
defaultValue |
number[] |
[min, max] |
value |
number[] — controlled value |
— |
onValueChange |
(value: number[]) => void |
— |
min |
number |
0 |
max |
number |
100 |
step |
number |
1 |
orientation |
horizontal | vertical |
horizontal |
disabled |
boolean |
false |
Examples
Range
import { Slider } from "@/components/ui/slider"
export default function SliderRangeDemo() {
return (
<Slider defaultValue={[25, 75]} max={100} step={1} className="w-[60%]" />
)
}Controlled
40
import * as React from "react"
import { Label } from "@/components/ui/label"
import { Slider } from "@/components/ui/slider"
export default function SliderControlledDemo() {
const [value, setValue] = React.useState([40])
return (
<div className="flex w-[60%] flex-col gap-3">
<div className="flex items-center justify-between">
<Label htmlFor="volume">Volume</Label>
<span className="text-muted-foreground text-sm tabular-nums">
{value[0]}
</span>
</div>
<Slider
id="volume"
value={value}
onValueChange={setValue}
max={100}
step={5}
/>
</div>
)
}Vertical
import { Slider } from "@/components/ui/slider"
export default function SliderVerticalDemo() {
return (
<div className="flex h-48 items-center gap-8">
<Slider defaultValue={[60]} max={100} step={1} orientation="vertical" />
<Slider
defaultValue={[20, 80]}
max={100}
step={1}
orientation="vertical"
/>
<Slider
defaultValue={[40]}
max={100}
step={1}
orientation="vertical"
disabled
/>
</div>
)
}Accessibility
- Each thumb is a
sliderrole element that is fully keyboard operable. Arrowkeys move bystep;Page Up/Page Downmove by a larger increment;Home/Endjump tomin/max.- Associate a visible label with the control (e.g. via
Label htmlFororaria-label) so screen readers announce its purpose. - On range sliders each thumb is focusable independently and cannot cross past its neighbor.