Skip to content

Color Picker

The ColorPicker field renders a color selection interface with HSL sliders, a color value input, swatches, an eyedropper tool, and copy-to-clipboard. The value is stored as a color string.

Basic Usage

Example
php
use InertiaUI\Forms\Fields\ColorPicker;

ColorPicker::make('brand_color');

The default format is hex, which automatically adds the hex_color validation rule. Switching to rgb or hsl removes that managed format rule and keeps the base string rule. Rules you add explicitly with rule() or rules() are preserved.

Color Format

Choose between hex, rgb, and hsl output formats:

Example
php
ColorPicker::make('color')->hex();   // #3b82f6
ColorPicker::make('color')->rgb();   // rgb(59, 130, 246)
ColorPicker::make('color')->hsl();   // hsl(217, 91%, 60%)

You may also use the format() method directly:

php
ColorPicker::make('color')->format('rgb');

The hex_color validation rule is only added when using the hex format.

Swatches

Provide a set of preset colors for quick selection:

Example
php
ColorPicker::make('theme_color')->swatches([
    '#ef4444', '#f97316', '#eab308',
    '#22c55e', '#3b82f6', '#8b5cf6',
    '#ec4899', '#6b7280', '#000000',
]);

The default swatches value is null, which tells the frontend to use the built-in palette. Pass an array to replace that palette with your own colors:

php
ColorPicker::make('brand_color')->swatches([
    '#1e40af',
    '#059669',
    '#d97706',
]);

Pass an empty array when you want no preset swatches. You may call swatches(null) again to return to the frontend default palette.

Named swatches can show the selected swatch name in the closed trigger. The array key is the submitted color value, and the array value is the swatch name:

Example
php
ColorPicker::make('brand_color')
    ->swatches([
        '#1e40af' => 'Brand color',
        '#059669' => 'Accent color',
    ])
    ->showSwatchName();

When showSwatchName() is enabled and the selected color does not match a named swatch, the trigger falls back to the formatted color value.

Alpha Channel

Enable the alpha/opacity slider:

Example
php
ColorPicker::make('overlay_color')->showAlpha();

This is disabled by default. Opacity below 100% submits alpha in the selected output format:

php
ColorPicker::make('color')->showAlpha()->hex(); // #3b82f680
ColorPicker::make('color')->showAlpha()->rgb(); // rgba(59, 130, 246, 0.5)
ColorPicker::make('color')->showAlpha()->hsl(); // hsla(217, 91%, 60%, 0.5)

Color Input

The text input for typing a color value is visible by default. It accepts hex, rgb/rgba, and hsl/hsla values, then normalizes the submitted value to the configured output format. Hide it when users should choose from swatches only:

Example
php
ColorPicker::make('color')
    ->swatches([
        '#1e40af' => 'Brand blue',
        '#059669' => 'Accent green',
        '#d97706' => 'Warning orange',
        '#dc2626' => 'Danger red',
        '#7c3aed' => 'Violet',
        '#db2777' => 'Pink',
    ])
    ->showSwatchName()
    ->hideInput();

// Or use the explicit method
ColorPicker::make('color')->showInput(false);

With input controls hidden, the popover shows only the swatch list. The HSL sliders, alpha slider, text input, eyedropper button, and copy button are hidden too. Pair hideInput() with a custom swatch array so users still have selectable colors.

hideInput() only controls the popover controls. Use showSwatchName() when the closed trigger should show a selected swatch name.

Clearable

Allow the user to clear the selected color:

php
ColorPicker::make('accent_color')->clearable();

Default Color

Set a fallback color that's used when no value is set:

php
ColorPicker::make('background')->defaultColor('#ffffff');

The default color is a visual fallback; it does not submit a value until the user selects or types a color.

Eyedropper

The eyedropper button lets users pick a color from anywhere on the screen. It's enabled by default in supported browsers (Chromium only):

Example
php
ColorPicker::make('color')
    ->defaultColor('#3b82f6')
    ->showEyeDropper();

Hide it:

php
ColorPicker::make('color')->hideEyeDropper();

// Or use the explicit method
ColorPicker::make('color')->showEyeDropper(false);

Copy to Clipboard

The copy action is enabled by default, but the button is shown only when input controls are visible and the field has an actual value. A defaultColor() preview does not show the copy button until the user selects or types a color.

The copied value matches the normalized display value for the configured format. Hex values are copied in uppercase, such as #3B82F6; rgb and hsl fields copy the normalized rgb(...) or hsl(...) string. Disable the action:

php
ColorPicker::make('color')->copyable(false);

Readonly

ColorPicker does not currently support a readonly state. Use disabled() when users should not be able to change the value.

Palette With Alpha

php
ColorPicker::make('brand_color')
    ->label('Brand Color')
    ->help('Used throughout the dashboard')
    ->swatches([
        '#1e40af', '#059669', '#d97706',
        '#dc2626', '#7c3aed', '#db2777',
    ])
    ->showAlpha()
    ->clearable()
    ->required();

ColorPicker-specific methods compose with shared field APIs. Use Form Class for labels and help text, Model Binding for default(), Validation for rules and precognition, Conditional Visibility, Authorization, and Styling for classes, layout, and part classes.

Using the Component Directly

ColorPicker is exported from each stack's components subpath. Pass serialized form.getField(...) props during manual rendering, or bind a local color value for standalone usage.

vue
<script setup lang="ts">
import { ColorPicker } from '@inertiaui/form-vue/components'
import { ref } from 'vue'

const brandColor = ref<string | null>('#1e40af')
const badgeColor = ref<string | null>(null)
const swatches = ['#1e40af', '#059669', '#d97706', '#dc2626', '#7c3aed', '#db2777']
const namedSwatches = [
    { color: '#1e40af', label: 'Brand blue' },
    { color: '#059669', label: 'Accent green' },
]
const pickerParts = {
    dropdown: 'max-h-80',
    swatch: 'rounded-md',
    slider: 'shadow-none',
    preview: 'ring-zinc-300',
    action: 'text-zinc-500',
}

const trackOpenIntent = () => {}
</script>

<template>
    <div class="grid gap-4">
        <ColorPicker
            v-model="brandColor"
            id="brand-color"
            name="brand_color"
            label="Brand color"
            help="Used in dashboard accents."
            format="hex"
            :swatches="swatches"
            show-input
            show-alpha
            show-eye-dropper
            copyable
            clearable
            default-color="#1e40af"
            control-class="min-w-64"
            wrapper-class="max-w-xl"
            :part-classes="pickerParts"
            data-testid="brand-color"
            @click="trackOpenIntent"
        />

        <ColorPicker
            v-model="badgeColor"
            name="badge_color"
            label="Badge color"
            :swatches="namedSwatches"
            :show-input="false"
            show-swatch-name
            default-color="#059669"
        />
    </div>
</template>
tsx
import { useState } from 'react'
import { ColorPicker } from '@inertiaui/form-react/components'

const swatches = ['#1e40af', '#059669', '#d97706', '#dc2626', '#7c3aed', '#db2777']
const namedSwatches = [
    { color: '#1e40af', label: 'Brand blue' },
    { color: '#059669', label: 'Accent green' },
]
const pickerParts = {
    dropdown: 'max-h-80',
    swatch: 'rounded-md',
    slider: 'shadow-none',
    preview: 'ring-zinc-300',
    action: 'text-zinc-500',
}

export default function BrandColorPicker() {
    const [brandColor, setBrandColor] = useState<string | null>('#1e40af')
    const [badgeColor, setBadgeColor] = useState<string | null>(null)
    const trackOpenIntent = () => {}

    return (
        <div className="grid gap-4">
            <ColorPicker
                value={brandColor}
                onValueChange={setBrandColor}
                id="brand-color"
                name="brand_color"
                label="Brand color"
                help="Used in dashboard accents."
                format="hex"
                swatches={swatches}
                showInput
                showAlpha
                showEyeDropper
                copyable
                clearable
                defaultColor="#1e40af"
                controlClass="min-w-64"
                wrapperClass="max-w-xl"
                partClasses={pickerParts}
                data-testid="brand-color"
                onClick={trackOpenIntent}
            />

            <ColorPicker
                value={badgeColor}
                onValueChange={setBadgeColor}
                name="badge_color"
                label="Badge color"
                swatches={namedSwatches}
                showInput={false}
                showSwatchName
                defaultColor="#059669"
            />
        </div>
    )
}

Vue uses v-model. React uses controlled value plus onValueChange. Standalone values are normalized color strings or null. defaultColor changes only the empty visual state, and name renders a hidden input for native form submission. Direct Vue and React usage may pass named swatches as { color: '#1e40af', label: 'Brand color' } objects in the same swatches array.

Native attributes and listeners target the underlying trigger <button>; see Native Attributes And Events.