Component
Slider
A 6px lilac-gray track filled purple to the value, with the switch's white knob.
npx -y github:anwarlemu/inkbox-brand-cli#release add slider250 emails
9:00 to 17:00
Usage
Use to pick an approximate value in a range where the exact number matters less than its position (a daily send limit, a retry delay, a storage quota). Show the current value next to its label. Pass two values for a range.
Avoid
- A slider for exact numbers (use Input)
- A thick or colored knob
- Ticks on every step
Exports: Slider. This component is a client component.
Dependencies: radix-ui.
Example
"use client";import * as React from "react";import { Label } from "@/components/ui/label";import { Slider } from "@/components/ui/slider";export function Preview() { const [limit, setLimit] = React.useState([250]); return ( <div className="grid w-full max-w-100 gap-3"> <div className="flex items-center justify-between"> <Label id="limit-label">Daily send limit</Label> <span className="text-body text-fg-muted">{limit[0]} emails</span> </div> <Slider aria-labelledby="limit-label" value={limit} onValueChange={setLimit} max={1000} step={50} /> </div> );}export function Range() { const [hours, setHours] = React.useState([9, 17]); return ( <div className="grid w-full max-w-100 gap-3"> <div className="flex items-center justify-between"> <Label id="hours-label">Calling hours</Label> <span className="text-body text-fg-muted"> {hours[0]}:00 to {hours[1]}:00 </span> </div> <Slider aria-labelledby="hours-label" value={hours} onValueChange={setHours} min={0} max={24} step={1} minStepsBetweenThumbs={1} /> </div> );}export function States() { return ( <div className="grid w-full max-w-100 gap-6"> <Slider aria-label="Disabled" defaultValue={[40]} disabled /> <div className="flex h-40 gap-8"> <Slider aria-label="Vertical" defaultValue={[60]} orientation="vertical" /> <Slider aria-label="Vertical range" defaultValue={[20, 70]} orientation="vertical" /> </div> </div> );}Source
"use client";import * as React from "react";import { Slider as SliderPrimitive } from "radix-ui";import { cn } from "@/lib/utils";// Extrapolated from the console's switch (Figma "Toggle"): a 6px pill track in the field's lilac-gray, filled with the// action purple up to the value, and a 20px white knob with the switch knob's soft drop. Under the pointer or keyboard// focus the knob takes a soft purple halo; it never animates its position (it follows the pointer). Pass two values for// a range.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-40 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", className, )} {...props} > <SliderPrimitive.Track data-slot="slider-track" className="relative grow overflow-hidden rounded-pill bg-line-field 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} aria-label={props["aria-label"] ? undefined : values.length > 1 ? (index === 0 ? "Minimum" : "Maximum") : undefined} className="block size-5 shrink-0 cursor-grab rounded-pill bg-surface shadow-knob outline-none transition-[box-shadow] duration-150 ease-out hover:shadow-[var(--ds-shadow-knob),0_0_0_4px_var(--ds-color-ring-tint)] focus-visible:shadow-[var(--ds-shadow-knob),0_0_0_4px_var(--ds-color-ring-tint)] active:cursor-grabbing disabled:pointer-events-none motion-reduce:transition-none" /> ))} </SliderPrimitive.Root> );}export { Slider };Reference: Extrapolated from the Inkbox console (Figma 427:2715): the switch's knob and purple, the field's lilac-gray.