Skip to content

Range

Accessible range slider that allows easy selection of a value by sliding a handle.

View Source 

Installation

Follow instructions for individual framework usage below

  • winduum 
  • winduum-elements 
  • winduum-stimulus 
  • winduum-vue 
  • winduum-react 

Styles

Variants

  • default
  • multi

Props

  • default 

Tokens

  • vertical

Scripts

The Range script updates track CSS variables and linked output values as the slider changes.

Examples

Default

html
<x-range class="x-range">
    <input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-part="start">
</x-range>

<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
liquid
<div data-controller="x-range" class="x-range">
    <input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-target="start" data-action="input->x-range#setValue">
</div>

<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
vue
<script setup lang="ts">
    import { ref } from 'vue'
    import { Range } from '@/components/range'

    const startElement = ref<HTMLInputElement>()
</script>

<template>
    <Range v-slot="{ setValue }" :refs="{ startElement }">
        <input ref="startElement" type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" @input="setValue">
    </Range>

    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</template>
tsx
import { useRef } from "react"
import { Range } from "@/components/range"

export function Example() {
    const startElement = useRef<HTMLInputElement>(null)

    return (
        <>
            <Range refs={{ startElement }}>
                {({ setValue }) => (
                    <input ref={startElement} type="range" defaultValue="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" onInput={setValue} />
                )}
            </Range>

            <output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
        </>
    )
}

Multi

html
<x-range class="x-range accent-warning">
    <input type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" data-x-range-part="start">
    <input type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" data-x-range-part="end" data-track="end">
</x-range>

<div class="flex-between items-center">
    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>
liquid
<div data-controller="x-range" class="x-range accent-warning">
    <input type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" data-x-range-target="start" data-action="input->x-range#setValue">
    <input type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" data-x-range-target="end" data-action="input->x-range#setValue" data-x-range-track-param="end">
</div>

<div class="flex-between items-center">
    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
</div>
vue
<script setup lang="ts">
    import { ref } from 'vue'
    import { Range } from '@/components/range'

    const startElement = ref<HTMLInputElement>()
    const endElement = ref<HTMLInputElement>()
</script>

<template>
    <Range v-slot="{ setValue }" :refs="{ startElement, endElement }" class="accent-warning">
        <input ref="startElement" type="range" value="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" @input="setValue">
        <input ref="endElement" type="range" value="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" @input="setValue">
    </Range>

    <div class="flex-between items-center">
        <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
        <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
    </div>
</template>
tsx
import { useRef } from 'react'
import { Range } from '@/components/range'

export function Example() {
    const startElement = useRef<HTMLInputElement>(null)
    const endElement = useRef<HTMLInputElement>(null)

    return (
        <>
            <Range className="accent-warning" refs={{ startElement, endElement }}>
                {({ setValue }) => (
                    <>
                        <input ref={startElement} type="range" defaultValue="0" step="100" max="10000" min="0" id="range-from" aria-labelledby="from" onInput={setValue} />
                        <input ref={endElement} type="range" defaultValue="10000" step="100" max="10000" min="0" id="range-to" aria-labelledby="to" onInput={setValue} />
                    </>
                )}
            </Range>

            <div className="flex-between items-center">
                <output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price from" id="from">0</output>
                <output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price to" id="to">10 000</output>
            </div>
        </>
    )
}

Vertical

html
<x-range class="x-range vertical h-48">
    <input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-part="start">
</x-range>

<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
liquid
<div data-controller="x-range" class="x-range vertical h-48">
    <input type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" data-x-range-target="start" data-action="input->x-range#setValue">
</div>

<output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
vue
<script setup lang="ts">
    import { ref } from 'vue'
    import { Range } from '@/components/range'

    const startElement = ref<HTMLInputElement>()
</script>

<template>
    <Range v-slot="{ setValue }" :refs="{ startElement }" class="vertical h-48">
        <input ref="startElement" type="range" value="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" @input="setValue">
    </Range>

    <output class="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
</template>
tsx
import { useRef } from 'react'
import { Range } from '@/components/range'

export function Example() {
    const startElement = useRef<HTMLInputElement>(null)

    return (
        <>
            <Range className="vertical h-48" refs={{ startElement }}>
                {({ setValue }) => (
                    <input ref={startElement} type="range" defaultValue="0" step="10" max="100" min="0" aria-labelledby="single" id="range-single" onInput={setValue} />
                )}
            </Range>

            <output className="before:content-[attr(data-unit)]" data-unit="$" aria-label="Price" id="single">10 000</output>
        </>
    )
}

JavaScript API

setTrackProperty

  • Type: (options: TrackOptions, track: 'start' | 'end') => void
  • Kind: sync

TrackOptions


element
  • Type: HTMLElement | Element
  • Default: undefined

value
  • Type: string
  • Default: undefined

min
  • Type: number
  • Default: undefined

max
  • Type: number
  • Default: undefined


setValue

  • Type: (element: HTMLInputElement, options: SetValueOptions) => void
  • Kind: sync

DefaultOptions


selector
  • Type: string
  • Default: .x-range

track
  • Type: string
  • Default: 'start' | 'end'


setOutputValue

  • Type: (element: HTMLInputElement, options: SetOutputOptions) => void
  • Kind: sync

SetOutputOptions


lang
  • Type: string
  • Default: document.documentElement.lang

formatOptions
  • Type: Intl.NumberFormatOptions
  • Default: { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }

Released under the MIT License.