Slider

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

Examples

Basic

PropDefaultTypeDescription
modelValue-numberThe controlled value of the slider. Can be bind as v-model.
defaultValue[0]number[]The value of the slider when initially rendered. Use when you do not need to control the state of the slider.
dirltrstringThe direction of the slider.
disabledfalsebooleanWhen true, prevents the user from interacting with the slider.
invertedfalsebooleanWhen true, the slider will be inverted.
max100numberThe maximum value of the slider.
min0numberThe minimum value of the slider.
Preview
Code

Color

PropDefaultTypeDescription
sliderprimarystringChange the color of the slider.
Preview
Code

Steps

PropDefaultTypeDescription
minStepsBetweenThumbs0numberThe minimum permitted steps between multiple thumbs.
step1numberThe step value of the slider.
Preview
Code

40

[ 40, 55, 75 ]

Form Group

You can use the slider component inside the form-group component, or you can use it with the label component.

Preview
Code
Adjust the volume
40/50

Orientation

Configure the slider orientation by using the orientation prop.

PropDefaultTypeDescription
orientationhorizontalvertical, horizontalThe orientation of the slider.
Preview
Code

Size

Adjust the slider size without limits. Use breakpoints (e.g., sm:sm, xs:lg) for responsive sizes or states (e.g., hover:lg, focus:3xl) for state-based sizes.

PropDefaultTypeDescription
sizemdstringSet the slider general size.
Preview
Code

Customization

Configure the progress using the una prop and utility classes.

Preview
Code
60
50
40
30
50
40
75
85
80
50
100
40
30

Slots

NamePropsDescription
slider-track-The track of the slider.
slider-thumb-The thumb of the slider.
slider-range-The range of the slider.

Presets

shortcuts/slider.ts
import type { RuleContext } from '@unocss/core'
import type { Theme } from '@unocss/preset-uno'
import { parseColor } from '@unocss/preset-mini/utils'

type SliderPrefix = 'slider'

export const staticSlider: Record<`${SliderPrefix}-${string}`, string> = {
  // configurations
  'slider-disabled': 'n-disabled',
  'slider-root-vertical': 'flex-col w-1em h-full',
  'slider-track-vertical': 'w-0.5em h-full',
  'slider-range-vertical': 'w-full',
  'slider-thumb-vertical': 'w-1.25em h-1.25em',

  // components
  'slider-root': 'relative flex w-full touch-none select-none items-center',
  'slider-track': 'h-0.5em relative w-full grow overflow-hidden rounded-full bg-muted',
  'slider-range': 'absolute h-full bg-brand',
  'slider-thumb': 'w-1.25em h-1.25em block border-2 border-brand rounded-full bg-base focus-visible:ring-base ring-offset-base transition-colors disabled:slider-disabled focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',

  'slider-accent': 'n-gray-300 dark:n-gray-800',
}

export const dynamicSlider = [
  [/^slider-(.*)$/, ([, body]: string[], { theme }: RuleContext<Theme>) => {
    const color = parseColor(body, theme)
    if ((color?.cssColor?.type === 'rgb' || color?.cssColor?.type === 'rgba') && color.cssColor.components)
      return `n-${body}-600 dark:n-${body}-500`
  }],
]

export const slider = [
  ...dynamicSlider,
  staticSlider,
]

Props

types/slider.ts
import type { SliderRootProps } from 'radix-vue'
import type { HTMLAttributes } from 'vue'

type Extensions = SliderRootProps & { class?: HTMLAttributes['class'] }

export interface NSliderProps extends Extensions {
  /**
   * Allows you to add `UnaUI` slider preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/slider.ts
   * @example
   * slider="green""
   */
  slider?: string
  /**
   * Allows you to change the size of the slider.
   *
   * @default base|md
   *
   * @example
   * size="sm" | size="2cm" | size="2rem" | size="2px"
   */
  size?: string
  /**
   * `UnaUI` preset configuration
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/slider.ts
   */
  una?: {
    // components
    sliderRoot?: HTMLAttributes['class']
    sliderTrack?: HTMLAttributes['class']
    sliderRange?: HTMLAttributes['class']
    sliderThumb?: HTMLAttributes['class']
  }
}

Components

Slider.vue
<script setup lang="ts">
import type { SliderRootEmits } from 'radix-vue'
import type { NSliderProps } from '../../types'
import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'radix-vue'
import { computed } from 'vue'
import { cn } from '../../utils'

const props = withDefaults(defineProps<NSliderProps>(), {
  slider: 'primary',
})
const emits = defineEmits<SliderRootEmits>()
const delegatedProps = computed(() => {
  const { class: _, ...delegated } = props

  return delegated
})
const forwarded = useForwardPropsEmits(delegatedProps, emits)
const isVertical = computed(() => props.orientation === 'vertical')
</script>

<template>
  <SliderRoot
    :class="cn(
      'slider-root',
      isVertical && 'slider-root-vertical',
      props.class,
      props.una?.sliderRoot,
      disabled && 'slider-disabled',
    )"
    v-bind="forwarded"
    :slider="slider"
  >
    <slot name="slider-track">
      <SliderTrack
        :class="cn(
          'slider-track',
          isVertical && 'slider-track-vertical',
          props.una?.sliderTrack,
        )"
      >
        <slot name="slider-range">
          <SliderRange
            :class="cn(
              'slider-range',
              isVertical && 'slider-range-vertical',
              props.una?.sliderRange,
            )"
          />
        </slot>
      </SliderTrack>
    </slot>

    <slot name="slider-thumb">
      <SliderThumb
        v-for="(_, key) in modelValue"
        :key="key"
        :class="cn(
          'slider-thumb',
          isVertical && 'slider-thumb-vertical',
          props.una?.sliderThumb,
        )"
      />
    </slot>
  </SliderRoot>
</template>