Slider
A control element that allows for a range of selections.
Anatomy
To set up the slider correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-partattribute to help identify them in the DOM.
Examples
Learn how to use the Slider component in your project. Let's take a look at the most basic example:
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const Basic = () => {
return (
<Slider.Root className={styles.Root} defaultValue={[40]}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const Basic = () => {
return (
<Slider.Root class={styles.Root} defaultValue={[40]}>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root :class="styles.Root" :default-value="[40]">
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root class={styles.Root} defaultValue={[40]}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Range Slider
You can add multiple thumbs to the slider by adding multiple Slider.Thumb
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const Range = () => {
return (
<Slider.Root defaultValue={[30, 60]} className={styles.Root}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
<Slider.Thumb index={1} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const Range = () => {
return (
<Slider.Root defaultValue={[30, 60]} class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
<Slider.Thumb index={1} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root :default-value="[30, 60]" :class="styles.Root">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
<Slider.Thumb :index="1" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root defaultValue={[30, 60]} class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
<Slider.Thumb index={1} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Adding marks
You can add marks to the slider track by using the Slider.MarkerGroup and Slider.Marker components.
Position the Slider.Marker components relative to the track by providing the value prop.
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const WithMarks = () => {
return (
<Slider.Root className={styles.Root} defaultValue={[50]}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
<Slider.MarkerGroup className={styles.MarkerGroup}>
{[0, 25, 50, 75, 100].map((value) => (
<Slider.Marker key={value} value={value} className={styles.Marker}>
{value}
</Slider.Marker>
))}
</Slider.MarkerGroup>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import { For } from 'solid-js'
import styles from 'styles/slider.module.css'
export const WithMarks = () => {
return (
<Slider.Root class={styles.Root} defaultValue={[50]}>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
<Slider.MarkerGroup class={styles.MarkerGroup}>
<For each={[0, 25, 50, 75, 100]}>
{(value) => (
<Slider.Marker value={value} class={styles.Marker}>
{value}
</Slider.Marker>
)}
</For>
</Slider.MarkerGroup>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
const marks = [0, 25, 50, 75, 100]
</script>
<template>
<Slider.Root :class="styles.Root" :default-value="[50]">
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
<Slider.MarkerGroup :class="styles.MarkerGroup">
<Slider.Marker v-for="value in marks" :key="value" :value="value" :class="styles.Marker">
{{ value }}
</Slider.Marker>
</Slider.MarkerGroup>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
const marks = [0, 25, 50, 75, 100]
</script>
<Slider.Root class={styles.Root} defaultValue={[50]}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
<Slider.MarkerGroup class={styles.MarkerGroup}>
{#each marks as value}
<Slider.Marker {value} class={styles.Marker}>{value}</Slider.Marker>
{/each}
</Slider.MarkerGroup>
</Slider.Root>
Specifying the minimum and maximum
By default, the minimum is 0 and the maximum is 100. If that's not what you want, you can easily specify different
bounds by changing the values of the min and/or max props.
For example, to ask the user for a value between -10 and 10, you can use:
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const MinMax = () => {
return (
<Slider.Root min={-10} max={10} defaultValue={[5]} className={styles.Root}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const MinMax = () => {
return (
<Slider.Root min={-10} max={10} defaultValue={[5]} class={styles.Root}>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root :min="-10" :max="10" :default-value="[5]" :class="styles.Root">
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root min={-10} max={10} defaultValue={[5]} class={styles.Root}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Setting the value's granularity
By default, the granularity, is 1, meaning that the value is always an integer. You can change the step attribute to
control the granularity.
For example, If you need a value between 5 and 10, accurate to two decimal places, you should set the value of step
to 0.01:
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const Step = () => {
return (
<Slider.Root step={0.01} min={5} max={10} defaultValue={[7.5]} className={styles.Root}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const Step = () => {
return (
<Slider.Root step={0.01} min={5} max={10} defaultValue={[7.5]} class={styles.Root}>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root :step="0.01" :min="5" :max="10" :default-value="[7.5]" :class="styles.Root">
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root step={0.01} min={5} max={10} defaultValue={[7.5]} class={styles.Root}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Listening for changes
When the slider value changes, the onValueChange and onValueChangeEnd callbacks are invoked. You can use this to set
up custom behaviors in your app.
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const OnEvent = () => {
return (
<Slider.Root
onValueChange={(details) => console.log('onValueChange', details.value)}
onValueChangeEnd={(details) => console.log('onValueChangeEnd', details.value)}
className={styles.Root}
>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const OnEvent = () => {
return (
<Slider.Root
onValueChange={(details) => console.log('onValueChange', details.value)}
onValueChangeEnd={(details) => console.log('onValueChangeEnd', details.value)}
class={styles.Root}
>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root
:class="styles.Root"
@value-change="(details) => console.log('onValueChange', details.value)"
@value-change-end="(details) => console.log('onValueChangeEnd', details.value)"
>
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider, type SliderValueChangeDetails } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
const handleValueChange = (details: SliderValueChangeDetails) => {
console.log('onValueChange', details.value)
}
const handleValueChangeEnd = (details: SliderValueChangeDetails) => {
console.log('onValueChangeEnd', details.value)
}
</script>
<Slider.Root class={styles.Root} onValueChange={handleValueChange} onValueChangeEnd={handleValueChangeEnd}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Changing the orientation
By default, the slider is assumed to be horizontal. To change the orientation to vertical, set the orientation property in the machine's context to vertical.
In this mode, the slider will use the arrow up and down keys to increment/decrement its value.
Don't forget to change the styles of the vertical slider by specifying its height
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const Vertical = () => {
return (
<Slider.Root orientation="vertical" className={styles.Root}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const Vertical = () => {
return (
<Slider.Root orientation="vertical" class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root orientation="vertical" :class="styles.Root">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root orientation="vertical" class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Changing the origin
By default, the slider's origin is at the start of the track. To change the origin to the center of the track, set the
origin prop to center.
import { Slider } from '@ark-ui/react/slider'
import styles from 'styles/slider.module.css'
export const CenterOrigin = () => {
return (
<Slider.Root origin="center" className={styles.Root} defaultValue={[75]}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
</div>
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
import { Slider } from '@ark-ui/solid/slider'
import styles from 'styles/slider.module.css'
export const CenterOrigin = () => {
return (
<Slider.Root origin="center" class={styles.Root} defaultValue={[75]}>
<div style={{ display: 'flex', 'justify-content': 'space-between' }}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
<script setup lang="ts">
import { Slider } from '@ark-ui/vue/slider'
import styles from 'styles/slider.module.css'
</script>
<template>
<Slider.Root origin="center" :class="styles.Root" :default-value="[75]">
<div :style="{ display: 'flex', justifyContent: 'space-between' }">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
</div>
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</template>
<script lang="ts">
import { Slider } from '@ark-ui/svelte/slider'
import styles from 'styles/slider.module.css'
</script>
<Slider.Root origin="center" class={styles.Root} defaultValue={[75]}>
<div style="display: flex; justify-content: space-between;">
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
</div>
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
Using the Root Provider
The RootProvider component provides a context for the slider. It accepts the value of the useSlider hook. You can
leverage it to access the component state and methods from outside the slider.
import { Slider, useSlider } from '@ark-ui/react/slider'
import button from 'styles/button.module.css'
import styles from 'styles/slider.module.css'
export const RootProvider = () => {
const slider = useSlider()
return (
<>
<button className={button.Root} onClick={() => slider.focus()}>
Focus
</button>
<Slider.RootProvider value={slider} className={styles.Root}>
<Slider.Label className={styles.Label}>Label</Slider.Label>
<Slider.ValueText className={styles.ValueText} />
<Slider.Control className={styles.Control}>
<Slider.Track className={styles.Track}>
<Slider.Range className={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} className={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.RootProvider>
</>
)
}
import { Slider, useSlider } from '@ark-ui/solid/slider'
import button from 'styles/button.module.css'
import styles from 'styles/slider.module.css'
export const RootProvider = () => {
const slider = useSlider()
return (
<>
<button class={button.Root} onClick={() => slider().focus()}>
Focus
</button>
<Slider.RootProvider value={slider} class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.RootProvider>
</>
)
}
<script setup lang="ts">
import { Slider, useSlider } from '@ark-ui/vue/slider'
import button from 'styles/button.module.css'
import styles from 'styles/slider.module.css'
const slider = useSlider()
</script>
<template>
<button :class="button.Root" @click="slider.focus()">Focus</button>
<Slider.RootProvider :value="slider" :class="styles.Root">
<Slider.Label :class="styles.Label">Label</Slider.Label>
<Slider.ValueText :class="styles.ValueText" />
<Slider.Control :class="styles.Control">
<Slider.Track :class="styles.Track">
<Slider.Range :class="styles.Range" />
</Slider.Track>
<Slider.Thumb :index="0" :class="styles.Thumb">
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.RootProvider>
</template>
<script lang="ts">
import { Slider, useSlider } from '@ark-ui/svelte/slider'
import button from 'styles/button.module.css'
import styles from 'styles/slider.module.css'
const id = $props.id()
const slider = useSlider({ id })
</script>
<button class={button.Root} onclick={() => slider().focus()}>Focus</button>
<Slider.RootProvider value={slider} class={styles.Root}>
<Slider.Label class={styles.Label}>Label</Slider.Label>
<Slider.ValueText class={styles.ValueText} />
<Slider.Control class={styles.Control}>
<Slider.Track class={styles.Track}>
<Slider.Range class={styles.Range} />
</Slider.Track>
<Slider.Thumb index={0} class={styles.Thumb}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.RootProvider>
If you're using the
RootProvidercomponent, you don't need to use theRootcomponent.
API Reference
Props
Root
| Prop | Default | Type |
|---|---|---|
aria-label | string[]The aria-label of each slider thumb. Useful for providing an accessible name to the slider | |
aria-labelledby | string[]The `id` of the elements that labels each slider thumb. Useful for providing an accessible name to the slider | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
defaultValue | number[]The initial value of the slider when rendered. Use when you don't need to control the value of the slider. | |
disabled | booleanWhether the slider is disabled | |
form | stringThe associate form of the underlying input element. | |
getAriaValueText | (details: ValueTextDetails) => stringFunction that returns a human readable value for the slider thumb | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
thumb: (index: number) => string
hiddenInput: (index: number) => string
control: string
track: string
range: string
label: string
valueText: string
marker: (index: number) => string
}>The ids of the elements in the slider. Useful for composition. | |
invalid | booleanWhether the slider is invalid | |
max | 100 | numberThe maximum value of the slider |
min | 0 | numberThe minimum value of the slider |
minStepsBetweenThumbs | 0 | numberThe minimum permitted steps between multiple thumbs. `minStepsBetweenThumbs` * `step` should reflect the gap between the thumbs. - `step: 1` and `minStepsBetweenThumbs: 10` => gap is `10` - `step: 10` and `minStepsBetweenThumbs: 2` => gap is `20` |
name | stringThe name associated with each slider thumb (when used in a form) | |
onFocusChange | (details: FocusChangeDetails) => voidFunction invoked when the slider's focused index changes | |
onValueChange | (details: ValueChangeDetails) => voidFunction invoked when the value of the slider changes | |
onValueChangeEnd | (details: ValueChangeDetails) => voidFunction invoked when the slider value change is done | |
orientation | 'horizontal' | 'horizontal' | 'vertical'The orientation of the slider |
origin | 'start' | 'center' | 'start' | 'end'The origin of the slider range. The track is filled from the origin to the thumb for single values. - "start": Useful when the value represents an absolute value - "center": Useful when the value represents an offset (relative) - "end": Useful when the value represents an offset from the end |
readOnly | booleanWhether the slider is read-only | |
step | 1 | numberThe step value of the slider |
thumbAlignment | 'contain' | 'center' | 'contain'The alignment of the slider thumb relative to the track - `center`: the thumb will extend beyond the bounds of the slider track. - `contain`: the thumb will be contained within the bounds of the track. |
thumbSize | { width: number; height: number }The slider thumbs dimensions | |
value | number[]The controlled value of the slider |
| CSS 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 |
| Data 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 |
Control
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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 |
DraggingIndicator
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | dragging-indicator |
[data-orientation] | The orientation of the draggingindicator |
[data-state] | "open" | "closed" |
HiddenInput
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Label
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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 |
MarkerGroup
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | slider |
[data-part] | marker-group |
[data-orientation] | The orientation of the markergroup |
Marker
| Prop | Default | Type |
|---|---|---|
value | number | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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] |
Range
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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 |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseSliderReturn | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Thumb
| Prop | Default | Type |
|---|---|---|
index | number | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
name | string |
| Data 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 |
Track
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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 |
ValueText
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data 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 |
Context
These are the properties available when using Slider.Context, useSliderContext hook or useSlider hook.
API
| Property | Type |
|---|---|
value | number[]The value of the slider. |
dragging | booleanWhether the slider is being dragged. |
focused | booleanWhether the slider is focused. |
setValue | (value: number[]) => voidFunction to set the value of the slider. |
getThumbValue | (index: number) => numberReturns the value of the thumb at the given index. |
setThumbValue | (index: number, value: number) => voidSets the value of the thumb at the given index. |
getValuePercent | (value: number) => numberReturns the percent of the thumb at the given index. |
getPercentValue | (percent: number) => numberReturns the value of the thumb at the given percent. |
getThumbPercent | (index: number) => numberReturns the percent of the thumb at the given index. |
setThumbPercent | (index: number, percent: number) => voidSets the percent of the thumb at the given index. |
getThumbMin | (index: number) => numberReturns the min value of the thumb at the given index. |
getThumbMax | (index: number) => numberReturns the max value of the thumb at the given index. |
increment | (index: number) => voidFunction to increment the value of the slider at the given index. |
decrement | (index: number) => voidFunction to decrement the value of the slider at the given index. |
focus | VoidFunctionFunction to focus the slider. This focuses the first thumb. |
Accessibility
Complies with the Slider WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
ArrowRight | Increments the slider based on defined step |
ArrowLeft | Decrements the slider based on defined step |
ArrowUp | Increases the value by the step amount. |
ArrowDown | Decreases the value by the step amount. |
PageUp | Increases the value by a larger step |
PageDown | Decreases the value by a larger step |
Shift + ArrowUp | Increases the value by a larger step |
Shift + ArrowDown | Decreases the value by a larger step |
Home | Sets the value to its minimum. |
End | Sets the value to its maximum. |