๐ข Slider
Features
- Can be controlled or uncontrolled.
- Supports multiple thumbs.
- Supports a minimum value between thumbs.
- Supports touch or click on track to update value.
- Supports Right to Left direction.
- Full keyboard navigation.
- Customizable.
Basic
use NSlider
to create a range input.
Color
slider="{color}"
- change the color of the slider.
primary
. You can also add your own colors to the palette through the Configuration section.Steps
step="{number}"
- define the step value of the slider.
min-steps-between-thumbs="{number}"
- define the minimum steps between thumbs.
min-steps-between-thumbs
prop.40
[ 40, 55, 75 ]
Label
You can use the
NFormGroup
component to create a label for the slider.
NFormGroup
component here.Orientation
orientation={value}
- change the orientation of the slider.
Value | Description |
---|---|
horizontal | The default orientation. |
vertical | The vertical orientation. |
Disabled
disabled
- disable the slider.
Size
size="{size}"
- change the size of the slider.
๐ You can freely adjust the size of the slider using any size imaginable. No limits exist, and you can use
breakpoints
such assm:sm, xs:lg
to change size based on screen size orstates
such ashover:lg, focus:3xl
to change size based on input state and more.
height
and width
of the slider scale depends on the slider-size
. If you want to change the height
and width
simultaneously, you can always customize it using utility classes.Customization
You can customize the slider using the
una
prop and utility classes.
Slots
You can use the following slots to customize the slider.
Name | Description | Props |
---|---|---|
slider-track | The track of the slider. | - |
slider-thumb | The the thumb of the slider. | - |
slider-range | The the range of the slider. | - |
Props
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']
}
}
Presets
import { parseColor } from '@unocss/preset-mini/utils'
import type { Theme } from '@unocss/preset-uno'
import type { RuleContext } from '@unocss/core'
type SliderPrefix = 'slider'
export const staticSlider: Record<`${SliderPrefix}-${string}` | SliderPrefix, string> = {
// configurations
'slider': 'slider-primary size-base',
'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': 'slider 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:pointer-events-none disabled:opacity-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
}
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,
]
Component
<script setup lang="ts">
import { computed } from 'vue'
import type { SliderRootEmits } from 'radix-vue'
import { SliderRange, SliderRoot, SliderThumb, SliderTrack, useForwardPropsEmits } from 'radix-vue'
import type { NSliderProps } from '../../types'
import { cn } from '../../utils'
const props = defineProps<NSliderProps>()
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"
>
<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>