Slider
macOS 26 slider — a capsule rail with an accent range and a frosted-white pill knob, in standard & center-biased variants, with optional tick marks.
The macOS 26 slider, aligned onto the Radix Slider primitive: a capsule
translucent rail, an accent-blue filled range, and a soft frosted-white pill
knob. Geometry (track height, knob pill, capsule radii) is lifted from the Apple
macOS 26 UI Kit "Sliders and Dials" page; colors flip light/dark via the Acrylic
theme tokens. The kit's two orthogonal axes are exposed as props — variant
(fill origin) and marks (the Ticked add-on) — and compose with five sizes,
single/range values, and both orientations.
Installation
npx shadcn add https://acrylic-ui.vercel.app/r/slider.jsonUsage
"use client"import { Slider } from "@/registry/acrylic/slider"// A basic single-value slider — a volume control at a sensible width.export default function SliderDemo() { return ( <div className="flex w-full max-w-xs flex-col gap-2 text-foreground"> <label className="text-[13px] text-muted-foreground">Volume</label> <Slider defaultValue={[60]} max={100} step={1} aria-label="Volume" /> </div> )}import { Slider } from "@/components/acrylic/slider"
<Slider defaultValue={[60]} max={100} step={1} />Variants
The kit's Sliders family is two orthogonal axes: fill origin
(standard vs center) × ticked (the marks add-on). All four combinations:
"use client"import { Slider } from "@/registry/acrylic/slider"// The four linear variants from the kit's "Sliders" family: Standard vs// Center-biased (fill origin) × plain vs Ticked (the marks add-on).export default function SliderVariants() { return ( <div className="flex w-full max-w-sm flex-col gap-7 text-foreground"> <div className="flex flex-col gap-2"> <label className="text-[13px] text-muted-foreground">Standard</label> <Slider defaultValue={[60]} max={100} step={1} aria-label="Standard" /> </div> <div className="flex flex-col gap-2"> <label className="text-[13px] text-muted-foreground">Standard + Ticked</label> <Slider defaultValue={[50]} max={100} step={12.5} marks aria-label="Standard ticked" /> </div> <div className="flex flex-col gap-2"> <label className="text-[13px] text-muted-foreground">Center-biased (−100…100)</label> <Slider variant="center" defaultValue={[35]} min={-100} max={100} step={1} aria-label="Center-biased" /> </div> <div className="flex flex-col gap-2"> <label className="text-[13px] text-muted-foreground">Center-biased + Ticked</label> <Slider variant="center" defaultValue={[-40]} min={-100} max={100} step={25} marks aria-label="Center-biased ticked" /> </div> </div> )}| variant | kit name | fill | use for |
|---|---|---|---|
standard | Standard | from the start edge to the thumb | one-directional values (volume, opacity) |
center | Center-biased | from the track midpoint to the thumb | bipolar values (balance/pan, EQ, −100…+100) |
<Slider variant="center" min={-100} max={100} defaultValue={[0]} /> {/* center-biased */}
<Slider marks defaultValue={[50]} step={12.5} /> {/* ticked */}
<Slider marks={[0, 25, 50, 75, 100]} defaultValue={[50]} /> {/* explicit marks */}Sizes
Five control sizes (kit 1 Mn … 5 XL). The track is 4px for mini/small
and 6px for medium/large/xl; the pill knob grows 16×12 → 24×20.
"use client"import { Slider } from "@/registry/acrylic/slider"// All five control sizes (kit 1 Mn … 5 XL). Track is 4px for mini/small and 6px// for medium/large/xl; the pill knob grows 16×12 → 24×20.const sizes = ["mini", "small", "medium", "large", "xl"] as constexport default function SliderSizes() { return ( <div className="flex w-full max-w-sm flex-col gap-6 text-foreground"> {sizes.map((size) => ( <div key={size} className="flex flex-col gap-2"> <label className="text-[13px] capitalize text-muted-foreground">{size}</label> <Slider size={size} defaultValue={[50]} max={100} step={1} aria-label={size} /> </div> ))} </div> )}mini · small · medium (default) · large · xl.
Examples
Volume, a bipolar balance (center-biased), a ticked brightness scale, a two-thumb price range, plus vertical and disabled — each with a live readout.
"use client"import * as React from "react"import { Slider } from "@/registry/acrylic/slider"// Real-world settings: a volume control, a bipolar balance (center-biased), a// ticked brightness scale, a two-thumb price range, plus vertical and disabled —// each with a live value readout. Geometry matches the macOS 26 Sliders page.export default function SliderShowcase() { const [volume, setVolume] = React.useState([65]) const [balance, setBalance] = React.useState([0]) const [brightness, setBrightness] = React.useState([60]) const [range, setRange] = React.useState([30, 70]) const row = "flex flex-col gap-2" const head = "flex items-center justify-between text-[13px]" return ( <div className="flex w-full max-w-sm flex-col gap-7 text-foreground"> <div className={row}> <div className={head}> <span className="text-muted-foreground">Volume</span> <span className="tabular-nums text-foreground">{volume[0]}%</span> </div> <Slider value={volume} onValueChange={setVolume} max={100} step={1} aria-label="Volume" /> </div> <div className={row}> <div className={head}> <span className="text-muted-foreground">Balance</span> <span className="tabular-nums text-foreground"> {balance[0] === 0 ? "Center" : `${balance[0] > 0 ? "R" : "L"} ${Math.abs(balance[0])}`} </span> </div> <Slider variant="center" value={balance} onValueChange={setBalance} min={-100} max={100} step={1} aria-label="Balance" /> </div> <div className={row}> <div className={head}> <span className="text-muted-foreground">Brightness</span> <span className="tabular-nums text-foreground">{brightness[0]}</span> </div> <Slider value={brightness} onValueChange={setBrightness} max={100} step={20} marks aria-label="Brightness" /> </div> <div className={row}> <div className={head}> <span className="text-muted-foreground">Price range</span> <span className="tabular-nums text-foreground"> ${range[0]} – ${range[1]} </span> </div> <Slider value={range} onValueChange={setRange} max={100} step={1} aria-label="Price range" /> </div> <div className="flex items-end gap-10"> <div className="flex flex-col items-center gap-2"> <Slider orientation="vertical" defaultValue={[40]} max={100} step={1} className="min-h-40" aria-label="Vertical" /> <span className="text-[13px] text-muted-foreground">Vertical</span> </div> <div className="flex flex-col items-center gap-2"> <Slider orientation="vertical" defaultValue={[70]} max={100} step={25} marks className="min-h-40" aria-label="Vertical ticked" /> <span className="text-[13px] text-muted-foreground">Vertical + ticks</span> </div> <div className="flex flex-1 flex-col gap-2"> <label className="text-[13px] text-muted-foreground">Disabled</label> <Slider defaultValue={[45]} max={100} step={1} disabled aria-label="Disabled" /> </div> </div> </div> )}Notes
- Track (rail): capsule,
6pxtall (kit medium/large/xl; mini/small are4px), filled with--acr-chip— the kit's translucent black/white rail (≈6% in the kit), so it flips light/dark for free. - Range (filled): capsule,
bg-primary— the kit's#0088FFaccent (dark#0091FF) maps exactly onto--primary. Forvariant="center"the range fills from the track midpoint toward the thumb instead of from the start edge. - Thumb (knob): frosted-white pill (
--acr-control) with a hairline border (--acr-control-border) and a soft ambient shadow, mirroring the kit's rounded pill knob (16×12 / 18×14 / 20×16 / 24×20, radius = height/2; the long axis runs perpendicular to the track, so it swaps on vertical sliders). Focus shows an accent ring (ring-ring/25); disabled dims to 50%. - Marks (Ticked): the kit's "linear slider with ticks" add-on — small
2×2capsule dots atforeground/25laid under the track.marksacceptstrue(derive positions fromstep, capped at 40, else 9 even dots) or an explicit array of values. - Over-glass: the kit also ships an "Over-glass" material set for sliders placed on a glass surface — its tokens are identical to the standard set, so it is not a separate variant here.
- Props:
defaultValue,value,min(0),max(100),step(1),onValueChange,variant(standard|center),marks(boolean | number[]),size(mini·small·medium·large·xl),orientation(horizontal|vertical), anddisabled. Pass an array with two entries to get a range slider.
<Slider defaultValue={[25, 75]} max={100} step={1} /> {/* range */}
<Slider variant="center" min={-100} max={100} marks step={25} /> {/* center + ticks */}
<Slider defaultValue={[40]} orientation="vertical" /> {/* vertical */}