# Color Picker

Popover-based color picker with a saturation and brightness plane, hue strip, hex input with eyedropper, and HSL, RGB, or HSV channel sliders. Optional preset swatches. Composable Root, Trigger, Content, Plane, Hue, Preview, HexInput, Channels, and Presets.

- Package: `@mielui/svelte`
- Component version: `3.1.0`
- Depends on Mielui components: _internal/utils, popover, button, slider
- Shared utilities: hugeicons-icon, utils.cn, utils.createContext

## Install

~~~~sh
pnpm dlx @mielui/svelte add color-picker
~~~~

## API

This reference is generated at build time from the component manifest, public `index.ts`, and documentation examples below. Changes to those source files are reflected here in the published Markdown. Standard Svelte and HTML attributes accepted by the exported prop types are supported.


### Channels

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Content

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | (string & (ClassValue \| null)) \| undefined | - | No | No | Classes added to the element. |
| tabindex | number \| undefined | - | No | No | Tab index of the panel. |
| role | "dialog" \| "alertdialog" \| "menu" \| "listbox" \| "none" \| undefined | - | No | No | ARIA role of the panel. |
| surface | "solid" \| "glass" \| undefined | - | No | No | Surface treatment. Omit it to inherit `--mielui-surface` from the theme. |
| surfaceClass | string \| undefined | - | No | No | Classes for the inset surface (where children live) — padding, layout, background overrides. The `class` prop styles the outer Panel frame. |
| allowClickOutside | boolean \| undefined | - | No | No | Closes when the pointer is pressed outside it. Set false to keep it open until it is dismissed another way. |
| dismissLayer | boolean \| undefined | - | No | No | Render the full-viewport dismiss layer under the panel while open. Defaults to `true`. Set to `false` for triggers that must stay clickable while open (e.g. an input-style combobox trigger); outside pointer dismissal still applies via `allowClickOutside`. |
| portal | boolean \| undefined | - | No | No | Moves the panel to the end of the document so ancestors cannot clip it. Set false to render it in place. |
| refElement | VirtualElement \| undefined | - | No | No | Positions the panel against this element or virtual element instead of the trigger. The panel then opens to the right of it, as a submenu does. |
| focusTrap | boolean \| undefined | - | No | No | Trap Tab focus inside the panel while open. Defaults to `true`. |
| lockScroll | boolean \| undefined | - | No | No | Lock document scrolling while the panel is open. Defaults to `true`. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### HexInput

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Hue

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Plane

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Presets

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Preview

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Root

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| labels | ColorPickerLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| label | string \| undefined | - | No | No | Accessible name of the trigger. |
| value | string \| undefined | '' | No | Yes | Selected color as a hex string. Bindable. |
| onValueChange | ((value: string) => void) \| undefined | - | No | No | Called with the new value when it changes. |
| options | ColorOption[] \| undefined | [] | No | No | Preset swatches offered at the bottom of the panel. |
| format | ColorFormat \| undefined | 'hsl' | No | No | Channel controls to show: HSL, RGB, or HSV. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Trigger

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| variant | "outline" \| "secondary" \| "ghost" \| undefined | 'outline' | No | No | Trigger style -- matches Button variants. Defaults to outlined. |
| class | string \| undefined | - | No | No | Classes added to the element. |



### Public types

~~~~ts
import type { PopoverContentProps } from '@mielui/svelte/components/popover';
import type { DefaultProps } from '@mielui/svelte/utils';
import type { Snippet } from 'svelte';
import type { HTMLAttributes } from 'svelte/elements';
import Channels from './color-picker-channels.svelte';
import Content from './color-picker-content.svelte';
import HexInput from './color-picker-hex-input.svelte';
import Hue from './color-picker-hue.svelte';
import Plane from './color-picker-plane.svelte';
import Presets from './color-picker-presets.svelte';
import Preview from './color-picker-preview.svelte';
import Root from './color-picker-root.svelte';
import Trigger from './color-picker-trigger.svelte';
import type { ColorFormat, ColorOption } from './context';

export type { ColorFormat, ColorOption, ColorPickerContext } from './context';

export type ColorPickerLabels = {
    /** Trigger text and name when no color is chosen. */
    choose?: string;
    /** Accessible name of the panel when Root has no `label`. */
    picker?: string;
    /** Accessible name of the hex input. */
    hex?: string;
    /** Accessible name of the button that picks a color from the screen. */
    eyedropper?: string;
    /** Accessible name of the trigger when Root has a `label`, given that label and the color. */
    trigger?: (label: string, color: string) => string;
    /** Accessible name of the hue slider and channel. */
    hue?: string;
    /** Accessible name of the saturation slider and channel. */
    saturation?: string;
    /** Accessible name of the HSL lightness channel. */
    lightness?: string;
    /** Accessible name of the HSV brightness slider and channel. */
    brightness?: string;
    /** Accessible name of the RGB red channel. */
    red?: string;
    /** Accessible name of the RGB green channel. */
    green?: string;
    /** Accessible name of the RGB blue channel. */
    blue?: string;
};

export type ColorPickerProps = {
    /**
     * Overrides the built-in text and accessible names. Every key is optional and English is the
     * fallback.
     */
    labels?: ColorPickerLabels;
    /** Accessible name of the trigger. */
    label?: string;
    /** Selected color as a hex string. Bindable. */
    value?: string;
    /** Called with the new value when it changes. */
    onValueChange?: (value: string) => void;
    /** Preset swatches offered at the bottom of the panel. */
    options?: ColorOption[];
    /** Channel controls to show: HSL, RGB, or HSV. */
    format?: ColorFormat;
    /** Content rendered inside. */
    children?: Snippet;
} & DefaultProps;

export type ColorPickerContentProps = Omit<PopoverContentProps, 'children'> & {
    /** Content rendered inside. */
    children?: Snippet;
};

export { Channels, Content, HexInput, Hue, Plane, Presets, Preview, Root, Trigger };

export type ColorPickerPlaneProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export type ColorPickerHueProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export type ColorPickerPreviewProps = Omit<HTMLAttributes<HTMLSpanElement>, 'children'>;

export type ColorPickerHexInputProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export type ColorPickerChannelsProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export type ColorPickerPresetsProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
~~~~

## Examples

### Composition

~~~~svelte
<script lang="ts">
    import type { ColorOption } from '@mielui/svelte/components/color-picker';
    import * as ColorPicker from '@mielui/svelte/components/color-picker';

    const options: ColorOption[] = [
        {
            label: 'Indigo',
            value: '#5e6ad2'
        },
        {
            label: 'Rose',
            value: '#e65c86'
        },
        {
            label: 'Green',
            value: '#36a375'
        }
    ];

    let value = $state('#5e6ad2');
</script>

<ColorPicker.Root bind:value {options} format="rgb" label="Accent color">
    <ColorPicker.Trigger />
    <ColorPicker.Content>
        <ColorPicker.Presets />
        <div class="flex items-center gap-2 px-2">
            <ColorPicker.Preview />
            <ColorPicker.HexInput class="flex-1" />
        </div>
        <ColorPicker.Channels />
    </ColorPicker.Content>
</ColorPicker.Root>
~~~~

### Default

~~~~svelte
<script lang="ts">
    import * as ColorPicker from '@mielui/svelte/components/color-picker';

    let value = $state('#5e6ad2');
</script>

<ColorPicker.Root bind:value label="Brand color">
    <ColorPicker.Trigger />
    <ColorPicker.Content />
</ColorPicker.Root>
~~~~

### Formats

~~~~svelte
<script lang="ts">
    import * as ColorPicker from '@mielui/svelte/components/color-picker';

    let hsl = $state('#5e6ad2');
    let rgb = $state('#5e6ad2');
    let hsv = $state('#5e6ad2');
</script>

<div class="flex flex-wrap items-start justify-center gap-4">
    <ColorPicker.Root bind:value={hsl} format="hsl" label="HSL">
        <ColorPicker.Trigger />
        <ColorPicker.Content />
    </ColorPicker.Root>
    <ColorPicker.Root bind:value={rgb} format="rgb" label="RGB">
        <ColorPicker.Trigger />
        <ColorPicker.Content />
    </ColorPicker.Root>
    <ColorPicker.Root bind:value={hsv} format="hsv" label="HSV">
        <ColorPicker.Trigger />
        <ColorPicker.Content />
    </ColorPicker.Root>
</div>
~~~~

### Glass

~~~~svelte
<script lang="ts">
    import * as ColorPicker from '@mielui/svelte/components/color-picker';

    let value = $state('#5e6ad2');
</script>

<ColorPicker.Root bind:value label="Highlight color">
    <ColorPicker.Trigger />
    <ColorPicker.Content surface="glass" />
</ColorPicker.Root>
~~~~

### With Presets

~~~~svelte
<script lang="ts">
    import type { ColorOption } from '@mielui/svelte/components/color-picker';
    import * as ColorPicker from '@mielui/svelte/components/color-picker';

    const options: ColorOption[] = [
        {
            label: 'Blue',
            value: '#2563eb'
        },
        {
            label: 'Indigo',
            value: '#4f46e5'
        },
        {
            label: 'Violet',
            value: '#7c3aed'
        },
        {
            label: 'Pink',
            value: '#db2777'
        },
        {
            label: 'Rose',
            value: '#e11d48'
        }
    ];

    let value = $state('#4f46e5');
</script>

<ColorPicker.Root bind:value {options} label="Label color">
    <ColorPicker.Trigger />
    <ColorPicker.Content />
</ColorPicker.Root>
~~~~

For the rendered reference, visit [/docs/components/color-picker](/docs/components/color-picker).
