Color Picker Shared Partial

Follow the Installation section first!
This component requires additional setup (dependencies, gems, controllers, partials, or libraries) before using these shared partials. Please complete the Installation section on this page first.

1. Copy shared partial files

Download all 1 shared partial files as a ZIP file.

Download all files (ZIP)

After downloading, unzip and copy the color_picker/ folder to your app/views/shared/components/ directory.

Copy these files to your app/views/shared/components/color_picker/ directory:

2. Usage example

<%# Enhanced color picker (example3) %>
<%= render "shared/components/color_picker/color_picker",
  id: "enhanced_color",
  label: "Brand Color",
  value: "#3b82f6",
  format: "hex" %>

<%# Color picker with opacity %>
<%= render "shared/components/color_picker/color_picker",
  id: "opacity_color",
  label: "Background Color",
  value: "#f5a623ff",
  opacity: true,
  no_format_toggle: true %>

<%# Format variations %>
<%= render "shared/components/color_picker/color_picker",
  id: "rgb_color",
  label: "RGB Format",
  value: "rgb(80, 227, 194)",
  format: "rgb" %>

<%= render "shared/components/color_picker/color_picker",
  id: "hsl_color",
  label: "HSL Format",
  value: "hsl(290, 87%, 47%)",
  format: "hsl" %>

<%= render "shared/components/color_picker/color_picker",
  id: "hsv_color",
  label: "HSV Format",
  value: "hsv(55, 89%, 97%)",
  format: "hsv" %>

<%# Custom swatches with form submission %>
<%= render "shared/components/color_picker/color_picker",
  id: "brand_palette",
  name: "settings[brand_color]",
  label: "Brand Color",
  value: "#4a5568",
  show_swatches: true,
  swatches: [
    "#1a202c", "#2d3748", "#4a5568", "#718096",
    "#fed7d7", "#fc8181", "#f56565", "#e53e3e"
  ] %>

Rendered usage example

Value: #3b82f6
Value: #f5a623ff
Value: rgb(80, 227, 194)
Value: hsl(290, 87%, 47%)
Value: hsv(55, 89%, 97%)
Value: #4a5568

Color Picker ViewComponent

Follow the Installation section first!
This component requires additional setup (gems, controllers, partials, or libraries) before using this ViewComponent. Please complete the Installation section on this page first.

1. Ensure the gem is installed

gem "view_component", "~> 4.2"

2. Copy component files

Download all 2 component files as a ZIP file.

Download all files (ZIP)

After downloading, unzip and copy the color_picker/ folder to your app/components/ directory.

Copy these files to your app/components/color_picker/ directory:

3. Usage example

<%# Enhanced color picker %>
<%= render ColorPicker::Component.new(
  id: "enhanced_color",
  label: "Brand Color",
  value: "#3b82f6",
  format: :hex
) %>

<%# Color picker with opacity %>
<%= render ColorPicker::Component.new(
  id: "opacity_color",
  label: "Background Color",
  value: "#f5a623ff",
  opacity: true,
  no_format_toggle: true
) %>

<%# Format variations %>
<%= render ColorPicker::Component.new(
  id: "rgb_color",
  label: "RGB Format",
  value: "rgb(80, 227, 194)",
  format: :rgb
) %>

<%= render ColorPicker::Component.new(
  id: "hsl_color",
  label: "HSL Format",
  value: "hsl(290, 87%, 47%)",
  format: :hsl
) %>

<%= render ColorPicker::Component.new(
  id: "hsv_color",
  label: "HSV Format",
  value: "hsv(55, 89%, 97%)",
  format: :hsv
) %>

<%# Custom swatches with form submission %>
<%= render ColorPicker::Component.new(
  id: "brand_palette",
  name: "settings[brand_color]",
  label: "Brand Color",
  value: "#4a5568",
  show_swatches: true,
  swatches: [
    "#1a202c", "#2d3748", "#4a5568", "#718096",
    "#fed7d7", "#fc8181", "#f56565", "#e53e3e"
  ]
) %>

Rendered usage example

Value: #3b82f6
Value: #f5a623ff
Value: rgb(80, 227, 194)
Value: hsl(290, 87%, 47%)
Value: hsv(55, 89%, 97%)
Value: #4a5568

Color Picker Rails Components

Add color selection functionality to your forms with Shoelace-powered color pickers, swatches, opacity controls, and multiple color formats. Perfect for theme customization, design tools, and user preferences.

Installation

1. Stimulus Controller Setup

Start by adding the following controller to your project:

import { Controller } from "@hotwired/stimulus"

// Shoelace Color Picker Controller
//
// Keeps a value display and optional hidden form input in sync with <sl-color-picker>.
// Also supports optional custom swatch buttons.
export default class extends Controller {
  static targets = ["picker", "value", "input", "swatch"]

  static values = {
    defaultValue: { type: String, default: "#3b82f6" }
  }

  connect() {
    this.sync(this.currentColor())
  }

  change(event) {
    const color = event.target.value
    this.sync(color)
    this.dispatchChangeEvent(color)
  }

  selectSwatch(event) {
    event.preventDefault()
    const color = event.currentTarget.dataset.color

    if (!color || !this.hasPickerTarget) {
      return
    }

    this.pickerTarget.value = color
    this.sync(color)
    this.dispatchChangeEvent(color)
  }

  currentColor() {
    if (this.hasPickerTarget && this.pickerTarget.value) {
      return this.pickerTarget.value
    }

    return this.defaultValueValue
  }

  sync(color) {
    const nextColor = color || this.defaultValueValue

    if (this.hasPickerTarget && this.pickerTarget.value !== nextColor) {
      this.pickerTarget.value = nextColor
    }

    if (this.hasValueTarget) {
      this.valueTarget.textContent = nextColor
    }

    if (this.hasInputTarget) {
      this.inputTarget.value = nextColor
    }

    this.updateSwatchSelection(nextColor)
  }

  updateSwatchSelection(selectedColor) {
    const normalized = (selectedColor || "").toLowerCase()

    this.swatchTargets.forEach((swatch) => {
      const swatchColor = (swatch.dataset.color || "").toLowerCase()
      const isSelected = swatchColor === normalized

      swatch.setAttribute("aria-pressed", isSelected ? "true" : "false")
      swatch.classList.toggle("ring-neutral-500", isSelected)
      swatch.classList.toggle("dark:ring-neutral-400", isSelected)
      swatch.classList.toggle("ring-transparent", !isSelected)
    })
  }

  dispatchChangeEvent(color) {
    const event = new CustomEvent("color-picker:change", {
      bubbles: true,
      detail: { color }
    })

    this.element.dispatchEvent(event)
  }
}

2. Shoelace Color Picker

For advanced color picker features, you can use Shoelace's color picker component.

<!-- Shoelace -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/components/color-picker/color-picker.js"></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/light.css"
/>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/dark.css"
/>

3. Shoelace Styling

If you want to have more neutral accent colors instead of the default blue and more rounded corners, you can use the following CSS to style the Shoelace color picker:

/* Shoelace Neutral styles */
:root {
  --sl-color-primary-50: var(--sl-color-neutral-50) !important;
  --sl-color-primary-100: var(--sl-color-neutral-100) !important;
  --sl-color-primary-200: var(--sl-color-neutral-200) !important;
  --sl-color-primary-300: var(--sl-color-neutral-300) !important;
  --sl-color-primary-400: var(--sl-color-neutral-400) !important;
  --sl-color-primary-500: var(--sl-color-neutral-500) !important;
  --sl-color-primary-600: var(--sl-color-neutral-600) !important;
  --sl-color-primary-700: var(--sl-color-neutral-700) !important;
  --sl-color-primary-800: var(--sl-color-neutral-800) !important;
  --sl-color-primary-900: var(--sl-color-neutral-900) !important;
  --sl-color-primary-950: var(--sl-color-neutral-950) !important;

  --sl-input-focus-ring-color: hsla(0, 0%, 81%, 0.4) !important;

  --sl-border-radius-medium: 0.5rem !important;
  --sl-border-radius-large: 0.75rem !important;
}

Shoelace Examples

Basic color picker

A simple Shoelace color picker with HEX output.

Current value: #3b82f6
<%# Basic Shoelace Color Picker (raw Stimulus markup) %>
<div class="space-y-4" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="#3b82f6">
  <div class="flex flex-col items-center gap-2">
    <sl-color-picker
      id="basic-picker"
      label="Choose a color"
      value="#3b82f6"
      format="hex"
      size="medium"
      data-shoelace-color-picker-target="picker"
      data-action="sl-change->shoelace-color-picker#change"
    ></sl-color-picker>
  </div>

  <div class="flex justify-center items-center gap-3 text-sm">
    <span class="text-neutral-600 dark:text-neutral-400">Current value:</span>
    <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" data-shoelace-color-picker-target="value">#3b82f6</code>
  </div>
</div>

Color picker with swatches

Shoelace color picker with an inline swatch palette for quick selection.

Selected swatch: #8b5cf6
<%# Shoelace Color Picker with Swatches (raw Stimulus markup) %>
<div class="space-y-4" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="#8b5cf6">
  <div class="flex flex-col items-center gap-2">
    <sl-color-picker
      id="swatches-picker"
      label="Theme Color"
      value="#8b5cf6"
      format="hex"
      size="medium"
      swatches="#ede9fe; #ddd6fe; #c4b5fd; #a78bfa; #8b5cf6; #7c3aed; #6d28d9; #5b21b6; #4c1d95"
      data-shoelace-color-picker-target="picker"
      data-action="sl-change->shoelace-color-picker#change"
    ></sl-color-picker>
  </div>

  <div class="flex justify-center items-center gap-3 text-sm">
    <span class="text-neutral-600 dark:text-neutral-400">Selected swatch:</span>
    <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" data-shoelace-color-picker-target="value">#8b5cf6</code>
  </div>
</div>

Enhanced color picker

Shoelace color picker with a modern interface and live value display.

Current value: rgb(59, 130, 246)
<%# Enhanced Shoelace Color Picker (raw Stimulus markup) %>
<div class="space-y-4" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="rgb(59, 130, 246)">
  <div class="flex flex-col items-center gap-2">
    <sl-color-picker
      id="enhanced-picker"
      label="Brand Color"
      value="rgb(59, 130, 246)"
      format="rgb"
      size="large"
      data-shoelace-color-picker-target="picker"
      data-action="sl-change->shoelace-color-picker#change"
    ></sl-color-picker>
  </div>

  <div class="flex justify-center items-center gap-3 text-sm">
    <span class="text-neutral-600 dark:text-neutral-400">Current value:</span>
    <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" data-shoelace-color-picker-target="value">rgb(59, 130, 246)</code>
  </div>
</div>

Color picker with opacity

Advanced color picker with alpha channel support for transparency control.

Hex (with alpha): #f5a623ff
<%# Shoelace Color Picker with Opacity (raw Stimulus markup) %>
<div class="space-y-4" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="#f5a623ff">
  <div class="flex flex-col items-center gap-2">
    <sl-color-picker
      id="opacity-picker"
      label="Background Color"
      value="#f5a623ff"
      format="hex"
      opacity
      no-format-toggle
      size="medium"
      data-shoelace-color-picker-target="picker"
      data-action="sl-change->shoelace-color-picker#change"
    ></sl-color-picker>
  </div>

  <div class="flex justify-center items-center gap-3 text-sm">
    <span class="text-neutral-600 dark:text-neutral-400">Hex (with alpha):</span>
    <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" data-shoelace-color-picker-target="value">#f5a623ff</code>
  </div>
</div>

Color format variations

Color pickers configured for different color format outputs: HEX, RGB, HSL, and HSV.

Choose the output format that best suits your needs

Output:
#4a90e2
Output:
rgb(80, 227, 194)
Output:
hsl(290, 87%, 47%)
Output:
hsv(55, 89%, 97%)
<%# Shoelace Color Picker with format variations (raw Stimulus markup) %>
<div class="space-y-6">
  <p class="text-sm text-neutral-500 dark:text-neutral-400 text-center">
    Choose the output format that best suits your needs
  </p>

  <div class="grid grid-cols-1 gap-6 md:grid-cols-2">
    <div class="space-y-3" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="#4a90e2">
      <div class="flex flex-col items-center">
        <sl-color-picker
          label="HEX Format"
          format="hex"
          value="#4a90e2"
          size="small"
          data-shoelace-color-picker-target="picker"
          data-action="sl-change->shoelace-color-picker#change"
        ></sl-color-picker>
      </div>
      <div class="text-center">
        <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div>
        <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" data-shoelace-color-picker-target="value">#4a90e2</code>
      </div>
    </div>

    <div class="space-y-3" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="rgb(80, 227, 194)">
      <div class="flex flex-col items-center">
        <sl-color-picker
          label="RGB Format"
          format="rgb"
          value="rgb(80, 227, 194)"
          size="small"
          data-shoelace-color-picker-target="picker"
          data-action="sl-change->shoelace-color-picker#change"
        ></sl-color-picker>
      </div>
      <div class="text-center">
        <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div>
        <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" data-shoelace-color-picker-target="value">rgb(80, 227, 194)</code>
      </div>
    </div>

    <div class="space-y-3" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="hsl(290, 87%, 47%)">
      <div class="flex flex-col items-center">
        <sl-color-picker
          label="HSL Format"
          format="hsl"
          value="hsl(290, 87%, 47%)"
          size="small"
          data-shoelace-color-picker-target="picker"
          data-action="sl-change->shoelace-color-picker#change"
        ></sl-color-picker>
      </div>
      <div class="text-center">
        <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div>
        <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" data-shoelace-color-picker-target="value">hsl(290, 87%, 47%)</code>
      </div>
    </div>

    <div class="space-y-3" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="hsv(55, 89%, 97%)">
      <div class="flex flex-col items-center">
        <sl-color-picker
          label="HSV Format"
          format="hsv"
          value="hsv(55, 89%, 97%)"
          size="small"
          data-shoelace-color-picker-target="picker"
          data-action="sl-change->shoelace-color-picker#change"
        ></sl-color-picker>
      </div>
      <div class="text-center">
        <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Output:</div>
        <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs text-neutral-700 dark:text-neutral-300" data-shoelace-color-picker-target="value">hsv(55, 89%, 97%)</code>
      </div>
    </div>
  </div>
</div>

Color picker with custom palette

Enhanced color picker with a custom color palette for consistent brand colors.

Selected Color:
#4a5568

Brand palette

<%# Shoelace Color Picker with custom buttons (raw Stimulus markup) %>
<div class="space-y-6" data-controller="shoelace-color-picker" data-shoelace-color-picker-default-value-value="#4a5568">
  <div class="flex flex-col items-center gap-3">
    <sl-color-picker
      id="brand-picker"
      label="Brand Color"
      value="#4a5568"
      format="hex"
      size="medium"
      data-shoelace-color-picker-target="picker"
      data-action="sl-change->shoelace-color-picker#change"
    ></sl-color-picker>

    <input
      type="hidden"
      name="settings[brand_color]"
      value="#4a5568"
      data-shoelace-color-picker-target="input"
    >

    <div class="text-sm text-center">
      <div class="text-xs text-neutral-500 dark:text-neutral-400 mb-1">Selected Color:</div>
      <code class="px-2 py-1 bg-neutral-100 dark:bg-neutral-800 rounded font-mono text-xs" data-shoelace-color-picker-target="value">#4a5568</code>
    </div>
  </div>

  <div class="space-y-2">
    <p class="text-xs text-neutral-500 dark:text-neutral-400 uppercase tracking-wide text-center">Brand palette</p>
    <div class="flex justify-center gap-2 flex-wrap">
      <% ["#1a202c", "#2d3748", "#4a5568", "#718096", "#a0aec0", "#e53e3e", "#c53030", "#742a2a"].each do |color| %>
        <% selected_classes = color.casecmp?("#4a5568") ? "ring-neutral-500 dark:ring-neutral-400" : "ring-transparent" %>
        <button
          type="button"
          class="h-8 w-8 rounded-md border border-black/15 dark:border-white/20 transition-transform hover:scale-110 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-neutral-600 dark:focus-visible:outline-neutral-200 ring-2 ring-offset-2 dark:ring-offset-neutral-900 <%= selected_classes %>"
          style="background-color: <%= color %>;"
          data-color="<%= color %>"
          data-shoelace-color-picker-target="swatch"
          data-action="click->shoelace-color-picker#selectSwatch"
          aria-label="Pick <%= color %>"
          aria-pressed="<%= color.casecmp?("#4a5568") ? "true" : "false" %>"
        ></button>
      <% end %>
    </div>
  </div>
</div>

Configuration

Shoelace color picker supports multiple formats, opacity, custom swatches, and events out of the box.

Basic Shoelace Usage

Minimal setup for a color input:

<sl-color-picker
  label="Brand Color"
  value="#3b82f6"
  format="hex"
  size="medium"
></sl-color-picker>

With Custom Swatches

Provide brand or preset colors directly on the picker:

<sl-color-picker
  label="Theme Color"
  value="#8b5cf6"
  swatches="#8b5cf6; #3b82f6; #10b981"
></sl-color-picker>

Shoelace Color Picker Options

Available attributes for Shoelace color picker customization:

Attribute Default Description
value #ffffff The current color value
format hex Output format: hex, rgb, hsl, or hsv
opacity false Show opacity slider for alpha channel
swatches "" Custom color swatches (semicolon-separated)
label "" Label text for the color picker
size medium Size variant: small, medium, or large

JavaScript Events

Handle color selection events:

// Shoelace native event
document.querySelector('sl-color-picker').addEventListener('sl-change', (e) => {
  console.log('Color changed:', e.target.value);
});

// Rails Blocks wrapper event (shared partial and ViewComponent)
document.addEventListener('color-picker:change', (e) => {
  console.log('Color changed:', e.detail.color);
});

Accessibility

  • Keyboard Support: Shoelace color picker supports keyboard interaction and focus management
  • Screen Readers: Use proper labels and aria-labels
  • Color Contrast: Ensure selected colors meet WCAG contrast requirements

Browser Support

  • Shoelace: Requires modern browsers with Web Components support
  • Fallback: Add a hidden/text fallback only if you need legacy browser support

Table of contents

Powered by

Get notified when new components come out