import { Slider } from '@cerberus/react'The Slider component is a controlled abstraction of the primitive slots to render a slider control.
The Slider component supports adding header content (such as a label) through its children. This content is rendered within an HStack that justifyContent is set to space-between.
In this example, we include the Slider.ValueText which displays the current value of the slider.
The Slider component supports different sizes through the size prop. The default size is lg.
You can control the style of the Slider by using the usage prop. The default usage is gradient.
You can customize the color palette of the Slider by using the palette prop. The default palette is action.
Note
Palettes are only customizable for non-gradient usages by nature of how CSS backgrounds work.
To create a range slider, set multiple values to the defaultValue prop.
Use the minStepsBetweenThumbs prop to avoid thumbs with the same value.
Use the thumbCollisionBehavior prop to control how thumbs interact when they collide. Options are "none" (default), "push", or "swap".
To display the value text of the slider, use the Slider.ValueText slot.
To disable the slider, use the disabled prop.
Use the step prop to define the step size of the slider which will create a discrete stop on value marker.
To display marks on the slider, use the marks prop.
To display the dragging indicator, use the showIndicator prop.
To display a vertical slider, use the orientation prop.
When you want to control the slider value programmatically, use the onValueChange in combination with the value prop.
An alternative way to control the Slider is to use the Provider component and the useSlider store hook.
This way you can access the slider state and methods from outside the slider.
Note
When using using the Provider component, you are opting out of the Slider abstraction which means you need to utilize the utility components mentioned in the Guides section.
Use the onValueChangeEnd prop to listen to the end of the slider change. This will fire when the user releases the slider thumb.
You can fully customize every slot layer of the Slider using style props.
This abstraction renders the following shortcuts internally to streamline development.
Slider.TrackThe Slider.Track and Slider.Range slots are used to render the track and range of the slider.
<SliderTrack>
<SliderRange />
</SliderTrack>Slider.ThumbsThe Slider.Thumb, Slider.DraggingIndicator, and Slider.HiddenInput slots are used to render the thumb of the slider.
<SliderThumb>
<SliderDraggingIndicator />
<SliderHiddenInput />
</SliderThumb>If you want to render a range of thumbs, we also provide the Slider.Thumbs slot.
<Slider.Thumbs values={[25, 50]} />Slider.MarksThe Slider.MarkerGroup and Slider.Marker slots are used to render the mark of the slider.
<SliderMarkerGroup>
<SliderMarker />
</SliderMarkerGroup>If you want to render a couple of marks, we also provide the Slider.Marks slot.
<Slider.Marks values={[0, 25, 50, 75, 100]} />To help streamline custom styling, the slider uses a set of CSS variables that you can override:
'--slider-thumb-size': '1.5rem' // size of the thumb
'--slider-track-size': '0.5rem' // height of the track
'--slider-marker-center': '9px' // the center position of the track
'--slider-marker-size': '0.06rem' // size of the marker
'--slider-marker-inset': '3px' // distance from the track edge to the marker
'--slider-dragging-indicator-offset': '-2rem' // The gap between the thumb and the dragging indicatorThe Slider exposes the following primitive slots:
| Component | Description |
|---|---|
Provider | The Provider context to use in place of the Root for the hook-based store solution. |
Root | The root element of the slider. |
Label | The label element of the slider. |
ValueText | The value text element of the slider. |
Control | The control element of the slider. |
Track | The track element of the slider. |
Range | The range element of the slider. |
Thumb | The thumb element of the slider. |
Thumbs | An abstraction of the Thumb and DraggingIndicator elements of the slider. |
DraggingIndicator | The dragging indicator element of the slider. |
MarkerGroup | The marker group element of the slider. |
Marker | The marker element of the slider. |
MarkerIndicator | The marker indicator element of the slider. |
Marks | An abstraction of the Marker elements of the slider. |
HiddenInput | The hidden input element of the slider. |
| Prop | Type | Required | Description |
|---|---|---|---|
aria-label | string[] | No | The aria-label of each slider thumb. Useful for providing an accessible name to the slider |
aria-labelledby | string[] | No | The id of the elements that labels each slider thumb. Useful for providing an accessible name to the slider |
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
defaultValue | number[] | No | The initial value of the slider when rendered.Use when you don't need to control the value of the slider. |
disabled | boolean | No | Whether the slider is disabled |
form | string | No | The associate form of the underlying input element. |
getAriaValueText | (details: ValueTextDetails) => string | No | Function that returns a human readable value for the slider thumb |
id | string | No | The unique identifier of the machine. |
ids | Partial<Slots> | No | The ids of the elements in the slider. Useful for composition. |
invalid | boolean | No | Whether the slider is invalid |
max | number | No | The maximum value of the slider |
min | number | No | The minimum value of the slider |
minStepsBetweenThumbs | number | No | The minimum permitted steps between multiple thumbs. minStepsBetweenThumbs * step should reflect the gap between the thumbs. step: 1 and minStepsBetweenThumbs: 10 => gap is 10 |
name | string | No | The name associated with each slider thumb (when used in a form) |
onFocusChange | (details: FocusChangeDetails) => void | No | Function invoked when the slider's focused index changes |
onValueChange | (details: ValueChangeDetails) => void | No | Function invoked when the value of the slider changes |
onValueChangeEnd | (details: ValueChangeDetails) => void | No | Function invoked when the slider value change is done |
orientation | 'horizontal' | 'vertical' | No | The orientation of the slider |
origin | 'center' | 'start' | 'end' | No | The origin of the slider range. The track is filled from the origin to the thumb for single values. |
readOnly | boolean | No | Whether the slider is read-only |
step | number | No | The step value of the slider |
thumbAlignment | 'center' | 'contain' | No | The alignment of the slider thumb relative to the track |
thumbCollisionBehavior | 'none' | 'push' | 'swap' | No | Controls how thumbs behave when they collide during pointer interactions. |
thumbSize | { width: number; height: number } | No | The slider thumbs dimensions |
value | number[] | No | The controlled value of the slider |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | root |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the slider |
[data-dragging] | Present when in the dragging state |
[data-invalid] | Present when invalid |
[data-focus] | Present when focused |
| Variable | Description |
|---|---|
--slider-thumb-width | The thumb width of the slider |
--slider-thumb-height | The thumb height of the slider |
--slider-thumb-transform | The thumb transform of the slider |
--slider-range-start | The range start of the slider |
--slider-range-end | The range end of the slider |
--translate-x | The horizontal translation value |
--translate-y | The vertical translation value |
| Prop | Type | Required | Description |
|---|---|---|---|
value | UseSliderReturn | Yes | |
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | control |
[data-dragging] | Present when in the dragging state |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the control |
[data-invalid] | Present when invalid |
[data-focus] | Present when focused |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | dragging-indicator |
[data-orientation] | The orientation of the draggingindicator |
[data-state] | "open" | "closed" |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | label |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the label |
[data-invalid] | Present when invalid |
[data-dragging] | Present when in the dragging state |
[data-focus] | Present when focused |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | marker-group |
[data-orientation] | The orientation of the markergroup |
| Prop | Type | Required | Description |
|---|---|---|---|
value | number | Yes | |
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | marker |
[data-orientation] | The orientation of the marker |
[data-value] | The value of the item |
[data-disabled] | Present when disabled |
[data-state] |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | range |
[data-dragging] | Present when in the dragging state |
[data-focus] | Present when focused |
[data-invalid] | Present when invalid |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the range |
| Prop | Type | Required | Description |
|---|---|---|---|
index | number | Yes | |
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
name | string | No |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | thumb |
[data-index] | The index of the item |
[data-name] | |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the thumb |
[data-focus] | Present when focused |
[data-dragging] | Present when in the dragging state |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | track |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-dragging] | Present when in the dragging state |
[data-orientation] | The orientation of the track |
[data-focus] | Present when focused |
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | value-text |
[data-disabled] | Present when disabled |
[data-orientation] | The orientation of the valuetext |
[data-invalid] | Present when invalid |
[data-focus] | Present when focused |
On this page
Loading...
Loading...
Loading...
Loading...
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function BasicDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30]} />
</HStack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function RangeDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30, 80]} />
</HStack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function OverlapDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30, 80]} minStepsBetweenThumbs={15} />
</HStack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function StepsDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30]} step={10} />
</HStack>
)
}
0'use client'
import { HStack, Stack } from '@/styled-system/jsx'
import { cerberus, Slider, Text } from '@cerberus/react'
import { useSignal } from '@cerberus/signals'
export function ControlledDemo() {
const [value, setValue] = useSignal<Array<number>>([0])
return (
<Stack gap="xl" w="3/4">
<Slider onValueChange={(details) => setValue(details.value)} value={value}>
<Slider.Label>Controlled</Slider.Label>
<Slider.ValueText />
</Slider>
<HStack gap="sm" w="full">
<Text as="small" textStyle="body-sm">
Value:{' '}
</Text>
<cerberus.code textStyle="mono-sm">{value}</cerberus.code>
</HStack>
</Stack>
)
}
40'use client'
import { HStack, Stack } from '@/styled-system/jsx'
import { cerberus, Slider, Text, useSlider } from '@cerberus/react'
export function StoreDemo() {
const slider = useSlider({
defaultValue: [40],
thumbAlignment: 'center',
})
return (
<Stack gap="xl" w="3/4">
<Slider.Provider direction="horizontal" value={slider}>
<HStack justify="space-between" w="full">
<Slider.Label>Slider Store</Slider.Label>
<Slider.ValueText />
</HStack>
<Slider.Control direction="horizontal">
<Slider.Track direction="horizontal">
<Slider.Range direction="horizontal" />
</Slider.Track>
<Slider.Thumbs direction="horizontal" value={slider.value} />
</Slider.Control>
</Slider.Provider>
<HStack gap="sm" w="full">
<Text as="small" textStyle="body-sm">
Value:{' '}
</Text>
<cerberus.code textStyle="mono-sm">{slider.value}</cerberus.code>
</HStack>
</Stack>
)
}
00'use client'
import { HStack, Stack } from '@/styled-system/jsx'
import { cerberus, Slider, Text } from '@cerberus/react'
import { useSignal } from '@cerberus/signals'
export function ChangeEndDemo() {
const [value, setValue] = useSignal<Array<number>>([0])
const [endVal, setEndVal] = useSignal<Array<number>>([0])
return (
<Stack gap="xl" w="3/4">
<Slider
onValueChange={(details) => setValue(details.value)}
onValueChangeEnd={(details) => setEndVal(details.value)}
value={value}
>
<Slider.Label>Controlled</Slider.Label>
<Slider.ValueText />
</Slider>
<Stack gap="sm">
<HStack gap="sm" w="full">
<Text as="small" textStyle="body-sm">
Value:{' '}
</Text>
<cerberus.code textStyle="mono-sm">{value}</cerberus.code>
</HStack>
<HStack gap="sm" w="full">
<Text as="small" textStyle="body-sm">
End Value:{' '}
</Text>
<cerberus.code textStyle="mono-sm">{endVal[0]}</cerberus.code>
</HStack>
</Stack>
</Stack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function LabelDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30]}>
<Slider.Label>Amount of Corn</Slider.Label>
<Slider.ValueText />
</Slider>
</HStack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function LabelDemo() {
return (
<HStack w="3/4">
<Slider defaultValue={[30]}>
<Slider.Label>Amount of Corn</Slider.Label>
<Slider.ValueText />
</Slider>
</HStack>
)
}
import { Stack } from '@/styled-system/jsx'
import { For, Slider, SliderProps } from '@cerberus/react'
import recipesSpec from 'styled-system/specs/recipes.json'
import { getSacredNumber } from './utils'
const sizes = (recipesSpec.data.find((r) => r.name === 'slider')?.variants.size ??
[]) as SliderProps['size'][]
export function SizesDemo() {
return (
<Stack gap="md" w="3/4">
<For each={sizes}>
{(size, idx) => (
<Slider key={String(size)} defaultValue={[getSacredNumber(idx)]} size={size}>
<Slider.Label>Slider - {size} </Slider.Label>
</Slider>
)}
</For>
</Stack>
)
}
import { Stack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function CollisionDemo() {
return (
<Stack gap="lg" w="3/4">
<Slider defaultValue={[30, 80]} thumbCollisionBehavior="none">
<Slider.Label>None</Slider.Label>
</Slider>
<Slider defaultValue={[30, 80]} thumbCollisionBehavior="push">
<Slider.Label>Push</Slider.Label>
</Slider>
<Slider defaultValue={[30, 80]} thumbCollisionBehavior="swap">
<Slider.Label>Swap</Slider.Label>
</Slider>
</Stack>
)
}
import { Stack } from '@/styled-system/jsx'
import { For, Slider, SliderProps } from '@cerberus/react'
import recipesSpec from 'styled-system/specs/recipes.json'
import { getSacredNumber } from './utils'
const palettes = (recipesSpec.data.find((r) => r.name === 'slider')?.variants.palette ??
[]) as SliderProps['palette'][]
export function PaletteDemo() {
return (
<Stack gap="md" w="3/4">
<For each={palettes}>
{(palette, idx) => (
<Slider
key={String(palette)}
defaultValue={[getSacredNumber(idx)]}
palette={palette}
usage="outlined"
>
<Slider.Label>Slider - {palette} </Slider.Label>
</Slider>
)}
</For>
</Stack>
)
}
import { Stack } from '@/styled-system/jsx'
import { For, Slider, SliderProps } from '@cerberus/react'
import recipesSpec from 'styled-system/specs/recipes.json'
import { getSacredNumber } from './utils'
const variants = (recipesSpec.data.find((r) => r.name === 'slider')?.variants.usage ??
[]) as SliderProps['usage'][]
export function DisabledDemo() {
return (
<Stack gap="md" w="3/4">
<For each={variants}>
{(usage, idx) => (
<Slider
key={String(usage)}
disabled
defaultValue={[getSacredNumber(idx)]}
size={usage === 'filled' ? 'sm' : 'lg'}
usage={usage}
>
<Slider.Label>Slider - {usage} </Slider.Label>
</Slider>
)}
</For>
</Stack>
)
}
import { Stack } from '@/styled-system/jsx'
import { Corn } from '@carbon/icons-react'
import { Slider } from '@cerberus/react'
export function MarksDemo() {
return (
<Stack gap="lg" w="3/4">
<Slider defaultValue={[0]} marks={[25, 50, 75]} step={25}>
<Slider.Label>With numbers</Slider.Label>
</Slider>
<Slider
defaultValue={[0]}
marks={[
{ value: 25, label: '25%' },
{ value: 50, label: '50%' },
{ value: 75, label: '75%' },
]}
>
<Slider.Label>With custom labels</Slider.Label>
</Slider>
<Slider
defaultValue={[0]}
marks={[
{ value: 25, label: <Corn /> },
{ value: 50, label: <Corn /> },
{ value: 75, label: <Corn /> },
]}
>
<Slider.Label>With Corn</Slider.Label>
</Slider>
<Slider defaultValue={[0]} marks={[25, 50, 75]} usage="filled" size="sm">
<Slider.Label>Filled small size</Slider.Label>
</Slider>
<Slider defaultValue={[0]} marks={[25, 50, 75]} usage="outlined" size="md">
<Slider.Label>Outlined medium size</Slider.Label>
</Slider>
</Stack>
)
}
import { HStack } from '@/styled-system/jsx'
import { Slider } from '@cerberus/react'
export function DraggingIndicatorDemo() {
return (
<HStack gap="4xl" justify="center" w="3/4">
<Slider defaultValue={[30]} marks={[0, 25, 50, 75, 100]} showIndicator />
<Slider
defaultValue={[30]}
marks={[0, 25, 50, 75, 100]}
orientation="vertical"
showIndicator
height="200px"
/>
</HStack>
)
}
import { HStack, VStack } from '@/styled-system/jsx'
import { VolumeMute } from '@carbon/icons-react'
import { Slider } from '@cerberus/react'
export function VerticalDemo() {
return (
<HStack gap="4xl" justify="center" w="3/4">
<Slider defaultValue={[30]} height="200px" orientation="vertical" />
<VStack gap="md">
<Slider defaultValue={[0]} height="168px" orientation="vertical" />
<VolumeMute />
</VStack>
<Slider
defaultValue={[30]}
marks={[0, 25, 50, 75, 100]}
orientation="vertical"
height="200px"
/>
</HStack>
)
}
import { Stack } from '@/styled-system/jsx'
import { For, Slider, SliderProps } from '@cerberus/react'
import recipesSpec from 'styled-system/specs/recipes.json'
import { getSacredNumber } from './utils'
const variants = (recipesSpec.data.find((r) => r.name === 'slider')?.variants.usage ??
[]) as SliderProps['usage'][]
export function UsageDemo() {
return (
<Stack gap="md" w="3/4">
<For each={variants}>
{(usage, idx) => (
<Slider
key={String(usage)}
defaultValue={[getSacredNumber(idx)]}
size={usage === 'filled' ? 'sm' : 'lg'}
usage={usage}
>
<Slider.Label>Slider - {usage} </Slider.Label>
</Slider>
)}
</For>
</Stack>
)
}
On this page