Slider

A slider input for selecting a single value or a range of values within a minimum and maximum.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Slider } from 'frappe-ui'

const value = ref([25])
</script>

<template>
  <div class="w-full max-w-md">
    <Slider v-model="value" />
  </div>
</template>

Sizes

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Slider } from 'frappe-ui'

const small = ref([30])
const medium = ref([60])
</script>

<template>
  <div class="flex flex-col gap-6 w-full max-w-md">
    <Slider v-model="small" size="sm" label="Small" />
    <Slider v-model="medium" size="md" label="Medium" />
  </div>
</template>

Range

Use a two-element modelValue to render two thumbs.

20 – 80
vue
<script setup lang="ts">
import { ref } from 'vue'
import { Badge, Slider } from 'frappe-ui'

const value = ref([20, 80])
</script>

<template>
  <div class="flex flex-col gap-3 w-full max-w-md">
    <Slider v-model="value" label="Price range" />
    <Badge class="w-fit !rounded-sm">{{ value.join(' – ') }}</Badge>
  </div>
</template>

Labeling

Adjust the volume.

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { Checkbox, Slider } from 'frappe-ui'

const value = ref([40])
const required = ref(true)
const showError = ref(false)

const error = computed(() =>
  showError.value ? 'Please pick a value greater than 50.' : '',
)
</script>

<template>
  <div class="flex gap-8 items-start">
    <Slider
      v-model="value"
      label="Volume"
      description="Adjust the volume."
      :error="error"
      :required="required"
      class="w-96"
    />
    <div
      class="flex flex-col gap-2 items-start border-l border-outline-gray-2 pl-6 shrink-0"
    >
      <Checkbox v-model="required" label="required" />
      <Checkbox v-model="showError" label="show error" />
    </div>
  </div>
</template>

value-commit

value-commit fires once when the user finishes dragging the slider — useful for triggering side effects only at drag end, not on every step.

Commits: —

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Slider } from 'frappe-ui'

const value = ref([50])
const commits = ref<number[][]>([])

function onValueCommit(committed: number[]) {
  commits.value = [...commits.value, committed]
}
</script>

<!--
  `value-commit` fires once at the end of a drag, not on every step.
  Drag the slider thumb and release to log committed values below.
-->

<template>
  <div class="flex flex-col gap-3 w-full max-w-md">
    <Slider
      v-model="value"
      label="Drag and release to commit"
      @value-commit="onValueCommit"
    />
    <p class="text-p-sm text-ink-gray-6">
      Commits: {{ commits.length ? commits.map((c) => c.join(',')).join(' · ') : '—' }}
    </p>
  </div>
</template>

States

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Slider } from 'frappe-ui'

const a = ref([30])
const b = ref([30])
const c = ref([30])
const d = ref([30])
</script>

<template>
  <div class="flex flex-col gap-6 w-full max-w-md">
    <Slider v-model="a" label="Default" />
    <Slider v-model="b" label="Required" required />
    <Slider v-model="c" label="Disabled" disabled />
    <Slider v-model="d" label="With error" error="Required." />
  </div>
</template>

API Reference

Show types
typescript
import type { ToggleSize } from '../../composables/inputTypes'
import type { InputLabelingProps } from '../../composables/useInputLabeling'

/**
 * Value model for the Slider component.
 * Use one number for a single-value slider or two numbers for a range slider.
 *
 * @example
 * const single: SliderValue = [25]
 *
 * @example
 * const range: SliderValue = [20, 80]
 */
export type SliderValue = number[]

export interface SliderProps extends InputLabelingProps {
  /** Step interval between slider values. */
  step?: number

  /** Maximum allowed slider value. */
  max?: number

  /** Minimum allowed slider value. */
  min?: number

  /** Visual size of the slider. */
  size?: ToggleSize

  /** Disables the slider. */
  disabled?: boolean
}

export interface SliderEmits {
  /** Fired once when the user finishes dragging the slider. */
  'value-commit': [value: SliderValue]
}
step
= 1
number

Step interval between slider values.

max
= 100
number

Maximum allowed slider value.

min
= 0
number

Minimum allowed slider value.

size
= "sm"
ToggleSize

Visual size of the slider.

disabled
= false
boolean

Disables the slider.

label
string

Label rendered above (or beside, for binary controls) the input.

description
string

Helper text rendered below the input. Hidden when `error` is set.

error
string | FrappeUIError

Error message rendered below the input. When set, the control receives `aria-invalid="true"` and `data-state="invalid"`. May be either a string or an `Error` object whose `messages?: string[]` is rendered as stacked lines (with `Error.message` as the fallback).

required
boolean

Marks the field as required. Renders an asterisk next to the label and forwards `required` / `aria-required` to the underlying control.

id
string

HTML id of the underlying control. Auto-generated via `useId()` if omitted.

modelValue
SliderValue

The current slider value (controlled).

label
{ required: boolean; }

Overrides the rendered label content. Receives `{ required }`.

description

Overrides the rendered description content.

update:modelValue
[value: SliderValue | undefined]

Fired when the model value changes.

value-commit
[value: SliderValue]

Fired once when the user finishes committing the value.