Slider
Used to allow users to make selections from a range of values.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root width="200px" defaultValue={[40]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Usage
import { Slider } from "@chakra-ui/react"<Slider.Root>
<Slider.Label />
<Slider.ValueText />
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumb>
<Slider.DraggingIndicator />
<Slider.HiddenInput />
</Slider.Thumb>
<Slider.MarkerGroup>
<Slider.Marker />
</Slider.MarkerGroup>
</Slider.Control>
</Slider.Root>Shortcuts
Slider.Thumbs
This component renders the Slider.Thumb and Slider.HiddenInput components
for each value.
The code below works:
<Slider.Thumb index={0}>
<Slider.HiddenInput />
</Slider.Thumb>but this might be better if you don't need to customize the thumb:
<Slider.Thumbs />Slider.Marks
This component renders the Slider.MarkerGroup and Slider.Marker components
for each value.
The code below works:
<Slider.MarkerGroup>
<Slider.Marker value={0} />
<Slider.Marker value={50} />
</Slider.MarkerGroup>but this might be better if you don't need to customize the marker:
<Slider.Marks marks={[0, 50]} />Examples
Sizes
Use the size prop to change the size of the slider.
import { For, Slider, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack width="200px" gap="4">
<For each={["sm", "md", "lg"]}>
{(size) => (
<Slider.Root defaultValue={[40]} size={size} key={size}>
<Slider.Label>Slider - {size}</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)}
</For>
</Stack>
)
}
Variants
Use the variant prop to change the visual style of the slider.
import { For, Slider, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack width="200px" gap="4">
<For each={["outline", "solid"]}>
{(variant) => (
<Slider.Root defaultValue={[40]} variant={variant} key={variant}>
<Slider.Label>Slider - {variant}</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)}
</For>
</Stack>
)
}
Colors
Use the colorPalette prop to change the color of the slider.
import { For, Slider, Stack } from "@chakra-ui/react"
const colors = ["gray", "blue", "red", "green", "pink"]
const Demo = () => {
return (
<Stack gap="4" align="flex-start">
<For each={colors}>
{(color) => (
<Slider.Root
key={color}
width="200px"
colorPalette={color}
defaultValue={[40]}
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)}
</For>
</Stack>
)
}
Label
Use the label prop to add a label to the slider.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root width="200px" defaultValue={[40]}>
<Slider.Label>Quantity</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Range Slider
Set the value or defaultValue prop to an array to create a range slider.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root width="200px" defaultValue={[30, 60]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Prevent Overlap
Use the minStepsBetweenThumbs prop to avoid thumbs with the same value.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root maxW="md" defaultValue={[20, 60]} minStepsBetweenThumbs={8}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Customization
Here's an example of customizing the thumb with custom icon and background.
"use client"
import { Box, Slider } from "@chakra-ui/react"
import { MdGraphicEq } from "react-icons/md"
const Demo = () => {
return (
<Slider.Root defaultValue={[30]}>
<Slider.Control>
<Slider.Track bg="red.100">
<Slider.Range bg="tomato" />
</Slider.Track>
<Slider.Thumb index={0} boxSize={6} borderColor="tomato" shadow="md">
<Box color="tomato" as={MdGraphicEq} />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
Value Text
Use the Slider.ValueText component to show the current value of the slider.
import { HStack, Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root maxW="sm" size="sm" defaultValue={[40]}>
<HStack justify="space-between">
<Slider.Label>Volume</Slider.Label>
<Slider.ValueText />
</HStack>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs rounded="l1" />
</Slider.Control>
</Slider.Root>
)
}
Controlled
Use the value and onValueChange props to control the value of the slider.
"use client"
import { Slider } from "@chakra-ui/react"
import { useState } from "react"
const Demo = () => {
const [value, setValue] = useState([40])
return (
<Slider.Root
maxW="200px"
value={value}
onValueChange={(e) => setValue(e.value)}
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Store
An alternative way to control the slider is to use the RootProvider component
and the useSlider store hook.
This way you can access the slider state and methods from outside the slider.
current: 40"use client"
import { Code, Slider, Stack, useSlider } from "@chakra-ui/react"
const Demo = () => {
const slider = useSlider({
defaultValue: [40],
thumbAlignment: "center",
})
return (
<Stack align="flex-start">
<Code>current: {slider.value}</Code>
<Slider.RootProvider value={slider} width="200px">
<Slider.Label>Slider</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.RootProvider>
</Stack>
)
}
Hook Form
Here's an example of how to integrate a slider with react-hook-form.
"use client"
import { Button, Field, Slider, Stack } from "@chakra-ui/react"
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema"
import { Controller, useForm } from "react-hook-form"
import { z } from "zod"
const formSchema = z.object({
value: z.array(
z
.number({ message: "Value is required" })
.min(60, { message: "Value must be greater than 60" }),
),
})
type FormValues = z.infer<typeof formSchema>
const Demo = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm<FormValues>({
resolver: standardSchemaResolver(formSchema),
defaultValues: { value: [40] },
})
const onSubmit = handleSubmit((data) => console.log(data))
return (
<form onSubmit={onSubmit}>
<Stack align="flex-start" gap="4" maxW="300px">
<Controller
name="value"
control={control}
render={({ field }) => (
<Field.Root invalid={!!errors.value?.length}>
<Field.Label>Slider: {field.value[0]}</Field.Label>
<Slider.Root
width="full"
name={field.name}
value={field.value}
onValueChange={({ value }) => {
field.onChange(value)
}}
onFocusChange={({ focusedIndex }) => {
if (focusedIndex !== -1) return
field.onBlur()
}}
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
<Field.ErrorText>{errors.value?.[0]?.message}</Field.ErrorText>
</Field.Root>
)}
/>
<Button size="sm" type="submit">
Submit
</Button>
</Stack>
</form>
)
}
Disabled
Use the disabled prop to disable the slider.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root width="200px" disabled defaultValue={[40]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Change End
Use the onValueChangeEnd prop to listen to the end of the slider change.
onChange: 50onChangeEnd: 50"use client"
import { Box, Code, Slider, Stack } from "@chakra-ui/react"
import { useState } from "react"
const initialValue = [50]
const Demo = () => {
const [value, setValue] = useState(initialValue)
const [endValue, setEndValue] = useState(initialValue)
return (
<Box maxW="240px">
<Slider.Root
value={value}
onValueChange={(e) => setValue(e.value)}
onValueChangeEnd={(e) => setEndValue(e.value)}
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
<Stack mt="3" gap="1">
<Code>
onChange: <b>{value}</b>
</Code>
<Code>
onChangeEnd: <b>{endValue}</b>
</Code>
</Stack>
</Box>
)
}
Steps
Use the step prop to set the step value of the slider.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root width="200px" defaultValue={[40]} step={10}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Thumb Alignment
Use the thumbAlignment and thumbSize prop to align the thumb within the
track. By default, the thumb is aligned to the start of the track.
import { Slider, Stack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack maxW="200px" gap="4">
<Slider.Root
thumbAlignment="contain"
thumbSize={{ width: 16, height: 16 }}
defaultValue={[40]}
>
<Slider.Label>Slider (contain)</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
<Slider.Root thumbAlignment="center" defaultValue={[40]}>
<Slider.Label>Slider (center)</Slider.Label>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
</Stack>
)
}
Marks
Use the marks prop to display marks on the slider.
size = sm
size = md
size = lg
import { For, Slider, Stack, Text, VStack } from "@chakra-ui/react"
const Demo = () => {
return (
<Stack gap="4">
<For each={["sm", "md", "lg"]}>
{(size) => (
<VStack key={size} align="flex-start">
<Slider.Root
key={size}
size={size}
defaultValue={[40]}
width="200px"
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
<Slider.Marks marks={[0, 50, 100]} />
</Slider.Control>
</Slider.Root>
<Text>size = {size}</Text>
</VStack>
)}
</For>
</Stack>
)
}
You can also add labels to the marks using the marks prop.
import { Slider } from "@chakra-ui/react"
const marks = [
{ value: 0, label: "0%" },
{ value: 50, label: "50%" },
{ value: 100, label: "100%" },
]
const Demo = () => {
return (
<Slider.Root width="200px" colorPalette="pink" defaultValue={[40]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
<Slider.Marks marks={marks} />
</Slider.Control>
</Slider.Root>
)
}
Vertical
Use the orientation prop to change the orientation of the slider.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root height="200px" orientation="vertical" defaultValue={[40]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
</Slider.Control>
</Slider.Root>
)
}
Vertical with Marks
Here's an example of a vertical slider with marks.
import { Slider } from "@chakra-ui/react"
const marks = [
{ value: 0, label: "0%" },
{ value: 50, label: "50%" },
{ value: 100, label: "100%" },
]
const Demo = () => {
return (
<Slider.Root
height="200px"
orientation="vertical"
colorPalette="pink"
defaultValue={[40]}
>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumbs />
<Slider.Marks marks={marks} />
</Slider.Control>
</Slider.Root>
)
}
Dragging Indicator
Render the Slider.DraggingIndicator component to show an indicator or tooltip
when dragging the thumb.
Pro Tip: You can render the Slider.ValueText component inside the
Slider.DraggingIndicator to show the current value.
import { Slider } from "@chakra-ui/react"
const Demo = () => {
return (
<Slider.Root maxW="200px" defaultValue={[40]}>
<Slider.Control>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumb index={0}>
<Slider.DraggingIndicator
layerStyle="fill.solid"
top="6"
rounded="sm"
px="1.5"
>
<Slider.ValueText />
</Slider.DraggingIndicator>
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
)
}
Closed Component
If you prefer a closed component composition, check out the snippet below.
import { Slider as ChakraSlider, HStack } from "@chakra-ui/react"
import * as React from "react"
export interface SliderProps extends ChakraSlider.RootProps {
marks?: Array<number | { value: number; label: React.ReactNode }>
label?: React.ReactNode
showValue?: boolean
}
export const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
function Slider(props, ref) {
const { label, showValue, marks, ...rest } = props
return (
<ChakraSlider.Root ref={ref} thumbAlignment="center" {...rest}>
{label && !showValue && (
<ChakraSlider.Label>{label}</ChakraSlider.Label>
)}
{label && showValue && (
<HStack justify="space-between">
<ChakraSlider.Label>{label}</ChakraSlider.Label>
<ChakraSlider.ValueText />
</HStack>
)}
<ChakraSlider.Control>
<ChakraSlider.Track>
<ChakraSlider.Range />
</ChakraSlider.Track>
<ChakraSlider.Thumbs />
<ChakraSlider.Marks marks={marks} />
</ChakraSlider.Control>
</ChakraSlider.Root>
)
},
)
If you want to automatically add the closed component to your project, run the command:
npx @chakra-ui/cli snippet add sliderProps
| Prop | Default | Type |
|---|---|---|
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` |
orientation | 'horizontal' | 'vertical' | 'horizontal'The orientation of the component |
origin | '\'start\'' | 'center' | 'end' | 'start'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 |
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. |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink'The color palette of the component |
size | 'md' | 'sm' | 'md' | 'lg'The size of the component |
variant | 'outline' | 'outline' | 'solid'The variant of the component |
as | React.ElementTypeThe underlying element to render. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | booleanWhether to remove the component's style. | |
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 | |
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 | |
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 | |
readOnly | booleanWhether the slider is read-only | |
thumbSize | { width: number; height: number }The slider thumbs dimensions | |
value | number[]The controlled value of the slider |
Explorer
Explore the Slider component parts interactively. Click on parts in the
sidebar to highlight them in the preview.
Component Anatomy
Hover to highlight, click to select parts
root
label
thumb
valueText
track
range
control
markerGroup
marker
draggingIndicator
markerIndicator
slider.recipe.ts