iOS slider
A native range input with a quiet track, pill thumb and synchronized stepped values.
Preview
In action
When to use
Use it for
- A bounded numeric level such as volume, brightness or playback intensity.
- Provide min, max and step when the range is discrete.
Not for
- Values that need precise text entry without an accompanying numeric field.
- Multiple independent values; use separate labeled sliders.
Install
Three ways in. They share one source, so the pixels match whichever you pick.
1. Import the package
npm install @noorddev/vlak-react
// once, next to your app's root
import "@noorddev/vlak-react/css";
import { IOSSlider } from "@noorddev/vlak-react";Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/ios-slider.
2. Vendor the source
npx @noorddev/vlak-cli add ios-slider
The StyleX leaf lands in components/vlak/, for your own compiler to own. See StyleX.
3. Through shadcn
npx shadcn add https://vlak.dev/r/ios-slider.json
The same registry item, installed by shadcn's CLI.
CSS only
<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />
No React. Link vlak.css and use the markup and classes below.
React
import { IOSSlider } from "@noorddev/vlak-react";
<IOSSlider name="volume" aria-label="Volume" min={0} max={100} defaultValue={40} onValueChange={value => console.log(value)} />Props
IOSSlider
Native range keyboard and form behavior beneath the iOS pill thumb.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | ||
defaultValue | number | 50 | |
min | number | 0 | |
max | number | 100 | |
step | number | "any" | 1 | |
onValueChange | (value: number) => void |
Also accepts Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "value" | "defaultValue" | "min" | "max" | "step" | "children">.
Keyboard
| Keys | Does |
|---|---|
| Tab, Shift+Tab | Moves focus to or away from the native range input. |
| Arrows, Home, End | Uses the browser’s native range stepping and boundary behavior. |
Accessibility
- The ref reaches the native range input, with min, max, step, name and disabled attributes.
- Value and fill are normalized to the same valid step. The invisible native input keeps a 44px target.
Markup
<div class="rs-ios-slider"><span class="rs-ios-slider-track" aria-hidden="true"><span class="rs-ios-slider-fill" style="width:50%"></span><span class="rs-ios-slider-thumb" style="inset-inline-start:50%"></span></span><input class="rs-ios-slider-input" type="range" min="0" max="100" value="50" aria-label="Volume" /></div>
Classes
.rs-ios-slider.rs-ios-slider-disabled.rs-ios-slider-track.rs-ios-slider-fill.rs-ios-slider-thumb.rs-ios-slider-input