Slider
Slider lets users select a value or range by moving handles along a track.
Source
LLM docs
Package
Examples
9
Properties
87
Playground
Basics
Basic slider usage for selecting numeric values within a range.
Loading demo…
import { useState } from 'react';
import { Block, Slider } from '@plocks/ui';
export function Demo() {
const [value, setValue] = useState(25);
return (
<Block fullWidth>
<Slider accessibilityLabel="Volume" value={value} onChange={setValue} />
</Block>
);
}Slider variants
Loading demo…
import { Block, Slider } from '@plocks/ui';
const VARIANTS = ['default', 'filled', 'outline', 'minimal', 'segmented', 'unstyled'] as const;
export function Demo() {
return (
<Block fullWidth>
{VARIANTS.map((variant) => (
<Slider
key={variant}
label={variant}
variant={variant}
defaultValue={40}
step={5}
showTicks={variant === 'segmented'}
restrictToTicks={variant === 'segmented'}
/>
))}
</Block>
);
}Ticks and Marks
Slider with visible tick marks and labeled values for better precision.
Loading demo…
import { Block, Slider } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Slider
accessibilityLabel="Milestone"
defaultValue={50}
restrictToTicks
ticks={[
{ value: 0, label: 'Min' },
{ value: 25 },
{ value: 50, label: 'Mid' },
{ value: 75 },
{ value: 100, label: 'Max' },
]}
/>
</Block>
);
}Range Slider
RangeSlider puts two thumbs on one track and its value is a [min, max] tuple, for filters such as price ranges.Loading demo…
import { useState } from 'react';
import { Block, RangeSlider } from '@plocks/ui';
export function Demo() {
const [priceRange, setPriceRange] = useState<[number, number]>([25, 75]);
return (
<Block fullWidth>
<RangeSlider label="Price range" value={priceRange} onChange={setPriceRange} />
</Block>
);
}Value label customization
valueLabelPosition chooses where the thumb tooltip sits (top / bottom for horizontal, left / right for vertical). valueLabelOffset tunes the gap from the thumb. valueLabelProps accepts any <Text> props — ff, fw, size, c, style — and valueLabelStyle overrides the wrapper Card's style. Set valueLabelAsCard={false} for a flat tooltip with no Card chrome. Both <Slider> and <RangeSlider> accept the same set of props.Loading demo…
import { Block, Slider, RangeSlider, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Block>
<Text variant="small" c="secondary">Bottom</Text>
<Slider
accessibilityLabel="Value label below"
defaultValue={60}
valueLabelAlwaysOn
valueLabelPosition="bottom"
valueLabelOffset={2}
/>
</Block>
<Block>
<Text variant="small" c="secondary">Custom text</Text>
<Slider
accessibilityLabel="Custom label text"
defaultValue={72}
valueLabelAlwaysOn
valueLabelProps={{
ff: 'monospace',
fw: '700',
size: 'md',
c: 'primary',
}}
/>
</Block>
<Block>
<Text variant="small" c="secondary">Flat</Text>
<Slider
accessibilityLabel="Flat value label"
defaultValue={72}
valueLabelAlwaysOn
valueLabelAsCard={false}
valueLabelStyle={{
backgroundColor: 'rgba(15, 23, 42, 0.92)',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 6,
}}
valueLabelProps={{ ff: 'monospace', fw: '600', c: '#fff' }}
/>
</Block>
<Block>
<Text variant="small" c="secondary">RangeSlider</Text>
<RangeSlider
accessibilityLabel="Range with labels below"
defaultValue={[20, 80]}
valueLabelAlwaysOn
valueLabelPosition="bottom"
valueLabelProps={{ fw: '700', size: 'sm' }}
valueLabel={(v, i) => (i === 0 ? `min ${Math.round(v)}` : `max ${Math.round(v)}`)}
/>
</Block>
<Block direction="row" justify="center" gap="xl">
<Block align="center">
<Text variant="small" c="secondary">Left</Text>
<Block style={{ height: 200 }}>
<Slider
accessibilityLabel="Vertical, label left"
defaultValue={40}
orientation="vertical"
valueLabelAlwaysOn
valueLabelPosition="left"
valueLabelProps={{ fw: '700' }}
/>
</Block>
</Block>
<Block align="center">
<Text variant="small" c="secondary">Right</Text>
<Block style={{ height: 200 }}>
<Slider
accessibilityLabel="Vertical, label right"
defaultValue={60}
orientation="vertical"
valueLabelAlwaysOn
valueLabelPosition="right"
valueLabelProps={{ fw: '700' }}
/>
</Block>
</Block>
</Block>
</Block>
);
}Decimal steps & precision
The thumb tooltip formats its value from the
step: a fractional step like 0.01 shows two decimals, while an integer step rounds to a whole number (trailing zeros are trimmed, so 0.10 reads as 0.1). Pass precision to force a fixed number of decimals regardless of the step.Loading demo…
import { Block, Slider, Text } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Block>
<Text variant="small" c="secondary">step 0.01</Text>
<Slider
accessibilityLabel="Position"
defaultValue={0.25}
max={1}
step={0.01}
valueLabelAlwaysOn
/>
</Block>
<Block>
<Text variant="small" c="secondary">step 0.5</Text>
<Slider
accessibilityLabel="Temperature"
defaultValue={21.5}
min={16}
max={30}
step={0.5}
valueLabelAlwaysOn
/>
</Block>
<Block>
<Text variant="small" c="secondary">precision 2</Text>
<Slider
accessibilityLabel="Ratio"
defaultValue={0.5}
max={1}
step={0.1}
precision={2}
valueLabelAlwaysOn
/>
</Block>
</Block>
);
}Slot styling
Each visual layer of the slider is independently customizable:
trackStyle and activeTrackStyle for the track halves, thumbStyle for the handle, tickStyle / activeTickStyle for tick marks, and tickLabelProps for tick labels. Per-tick style overrides on individual ticks[i].style win over the global tick styles. Combined with the value-label slot props (valueLabelStyle, valueLabelProps) you can fully reskin the slider without forking it.Loading demo…
import { Block, Slider, RangeSlider, Text } from '@plocks/ui';
const milestoneTicks = [
{ value: 0, label: '0' },
{ value: 25, label: '25' },
{ value: 50, label: '50' },
{ value: 75, label: '75' },
{ value: 100, label: '100' },
];
const milestoneTicksWithHighlight = milestoneTicks.map((t) =>
t.value === 50
? {
...t,
style: {
width: 4,
height: 14,
backgroundColor: '#facc15',
borderRadius: 2,
top: 11,
},
}
: t,
);
export function Demo() {
return (
<Block fullWidth>
<Block>
<Text variant="small" c="secondary">Track and thumb</Text>
<Slider
accessibilityLabel="Track and thumb overrides"
defaultValue={35}
trackStyle={{ height: 10, borderRadius: 2 }}
activeTrackStyle={{ height: 10, borderRadius: 2 }}
thumbStyle={{ borderRadius: 4, borderWidth: 0 }}
/>
</Block>
<Block>
<Text variant="small" c="secondary">Ticks and tick labels</Text>
<Slider
accessibilityLabel="Tick styling"
defaultValue={50}
ticks={milestoneTicks}
tickStyle={{ width: 3, height: 10, borderRadius: 1.5, top: 13 }}
activeTickStyle={{ width: 3, height: 12, borderRadius: 1.5, top: 12 }}
tickLabelProps={{ ff: 'monospace', size: 'xs', fw: '700' }}
/>
</Block>
<Block>
<Text variant="small" c="secondary">Per-tick style</Text>
<Slider
accessibilityLabel="Per-tick override"
defaultValue={50}
ticks={milestoneTicksWithHighlight}
tickStyle={{ width: 3, height: 10, borderRadius: 1.5, top: 13 }}
activeTickStyle={{ width: 3, height: 10, borderRadius: 1.5, top: 13 }}
tickLabelProps={{ size: 'xs' }}
/>
</Block>
<Block>
<Text variant="small" c="secondary">RangeSlider</Text>
<RangeSlider
accessibilityLabel="Range with slot styling"
defaultValue={[20, 80]}
ticks={milestoneTicks}
activeTrackColor="#a855f7"
trackStyle={{ height: 8, borderRadius: 4 }}
activeTrackStyle={{ height: 8, borderRadius: 4 }}
thumbStyle={{ backgroundColor: '#a855f7', borderColor: '#7e22ce', borderWidth: 2 }}
tickStyle={{ width: 2, height: 8, top: 14 }}
activeTickStyle={{ width: 2, height: 8, top: 14, backgroundColor: '#a855f7' }}
tickLabelProps={{ size: 'xs', c: 'muted' }}
valueLabelAlwaysOn
valueLabelProps={{ fw: '700', size: 'sm' }}
/>
</Block>
</Block>
);
}Vertical Orientation
Vertical slider orientation for space-efficient layouts and different use cases.
Loading demo…
import { Block, Slider } from '@plocks/ui';
export function Demo() {
return (
<Block style={{ height: 200 }}>
<Slider accessibilityLabel="Level" defaultValue={60} orientation="vertical" />
</Block>
);
}CustomStyles
Restyle the slider with
color, trackSize / thumbSize, and the trackStyle, activeTrackStyle, and thumbStyle overrides. RangeSlider accepts the same props.Loading demo…
import { Block, RangeSlider, Slider } from '@plocks/ui';
export function Demo() {
return (
<Block fullWidth>
<Slider
label="Success palette"
defaultValue={65}
color="success"
trackSize={12}
thumbSize={30}
trackStyle={{ opacity: 0.25 }}
activeTrackStyle={{
shadowColor: '#34C759',
shadowOpacity: 0.35,
shadowRadius: 8,
shadowOffset: { width: 0, height: 4 },
}}
thumbStyle={{ borderColor: '#1F5520', borderWidth: 3 }}
/>
<RangeSlider
label="Warning palette"
defaultValue={[20, 80]}
color="warning"
trackSize={10}
thumbSize={26}
trackStyle={{ opacity: 0.2 }}
activeTrackStyle={{ opacity: 0.55 }}
thumbStyle={{ borderColor: '#B45309', borderWidth: 2 }}
/>
</Block>
);
}React Native design for iOS, Android, and Web.
Quick Links
Resources