gnome-ui
Components

Slider

An input where the user selects a value from within a given range.

Slider component
75
import * as React from 'react';
import { Slider } from 'gnome-ui/slider';
import { Volume2 } from 'lucide-react';

export function SliderDefault() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <div className="flex items-center justify-between text-sm font-medium text-foreground">
        <label className="flex items-center gap-2">
          <Icons.Volume2 className="size-4 text-muted-foreground" />
          System volume
        </label>
        <Slider.Value />
      </div>
      
      <Slider.Root defaultValue={75} className="flex w-full items-center">
        <Slider.Control className="relative flex w-full items-center py-2">
          <Slider.Track className="h-1.5 w-full overflow-hidden rounded-full bg-secondary">
            <Slider.Indicator className="h-full bg-primary" />
          </Slider.Track>
          <Slider.Thumb className="block size-4 rounded-full border border-primary bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50" />
        </Slider.Control>
      </Slider.Root>
    </div>
  );
}

Anatomy

import { Slider } from 'gnome-ui/slider';

<Slider.Root>
  <Slider.Value />
  <Slider.Control>
    <Slider.Track>
      <Slider.Indicator />
    </Slider.Track>
    <Slider.Thumb />
  </Slider.Control>
</Slider.Root>

Examples

Range Slider

Provide an array to the defaultValue or value prop to create a range slider with multiple thumbs. When doing this, ensure you pass an index to <Slider.Thumb> and <Slider.Value> if you want to display individual thumb values.

Slider component
20 80
import * as React from 'react';
import { Slider } from 'gnome-ui/slider';
import { Monitor } from 'lucide-react';

export function SliderRange() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <div className="flex items-center justify-between text-sm font-medium text-foreground">
        <label className="flex items-center gap-2">
          <Icons.Monitor className="size-4 text-muted-foreground" />
          Workspace (GB)
        </label>
        <div className="flex gap-1 text-muted-foreground">
          <Slider.Value index={0} /> - <Slider.Value index={1} />
        </div>
      </div>
      
      <Slider.Root defaultValue={[20, 80]} className="flex w-full items-center">
        <Slider.Control className="relative flex w-full items-center py-2">
          <Slider.Track className="h-1.5 w-full overflow-hidden rounded-full bg-secondary">
            <Slider.Indicator className="h-full bg-[oklch(0.55_0.12_250)]" />
          </Slider.Track>
          <Slider.Thumb index={0} className="block size-4 rounded-full border border-[oklch(0.55_0.12_250)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.55_0.12_250)]" />
          <Slider.Thumb index={1} className="block size-4 rounded-full border border-[oklch(0.55_0.12_250)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.55_0.12_250)]" />
        </Slider.Control>
      </Slider.Root>
    </div>
  );
}

Vertical Slider

Use orientation="vertical" on the root component to create a vertical slider. Make sure to adjust the width and height of the track, indicator, and control accordingly.

Slider component
import * as React from 'react';
import { Slider } from 'gnome-ui/slider';
import { Sun } from 'lucide-react';

export function SliderVertical() {
  return (
    <div className="flex h-48 flex-col items-center gap-4">
      <Icons.Sun className="size-4 text-muted-foreground" />
      <Slider.Root orientation="vertical" defaultValue={60} className="flex h-full items-center">
        <Slider.Control className="relative flex h-full items-center px-2">
          <Slider.Track className="w-1.5 h-full overflow-hidden rounded-full bg-secondary">
            <Slider.Indicator className="w-full bg-[oklch(0.75_0.15_50)]" />
          </Slider.Track>
          <Slider.Thumb className="block size-4 rounded-full border border-[oklch(0.75_0.15_50)] bg-background shadow-sm transition-transform hover:scale-110 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[oklch(0.75_0.15_50)]" />
        </Slider.Control>
      </Slider.Root>
    </div>
  );
}

SliderControl

The clickable, interactive part of the slider. Renders a &lt;div&gt; element.

Documentation: Base UI Slider

API reference

Root

Groups all parts of the slider. Renders a <div> element.

Root Props:

PropTypeDefaultDescription
namestring-Identifies the field when a form is submitted.
defaultValuenumber | number[]-The uncontrolled value of the slider when it’s initially rendered.To render a controlled slider, use the value prop instead.
valuenumber | number[]-The value of the slider. For ranged sliders, provide an array with two values.
onValueChange((value: number | number[], eventDetails: Slider.Root.ChangeEventDetails) => void)-Callback function that is fired when the slider's value changed. You can pull out the new value by accessing event.target.value (any).The eventDetails.reason indicates what triggered the change:* 'input-change' when the hidden range input emits a change event (for example, via form integration)
  • 'track-press' when the control track is pressed
  • 'drag' while dragging a thumb
  • 'keyboard' for keyboard input
  • 'none' when the change is triggered without a specific interaction | | onValueCommitted | ((value: number \| number[], eventDetails: Slider.Root.CommitEventDetails) => void) | - | Callback function that is fired when the pointerup is triggered. Warning: This is a generic event not a change event.The eventDetails.reason indicates what triggered the commit:* 'drag' while dragging a thumb
  • 'track-press' when the control track is pressed
  • 'keyboard' for keyboard input
  • 'input-change' when the hidden range input emits a change event (for example, via form integration)
  • 'none' when the commit occurs without a specific interaction | | locale | Intl.LocalesArgument | - | The locale used by Intl.NumberFormat when formatting the value. Defaults to the user's runtime locale. | | thumbAlignment | 'center' \| 'edge' \| 'edge-client-only' | 'center' | How the thumb(s) are aligned relative to Slider.Control when the value is at min or max:* center: The center of the thumb is aligned with the control edge
  • edge: The thumb is inset within the control such that its edge is aligned with the control edge
  • edge-client-only: Same as edge but renders after React hydration on the client, reducing bundle size in return | | thumbCollisionBehavior | 'push' \| 'swap' \| 'none' | 'push' | Controls how thumbs behave when they collide during pointer interactions.* 'push' (default): Thumbs push each other without restoring their previous positions when dragged back.
  • 'swap': Thumbs swap places when dragged past each other.
  • 'none': Thumbs cannot move past each other; excess movement is ignored. | | step | number | 1 | The granularity with which the slider can step through values. (A "discrete" slider.) The min prop serves as the origin for the valid values. We recommend (max - min) to be evenly divisible by the step. | | largeStep | number | 10 | The granularity with which the slider can step through values when using Page Up/Page Down or Shift + Arrow Up/Arrow Down. | | minStepsBetweenValues | number | 0 | The minimum steps between values in a range slider. | | min | number | 0 | The minimum allowed value of the slider. Should not be equal to max. | | max | number | 100 | The maximum allowed value of the slider. Should not be equal to min. | | format | Intl.NumberFormatOptions | - | Options to format the input value. | | disabled | boolean | false | Whether the slider should ignore user interaction. | | orientation | Orientation | 'horizontal' | The component orientation. | | className | string \| ((state: Slider.Root.State) => string \| undefined) | - | CSS class applied to the element, or a function that returns a class based on the component’s state. | | style | CSSProperties \| ((state: Slider.Root.State) => CSSProperties \| undefined) | - | - | | render | ReactElement \| ((props: HTMLProps, state: Slider.Root.State) => ReactElement) | - | Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render. |

Root Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).

Value

Displays the current value of the slider as text. Renders an <output> element.

Value Props:

PropTypeDefaultDescription
children((formattedValues: string[], values: number[]) => ReactNode) | null--
classNamestring | ((state: Slider.Root.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component’s state.
styleCSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined)-*
renderReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement)-Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Value Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).

Control

The clickable, interactive part of the slider. Renders a <div> element.

Control Props:

PropTypeDefaultDescription
classNamestring | ((state: Slider.Root.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component’s state.
styleCSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined)--
renderReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement)-Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Control Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).

Track

Contains the slider indicator and represents the entire range of the slider. Renders a <div> element.

Track Props:

PropTypeDefaultDescription
classNamestring | ((state: Slider.Root.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component’s state.
styleCSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined)--
renderReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement)-Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Track Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).

Indicator

Visualizes the current value of the slider. Renders a <div> element.

Indicator Props:

PropTypeDefaultDescription
classNamestring | ((state: Slider.Root.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component’s state.
styleCSSProperties | ((state: Slider.Root.State) => CSSProperties | undefined)--
renderReactElement | ((props: HTMLProps, state: Slider.Root.State) => ReactElement)-Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Indicator Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).

Thumb

The draggable part of the slider at the tip of the indicator. Renders a <div> element and a nested <input type="range">.

Thumb Props:

PropTypeDefaultDescription
getAriaLabel((index: number) => string) | null-A function which returns a string value for the aria-label attribute of the input.
getAriaValueText((formattedValue: string, value: number, index: number) => string) | null-A function which returns a string value for the aria-valuetext attribute of the input. This is important for screen reader users.
indexnumber-The index of the thumb which corresponds to the index of its value in the value or defaultValue array. This prop is required to support server-side rendering for range sliders with multiple thumbs.
onBlurFocusEventHandler<HTMLInputElement>-A blur handler forwarded to the input.
onFocusFocusEventHandler<HTMLInputElement>-A focus handler forwarded to the input.
tabIndexnumber-Optional tab index attribute forwarded to the input.
disabledbooleanfalseWhether the thumb should ignore user interaction.
inputRefRef<HTMLInputElement>-A ref to access the nested input element.
classNamestring | ((state: Slider.Thumb.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component’s state.
styleCSSProperties | ((state: Slider.Thumb.State) => CSSProperties | undefined)--
renderReactElement | ((props: HTMLProps, state: Slider.Thumb.State) => ReactElement)-Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Thumb Data Attributes:

AttributeTypeDescription
data-dragging-Present while the user is dragging.
data-orientation'horizontal' | 'vertical'Indicates the orientation of the slider.
data-disabled-Present when the slider is disabled.
data-valid-Present when the slider is in valid state (when wrapped in Field.Root).
data-invalid-Present when the slider is in invalid state (when wrapped in Field.Root).
data-dirty-Present when the slider's value has changed (when wrapped in Field.Root).
data-touched-Present when the slider has been touched (when wrapped in Field.Root).
data-focused-Present when the slider is focused (when wrapped in Field.Root).
data-index-Indicates the index of the thumb in range sliders.

On this page