ColorSlider

A color slider allows users to adjust an individual channel of a color value

Usage

<script setup lang="ts">
import { ColorSlider } from '@hareui/vue'
</script>
0°
<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <ColorSlider channel="hue" class="w-full max-w-xs" default-value="hsl(0, 100%, 50%)" label="Hue" /></template>

Anatomy

ColorSlider renders a Label, an output with the formatted channel value, and a track with a thumb. The label comes from the label prop (or #label); the output is shown whenever there is a label (show-output overrides that). Without a label, pass aria-label.

<template>
  <ColorSlider channel="hue" label="Hue">
    <template #label />   <!-- Label content -->
    <template #output="{ channelName, channelValue, valueText }" />  <!-- Output content -->
    <template #thumb="{ channelName, channelValue, valueText }" />   <!-- Thumb content -->
  </ColorSlider>
</template>
ui keydata-slotElement
basecolor-sliderroot
labellabelLabel (iff label / #label)
outputcolor-slider-outputformatted channel value
trackcolor-slider-tracktrack with the channel gradient
thumbcolor-slider-thumbthumb showing the current color

Examples

Disabled

200°
<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <ColorSlider disabled channel="hue" class="w-full max-w-xs" default-value="hsl(200, 100%, 50%)" label="Hue" /></template>

Vertical

<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <div class="flex h-48 gap-4">    <ColorSlider aria-label="Hue" channel="hue" default-value="hsl(0, 100%, 50%)" orientation="vertical" />    <ColorSlider aria-label="Saturation" channel="saturation" default-value="hsl(0, 100%, 50%)" orientation="vertical" />    <ColorSlider aria-label="Lightness" channel="lightness" default-value="hsl(0, 100%, 50%)" orientation="vertical" />  </div></template>

Controlled

Bind the color with v-model. It accepts a string or a Color and always commits a Color in the channel's colour space; use colorToString(color, 'hsl') to read it as a string.

200°

Current color: hsl(200, 100%, 50%)

<script setup lang="ts">import { ColorSlider, ColorSwatch, colorToString, parseColor } from '@hareui/vue'import { ref } from 'vue'const color = ref(parseColor('hsl(200, 100%, 50%)'))</script><template>  <div class="flex w-full max-w-xs flex-col gap-4">    <ColorSlider v-model="color" channel="hue" label="Hue" />    <div class="flex items-center gap-2">      <ColorSwatch :color="color" size="sm" />      <p class="text-sm text-muted">        Current color: <code class="font-mono">{{ colorToString(color, 'hsl') }}</code>      </p>    </div>  </div></template>

HSL Channels

Use multiple ColorSliders to control different channels of a color value. The sliders can share the same color value to create a complete color picker.

0°100%50%

Current color: hsl(0, 100%, 50%)

<script setup lang="ts">import { ColorSlider, ColorSwatch, colorToString, parseColor } from '@hareui/vue'import { ref } from 'vue'const color = ref(parseColor('hsl(0, 100%, 50%)'))</script><template>  <div class="flex w-full max-w-xs flex-col gap-4">    <ColorSlider v-model="color" channel="hue" label="Hue" />    <ColorSlider v-model="color" channel="saturation" label="Saturation" />    <ColorSlider v-model="color" channel="lightness" label="Lightness" />    <div class="flex items-center gap-2">      <ColorSwatch :color="color" size="sm" />      <p class="text-sm text-muted">        Current color: <code class="font-mono">{{ colorToString(color, 'hsl') }}</code>      </p>    </div>  </div></template>

Alpha Channel

The alpha channel slider shows a transparency checkerboard pattern to help visualize the transparency level.

50%
<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <ColorSlider channel="alpha" class="w-full max-w-xs" default-value="hsla(0, 100%, 50%, 0.5)" label="Alpha" /></template>

RGB Channels

You can also use RGB color space with red, green, and blue channels.

25510050

Current color: rgb(255, 100, 50)

<script setup lang="ts">import { ColorSlider, ColorSwatch, colorToString, parseColor } from '@hareui/vue'import { ref } from 'vue'const color = ref(parseColor('rgb(255, 100, 50)'))</script><template>  <div class="flex w-full max-w-xs flex-col gap-4">    <ColorSlider v-model="color" channel="red" label="Red" />    <ColorSlider v-model="color" channel="green" label="Green" />    <ColorSlider v-model="color" channel="blue" label="Blue" />    <div class="flex items-center gap-2">      <ColorSwatch :color="color" size="sm" />      <p class="text-sm text-muted">        Current color: <code class="font-mono">{{ colorToString(color, 'rgb') }}</code>      </p>    </div>  </div></template>

Render Function

HeroUI's render prop replaces the root element. In Vue, attributes you pass to ColorSlider fall through to the root element.

0°
<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <!-- Attributes fall through to the root element (HeroUI's `render` prop) -->  <ColorSlider    channel="hue"    class="w-full max-w-xs"    data-custom="foo"    default-value="hsl(0, 100%, 50%)"    label="Hue"  /></template>

Customization

Tailwind CSS

220°
<script setup lang="ts">import { ColorSlider } from '@hareui/vue'</script><template>  <ColorSlider    channel="hue"    class="w-full max-w-sm"    default-value="hsl(220, 70%, 50%)"    label="Hue"    :ui="{      label: 'font-medium text-foreground',      output: 'text-muted tabular-nums',      track: 'h-4! rounded-none! ring-1 ring-border [&::after]:rounded-r-sm! [&::before]:rounded-l-sm!',      thumb: 'size-4 rounded-sm! border-2 border-background shadow-md ring-1 ring-black/10 dark:ring-white/20',    }"  /></template>

Global Configuration

app.use(createHareUI({
  ui: { colorSlider: { slots: { output: 'text-muted', thumb: 'size-5' } } },
}))

Styling Reference

Slots

  • base → [data-slot="color-slider"] – grid root
  • label → [data-slot="label"]
  • output → [data-slot="color-slider-output"]
  • track → [data-slot="color-slider-track"] – gradient track; ::before / ::after are the edge caps
  • thumb → [data-slot="color-slider-thumb"]

Interactive States

  • Disabled: [data-disabled] on the root and the thumb
  • Orientation: [data-orientation] on the root, track and thumb
  • Focus Visible: :focus-visible on the thumb
  • Dragging: :active on the thumb

API Reference

Props

PropTypeDefaultDescription
channelColorChannel-The color channel that this slider manipulates.
colorSpaceColorSpace'hsl'The color space the channel/gradient is resolved in. Auto-corrected with a dev warning when it conflicts with channel (e.g. channel="red" forces "rgb").
modelValuestring | Color-The color value (controlled). Falls back to the enclosing ColorPicker's color when omitted and one is present.
defaultValuestring | Color"#000000"The default color (uncontrolled), used when there's no v-model and no enclosing ColorPicker.
orientation"horizontal" | "vertical""horizontal"The orientation of the slider.
disabledbooleanfalseWhether the slider is disabled.
stepnumber-Custom step value for increment/decrement. Defaults to the channel's natural step.
labelstring-Visible label, rendered above (horizontal) or below (vertical) the track.
showOutputbooleanundefinedWhether to render the formatted value output.
namestring-The name of the hidden input, used for form submission (the color is always submitted as hex).
uiComponentSlots<{ slots: { base: string; label: string; output: string; track: string[]; thumb: string[]; }; variants: { orientation: { horizontal: { base: string; label: string; track: string[]; thumb: string; }; vertical: { base: string; output: string; label: string; track: string[]; thumb: string; }; }; hasLabel: { true: {}; false: {}; }; hasOutput: { true: {}; false: {}; }; }; compoundVariants: ({ orientation: string; hasLabel: boolean; hasOutput: boolean; class: { base: string; output?: undefined; }; } | { orientation: string; hasLabel: boolean; hasOutput: boolean; class: { base: string; output: string; }; })[]; defaultVariants: { orientation: string; hasLabel: boolean; hasOutput: boolean; }; }>-Per-slot class overrides.

Slots

SlotPropsDescription
labelanyLabel content. Replaces the label prop.
outputColorSliderSlotPropsOutput content. Replaces the formatted value text.
thumbColorSliderSlotPropsThumb content.

Emits

EventPayloadDescription
update:modelValue[value: Color]-
change[value: string]-
changeEnd[value: string]-

Accessibility

  • The thumb is a role="slider" labelled by the channel name, with a localised aria-valuetext
  • Keyboard: arrow keys, Home, End, PageUp and PageDown
  • name submits the colour as hex through a hidden input

On this page

No Headings