Primitives
Slider
Smooth: the thumb follows the pointer and settles on the step; clicks and keys glide. default, gradient, fat, stepped, glow, minimal; ranges, marks, vertical.
default · drag it: the thumb follows the pointer, the value snaps
gradient · a range
fat · the value inside the fill
stepped · a dot for every step
glow · for dark panels
minimal · a hairline; the dot grows when touched
marks with labels · showValue="always"
slider.tsx
"use client";
import { Slider } from "@waveinno/ui";
import { Car } from "lucide-react";
import * as React from "react";
export default function SliderDemo() {
const [hours, setHours] = React.useState([3]);
const [cap, setCap] = React.useState([65]);
return (
<div className="space-y-10">
<div className="grid gap-x-10 gap-y-9 md:grid-cols-2">
<div className="space-y-1">
<p className="text-[12px] text-muted">default · drag it: the thumb follows the pointer, the value snaps</p>
<Slider value={hours} onValueChange={setHours} min={1} max={24} aria-label="Hours" format={(v) => `${v} h · ৳${v * 30}`} />
</div>
<div className="space-y-1">
<p className="text-[12px] text-muted">gradient · a range</p>
<Slider variant="gradient" defaultValue={[200, 600]} min={0} max={1000} step={50} format={(v) => `৳${v}`} aria-label="Price range" />
</div>
<div className="space-y-2">
<p className="text-[12px] text-muted">fat · the value inside the fill</p>
<Slider variant="fat" value={cap} onValueChange={setCap} icon={<Car />} format={(v) => `${v}% full`} aria-label="Occupancy alert" />
</div>
<div className="space-y-1">
<p className="text-[12px] text-muted">stepped · a dot for every step</p>
<Slider variant="stepped" defaultValue={[4]} min={1} max={10} format={(v) => `${v} of 10`} aria-label="Priority" />
</div>
<div className="space-y-1 rounded-card bg-ink p-5 pt-9">
<p className="mb-2 text-[12px] text-white/60">glow · for dark panels</p>
<Slider variant="glow" defaultValue={[72]} format={(v) => `${v}%`} aria-label="Brightness" />
</div>
<div className="space-y-1 pt-4">
<p className="text-[12px] text-muted">minimal · a hairline; the dot grows when touched</p>
<Slider variant="minimal" defaultValue={[30]} aria-label="Volume" />
</div>
</div>
<div className="grid gap-x-10 gap-y-8 md:grid-cols-[1fr_auto]">
<div className="space-y-1">
<p className="text-[12px] text-muted">marks with labels · showValue="always"</p>
<Slider
showValue="always"
defaultValue={[60]}
min={0}
max={180}
step={15}
format={(v) => `${v} min`}
marks={[
{ value: 0, label: "0" },
{ value: 30, label: "Free" },
{ value: 60, label: "1 h" },
{ value: 120, label: "2 h" },
{ value: 180, label: "3 h" },
]}
aria-label="Grace period"
/>
</div>
<div className="flex h-44 items-stretch gap-6">
<Slider orientation="vertical" variant="gradient" defaultValue={[40]} aria-label="Level" />
<Slider orientation="vertical" defaultValue={[70]} aria-label="Level 2" />
</div>
</div>
</div>
);
}Import#
Everything comes from the package root. The example above uses:
your-component.tsx
import { Slider } from "@waveinno/ui";Props#
Read from the source of this version, so they match the code exactly.
<Slider>
src/components/ui/slider.tsx| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "gradient" | "fat" | "glow" | "stepped" | "minimal" | "default" | |
marks | { value: number; label?: React.ReactNode }[] | — | Ticks under the track. |
showValue | "active" | "always" | "never" | "active" | The value over the thumb: while used (default), always, or never. |
format | (value: number) => string | (v) => v.toLocaleString() | |
smooth | boolean | true | Follow the pointer between steps while dragging (default), or move in steps. |
icon | React.ReactNode | — | `fat` only: an icon at the start of the fill. |
Also takes Omit<React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>, "children">.
Install#
If the project does not have the package yet, add it, then follow the setup for Next.js or Vite once.
$ npm install @waveinno/ui