# Slider

A slider lets someone set a value from a given range. Sliders can take immediate effect, like a volume control, or can require a submission, like in a form.

## Best practices

### Do

- Use a slider when approximate or imprecise values are acceptable.
- Use a step slider when selection must snap to discrete values.
- Provide a label, even if it is visually hidden.

### Don't

- Use a slider for extremely small or large ranges.
- Use a slider for precise numerical input; use an input.

## Behavior and states

- Default sliders let someone choose any approximate value along an unmarked range.
- Step sliders divide a track into discrete values and snap the thumb to the closest value.
- Move the thumb along the track or select a point on the track for the thumb to jump to.
- Sliders can be laid out vertically or horizontally.
- Use a slider for imprecise values.
- Don't use them for ranges that are very small or very large.
- For precise numerical inputs, like a dollar amount, try an input.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-slider--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = (): JSXElement => {
    const id = useId();
    return (<>
      <Label htmlFor={id}>Basic Example</Label>
      <Slider defaultValue={20} id={id}/>
    </>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### Slider API

The Slider component allows users to quickly select a value by dragging a thumb across a rail.

```ts
interface SliderProps {
  as?: "input";

  children?: undefined;

  className?: string;

  /**
   * The starting value for an uncontrolled Slider.
   * Mutually exclusive with `value` prop.
   */
  defaultValue?: number;

  /**
   * Whether to render the Slider as disabled.
   * @default `false` (renders enabled)
   */
  disabled?: boolean;

  /**
   * The hidden input for the Slider.
   * This is the PRIMARY slot: all native properties specified directly on `<Slider>` will be applied to this slot,
   * except `className` and `style`, which remain on the root slot.
   */
  input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; } & { orient?: "horizontal" | "vertical" | undefined; }) | undefined;

  /**
   * The max value of the Slider.
   * @default 100
   */
  max?: string | number;

  /**
   * The min value of the Slider.
   * @default 0
   */
  min?: string | number;

  /**
   * Triggers a callback when the value has been changed. This will be called on every individual step.
   */
  onChange?: ((ev: ChangeEvent<HTMLInputElement>, data: SliderOnChangeData) => void);

  /**
   * Orient is a non standard attribute that allows for vertical orientation in Firefox. It is set internally
   * when `vertical` is set to true.
   * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range#non_standard_attributes
   * Webkit/Chromium support for vertical inputs is provided via -webkit-appearance css property
   */
  orient?: "horizontal" | "vertical";

  /**
   * The Slider's base. It is used to visibly display the min and max selectable values.
   */
  rail?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  ref?: Ref<HTMLInputElement>;

  /**
   * The root of the Slider.
   * The root slot receives the `className` and `style` specified directly on the `<Slider>`.
   * All other native props will be applied to the primary slot, `input`.
   */
  root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * The size of the Slider.
   * @default 'medium'
   */
  size?: "small" | "medium";

  /**
   * The number of steps that the Slider's `value` will increment upon change. When provided, the Slider
   * will snap to the closest available value. This must be a positive value.
   * @default 1
   */
  step?: string | number;

  style?: CSSProperties;

  /**
   * The draggable icon used to select a given value from the Slider.
   * This is the element containing `role = 'slider'`.
   */
  thumb?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * The current value of the controlled Slider.
   * Mutually exclusive with `defaultValue` prop.
   */
  value?: number;

  /**
   * Render the Slider in a vertical orientation, smallest value on the bottom.
   * @default `false`
   */
  vertical?: boolean;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

Note: Storybook-only layout decorators are omitted. Examples use the documentation preview spacing instead.

## Controlled

Source: Fluent, adapted for CoreAI.

A slider can be a controlled input where the slider value is stored in state
      and updated with `onChange`. This is also useful for setting custom aria-valuetext

[Download source](/coreai-design-system/source/examples/components-slider--controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import type { SliderProps } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";

export const Controlled = (): JSXElement => {
    const id = useId();
    const [sliderValue, setSliderValue] = React.useState(160);
    const onSliderChange: SliderProps['onChange'] = (_, data) => setSliderValue(data.value);
    const resetSlider = () => setSliderValue(0);
    return (<>
      <Label htmlFor={id}>Control Slider [ Current Value: {sliderValue} ]</Label>
      <Slider aria-valuetext={`Value is ${sliderValue}`} value={sliderValue} min={20} max={200} onChange={onSliderChange} id={id}/>
      <Button onClick={resetSlider}>Reset</Button>
    </>);
};

export default Controlled;
```

## Disabled

Source: Fluent, adapted for CoreAI.

A disabled slider will not change or fire events on click or keyboard press.

[Download source](/coreai-design-system/source/examples/components-slider--disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

export const Disabled = (): JSXElement => {
    const id = useId();
    return (<>
      <Label htmlFor={id}>Disabled Example</Label>
      <Slider defaultValue={30} disabled id={id}/>
    </>);
};

export default Disabled;
```

## Min Max

Source: Fluent, adapted for CoreAI.

A slider with min and max values displayed

[Download source](/coreai-design-system/source/examples/components-slider--min-max.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

const useStyles = makeStyles({
    wrapper: {
        display: 'flex',
        alignItems: 'center',
    },
});

export const MinMax = (): JSXElement => {
    const styles = useStyles();
    const id = useId();
    const min = 10;
    const max = 50;
    return (<>
      <Label htmlFor={id}>Min/Max Example</Label>
      <div className={styles.wrapper}>
        <Label aria-hidden>{min}</Label>
        <Slider min={min} max={max} defaultValue={20} id={id}/>
        <Label aria-hidden>{max}</Label>
      </div>
    </>);
};

export default MinMax;
```

## Size

Source: Fluent, adapted for CoreAI.

A slider comes in both medium and small size. Medium is the default.

[Download source](/coreai-design-system/source/examples/components-slider--size.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

export const Size = (): JSXElement => {
    const smallId = useId('small');
    const mediumId = useId('medium');
    return (<>
      <Label htmlFor={mediumId}>Medium Slider</Label>
      <Slider size="medium" defaultValue={20} id={mediumId}/>

      <Label htmlFor={smallId}>Small Slider</Label>
      <Slider size="small" defaultValue={20} id={smallId}/>
    </>);
};

export default Size;
```

## Step

Source: Fluent, adapted for CoreAI.

You can define the step value of a slider so that the value will always be a mutiple of that step

[Download source](/coreai-design-system/source/examples/components-slider--step.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

export const Step = (): JSXElement => {
    const id = useId();
    return (<>
      <Label htmlFor={id}>Step Example</Label>
      <Slider defaultValue={6} step={3} min={0} max={12} id={id}/>
    </>);
};

export default Step;
```

## Vertical

Source: Fluent, adapted for CoreAI.

A slider can be oriented vertically where the max value is at the top of the slider.

[Download source](/coreai-design-system/source/examples/components-slider--vertical.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Slider } from "@coreai-ds/react-components";
import * as React from 'react';

export const Vertical = (): JSXElement => {
    const id = useId();
    return (<>
      <Label htmlFor={id}>Vertical Example</Label>
      <Slider vertical step={2} defaultValue={6} min={0} max={10} id={id}/>
    </>);
};

export default Vertical;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=12126-152884)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/slider/usage)