- Accordion
- Agent Thinking
- Alert
- Alert Dialog
- Announcement
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Checkbox Card
- Code Block
- Collapsible
- Color Picker
- Combobox
- Command
- Composer
- Composer Loader
- Context Menu
- Data Grid
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- File Upload
- Hover Card
- Input
- Input Group
- Input Otp
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Meter
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Period Switcher
- Popover
- Progress
- Questionnaire
- Radio Card
- Radio Group
- Resizable
- Reveal
- Scroll Area
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Social Button
- Sonner
- Spinner
- Status Dot
- Switch
- Switch Card
- Table
- Tabs
- Tag Group
- Textarea
- Theme Toggle
- Time Field
- Toggle
- Toggle Group
- Tooltip
- Trace
- Tree View
- Agent Creator 01
- Agent Limits Card 01
- Agent Progress 01
- AI Chat 01
- AI Image Generation 01
- AI Profile 01
- Alerts Card 01
- Auth Card 01
- Calendar 01
- Composer 01
- Composer Attachments 01
- Composer Panel 01
- Finance Dashboard 01
- Home Dashboard 01
- Marketing Dashboard 01
- Medical Profile 01
- Meeting Scheduler 01
- Multi Agent Chat 01
- Notification Center 01
- Patient Info Card 01
- Project Board 01
- Questionnaire 01
- Settings Modal 01
- Sidebar 01
- Stat Cards 01
- Task List 01
- Web Search 01
- Activity Rings Card 01
- Area Chart Card 01
- Bar List Card 01
- Combo Chart Card 01
- Contributions Card 01
- Earnings Chart Card 01
- Funnel Chart Card 01
- Heatmap Chart Card 01
- Line Chart Card 01
- Most Active Days Card 01
- Orders Chart Card 01
- Radar Chart Card 01
- Radial Chart Card 01
- Revenue Chart Card 01
- Sankey Chart Card 01
- Scatter Chart Card 01
- Sleep Score Card 01
- Stage Bars Card 01
- Steps Card 01
Volume
Price range
Exact value
Without value bubbles
Disabled range
Installation
$ pnpm dlx shadcn@latest add @cobalt/slider
Source
import { Slider as SliderPrimitive } from "@base-ui/react/slider";
import { cn } from "cn";
import type * as React from "react";
function Slider({
className,
defaultValue,
value,
min = 0,
max = 100,
label,
showTooltip = true,
formatValue,
thumbLabels,
variant = "default",
trackContent,
...props
}: SliderPrimitive.Root.Props & {
/**
* `stepped` is a 28px recessed track with a tick for every step and a
* lifted block thumb, for choosing one of a few levels. Pass `step`.
*/
variant?: "default" | "stepped";
/** `stepped` only: drawn over the track, under the thumb. */
trackContent?: React.ReactNode;
label?: React.ReactNode;
showTooltip?: boolean;
formatValue?: (value: number, index: number) => React.ReactNode;
thumbLabels?: string[];
}) {
const current = value ?? defaultValue;
const count = Array.isArray(current) ? current.length : 1;
if (variant === "stepped") {
const steps = Math.max(
1,
Math.round((max - min) / (Number(props.step) || 1))
);
return (
<SliderPrimitive.Root
data-slot="slider"
data-variant="stepped"
className={cn(
"group flex min-w-0 flex-col gap-2 data-horizontal:w-full data-disabled:cursor-not-allowed data-disabled:opacity-50",
className
)}
defaultValue={defaultValue}
value={value}
min={min}
max={max}
thumbAlignment="edge"
{...props}
>
{label != null && (
<SliderPrimitive.Label className="text-sm leading-5 font-medium text-foreground">
{label}
</SliderPrimitive.Label>
)}
<SliderPrimitive.Control className="relative flex h-7 w-full touch-none items-center select-none">
<SliderPrimitive.Track
data-slot="slider-track"
className="relative h-full grow overflow-hidden rounded-[8px] bg-[var(--surface-sunken,var(--muted))]"
>
<SliderPrimitive.Indicator
data-slot="slider-range"
className="rounded-[8px] bg-[var(--border-strong,var(--accent))]"
/>
{Array.from({ length: steps + 1 }, (_, index) => (
<span
aria-hidden
key={index}
className="pointer-events-none absolute top-1/2 h-3 w-0.5 -translate-x-1/2 -translate-y-1/2 rounded-full bg-[var(--foreground-subtle,var(--muted-foreground))]/50"
style={{
left: `calc(10px + (100% - 20px) * ${index / steps})`,
}}
/>
))}
{trackContent}
</SliderPrimitive.Track>
{Array.from({ length: count }, (_, index) => (
<SliderPrimitive.Thumb
key={index}
index={index}
data-slot="slider-thumb"
getAriaLabel={() => thumbLabels?.[index] ?? "Value"}
className="h-7 w-5 cursor-grab rounded-[8px] border border-[var(--border-hover,var(--border))] bg-[var(--surface-raised,var(--background))] shadow-[0_1px_2px_0_rgb(0_0_0/0.18)] outline-none transition-[box-shadow] duration-150 focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing motion-reduce:transition-none"
/>
))}
</SliderPrimitive.Control>
</SliderPrimitive.Root>
);
}
return (
<SliderPrimitive.Root
data-slot="slider"
className={cn(
"group flex min-w-0 flex-col gap-2 data-horizontal:w-full data-vertical:h-full data-disabled:cursor-not-allowed data-disabled:opacity-50",
className
)}
defaultValue={defaultValue}
value={value}
min={min}
max={max}
thumbAlignment="center"
{...props}
>
{label != null && (
<SliderPrimitive.Label className="text-sm leading-5 font-medium text-foreground">
{label}
</SliderPrimitive.Label>
)}
<SliderPrimitive.Control
className={cn(
"relative flex touch-none items-center select-none data-horizontal:h-8 data-horizontal:w-full data-vertical:h-full data-vertical:min-h-40 data-vertical:w-8 data-vertical:flex-col",
showTooltip && "data-horizontal:mt-8"
)}
>
<SliderPrimitive.Track
data-slot="slider-track"
className="relative grow rounded-full bg-[var(--surface-strong,var(--input))] shadow-[inset_0_1px_1px_rgb(0_0_0/0.06)] transition-colors duration-150 ease-[ease] group-hover:bg-[var(--border-strong,var(--border))] motion-reduce:transition-none data-horizontal:h-1.5 data-horizontal:w-full data-vertical:h-full data-vertical:w-1.5"
>
<SliderPrimitive.Indicator
data-slot="slider-range"
className="rounded-full bg-primary bg-[image:var(--slider-range-gradient,var(--gradient-button-primary-default,linear-gradient(90deg,var(--primary),var(--primary))))] shadow-[inset_0_1px_0_rgb(255_255_255/0.24),0_1px_2px_rgb(4_80_226/0.16)] data-horizontal:h-full data-vertical:w-full"
/>
</SliderPrimitive.Track>
{Array.from({ length: count }, (_, index) => (
<SliderPrimitive.Thumb
key={index}
index={index}
data-slot="slider-thumb"
getAriaLabel={() =>
thumbLabels?.[index] ??
(count > 1 ? `Value ${index + 1}` : "Value")
}
className="group/thumb flex size-5 cursor-grab items-center justify-center rounded-full border border-border bg-[var(--slider-thumb-surface,var(--background))] shadow-[0_2px_4px_rgb(0_0_0/0.10),inset_0_1px_0_rgb(255_255_255/0.8)] outline-none transition-[scale,box-shadow,border-color] duration-150 ease-[ease] hover:scale-105 hover:border-[var(--border-hover,var(--border))] focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background data-dragging:z-20 data-dragging:scale-110 data-dragging:border-ring data-dragging:shadow-[0_3px_8px_color-mix(in_srgb,var(--primary)_22%,transparent)] data-disabled:cursor-not-allowed motion-reduce:transition-none"
>
{showTooltip && (
<span
aria-hidden
className="pointer-events-none absolute bottom-[calc(100%+9px)] left-1/2 flex h-7 min-w-8 -translate-x-1/2 items-center justify-center rounded-[8px] border border-border bg-popover px-2 text-xs leading-4 font-medium tracking-[0.15px] whitespace-nowrap text-foreground shadow-[shadow:var(--shadow-control,0_1px_2px_0_rgb(0_0_0/0.05))] transition-[translate,box-shadow] duration-150 ease-[ease] group-focus-within/thumb:-translate-y-0.5 group-focus-within/thumb:shadow-[shadow:var(--shadow-dropdown,0_1px_1px_0_rgb(0_0_0/0.04),0_4px_4px_0_rgb(0_0_0/0.02))] group-data-dragging/thumb:-translate-y-0.5 motion-reduce:transition-none"
>
<SliderPrimitive.Value>
{(formatted, values) =>
formatValue?.(values[index], index) ?? formatted[index]
}
</SliderPrimitive.Value>
<span
aria-hidden
className="absolute -bottom-[4.5px] left-1/2 size-2 -translate-x-1/2 rotate-45 border-r border-b border-border bg-popover"
/>
</span>
)}
<span
aria-hidden
className="size-2 rounded-full bg-primary bg-[image:var(--gradient-button-primary-default,linear-gradient(180deg,var(--primary),var(--primary)))] shadow-[inset_0_1px_0_rgb(255_255_255/0.24)] transition-[filter] duration-150 ease-[ease] group-focus-within/thumb:brightness-110 group-data-dragging/thumb:brightness-110 motion-reduce:transition-none"
/>
</SliderPrimitive.Thumb>
))}
</SliderPrimitive.Control>
</SliderPrimitive.Root>
);
}
export { Slider }; On this page