# Color Picker

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
---

<ColorPicker
  label="Brand color"
  name="brand-color"
  defaultValue="#ff000080"
  alpha
  swatches={swatches}
/>
```
  </div>
  <div slot="react">
```tsx
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];

export function Example() {
  return (
    <ColorPicker
      label="Brand color"
      name="brand-color"
      defaultValue="#ff000080"
      alpha
      swatches={swatches}
    />
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
</script>

<template>
  <ColorPicker
    label="Brand color"
    name="brand-color"
    defaultValue="#ff000080"
    alpha
    :swatches="swatches"
  />
</template>
```
  </div>
</FrameworkCodeSwitcher>

`ColorPicker` renders a complete popover editor when it has no children. The default editor includes
the color area, hue and alpha sliders, exact value input, styled format selector, EyeDropper action,
and any supplied swatches. It also appends the hidden form input automatically.

## Installation

```bash
npx starwind@latest add color-picker --framework astro
```
</DocsTabsContent>
```bash
npx starwind@latest add color-picker --framework react
```
</DocsTabsContent>
```bash
npx starwind@latest add color-picker --framework vue
```
</DocsTabsContent>
</DocsTabs>

To vendor the unstyled adapter source for raw anatomy customization, run
`starwind primitives add color-picker`. The [Runtime controller
reference](/docs/runtime/#create-color-picker) documents the underlying behavior API.

## Usage

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
---

<ColorPicker
  label="Brand color"
  name="brand-color"
  defaultValue="#ff000080"
  alpha
  swatches={swatches}
/>
```
  </div>
  <div slot="react">
```tsx
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];

export function Example() {
  return (
    <ColorPicker
      label="Brand color"
      name="brand-color"
      defaultValue="#ff000080"
      alpha
      swatches={swatches}
    />
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#ef4444", label: "Red" },
  { value: "#f59e0b", label: "Amber" },
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
</script>

<template>
  <ColorPicker
    label="Brand color"
    name="brand-color"
    defaultValue="#ff000080"
    alpha
    :swatches="swatches"
  />
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Sizes

`ColorPicker` owns trigger-side and inline anatomy. `ColorPickerContent` independently owns the
portaled editor, because it cannot inherit styling state across the portal boundary. Both scopes
accept `sm`, `md` (the default), or `lg`. Default composition passes the root size to its owned
content automatically.

`ColorPickerInput` accepts `formatContentSize` only for its nested Select popup. Use it when a
custom editor needs that second portal to differ from the editor scope.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";
---

<div class="space-y-10">
  <section class="mx-auto max-w-md space-y-3">
    <h3 class="text-sm font-medium">Small</h3>
    <ColorPicker size="sm" label="Compact brand color" defaultValue="#ef4444" />
  </section>

  <section class="mx-auto max-w-md space-y-3">
    <h3 class="text-sm font-medium">Large</h3>
    <ColorPicker size="lg" label="Large accent color" defaultValue="#0ea5e9" />
  </section>

  <section class="mx-auto max-w-md space-y-3">
    <h3 class="text-sm font-medium">Independent popup size</h3>
    <ColorPicker size="sm" defaultValue="#8b5cf6">
      <ColorPickerTrigger>Compact trigger</ColorPickerTrigger>
      <ColorPickerContent size="lg" aria-label="Large color editor" />
    </ColorPicker>
  </section>
</div>
```
  </div>
  <div slot="react">
```tsx
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";

export function Example() {
  return (
    <div className="space-y-10">
      <section className="mx-auto max-w-md space-y-3">
        <h3 className="text-sm font-medium">Small</h3>
        <ColorPicker size="sm" label="Compact brand color" defaultValue="#ef4444" />
      </section>

      <section className="mx-auto max-w-md space-y-3">
        <h3 className="text-sm font-medium">Large</h3>
        <ColorPicker size="lg" label="Large accent color" defaultValue="#0ea5e9" />
      </section>

      <section className="mx-auto max-w-md space-y-3">
        <h3 className="text-sm font-medium">Independent popup size</h3>
        <ColorPicker size="sm" defaultValue="#8b5cf6">
          <ColorPickerTrigger>Compact trigger</ColorPickerTrigger>
          <ColorPickerContent size="lg" aria-label="Large color editor" />
        </ColorPicker>
      </section>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";
</script>

<template>
  <div class="space-y-10">
    <section class="mx-auto max-w-md space-y-3">
      <h3 class="text-sm font-medium">Small</h3>
      <ColorPicker size="sm" label="Compact brand color" defaultValue="#ef4444" />
    </section>

    <section class="mx-auto max-w-md space-y-3">
      <h3 class="text-sm font-medium">Large</h3>
      <ColorPicker size="lg" label="Large accent color" defaultValue="#0ea5e9" />
    </section>

    <section class="mx-auto max-w-md space-y-3">
      <h3 class="text-sm font-medium">Independent popup size</h3>
      <ColorPicker size="sm" defaultValue="#8b5cf6">
        <ColorPickerTrigger>Compact trigger</ColorPickerTrigger>
        <ColorPickerContent size="lg" aria-label="Large color editor" />
      </ColorPicker>
    </section>
  </div>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Respond to Color Changes

Use value changes for immediate UI such as previews. In React, control the picker with `value` and
`onValueChange`. In Astro, listen for `starwind:value-change` on the root and read
`event.detail.valueAsString`.

For work that should happen only after an interaction finishes—such as persisting a preference—use
React's `onValueCommitted` or Astro's `starwind:value-committed` event instead.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import type { ColorPickerValueChangeDetails } from "@starwind-ui/astro/color-picker";
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
---

<div class="grid gap-5 rounded-lg border p-5 sm:grid-cols-[8rem_1fr]">
  <div
    class="aspect-square rounded-md border shadow-sm"
    style="background-color: #4f46e5"
    data-color-preview
    aria-hidden="true"
  />
  <div class="space-y-3">
    <ColorPicker
      inline
      id="preview-color"
      label="Preview color"
      defaultValue="#4f46e5"
      alpha={false}
      formatControl="native"
      showEyeDropper={false}
      swatches={swatches}
    />
    <output class="text-muted-foreground block text-sm tabular-nums" data-color-value>
      #4f46e5
    </output>
  </div>
</div>

<script>
  const root = document.querySelector("#preview-color");
  const preview = document.querySelector<HTMLElement>("[data-color-preview]");
  const value = document.querySelector<HTMLOutputElement>("[data-color-value]");

  root?.addEventListener("starwind:value-change", (event) => {
    const { valueAsString } = (event as CustomEvent<ColorPickerValueChangeDetails>).detail;
    if (preview) preview.style.backgroundColor = valueAsString;
    if (value) value.value = valueAsString;
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import {
  parseColor,
  type ColorPickerColor,
  type ColorPickerFormat,
} from "@starwind-ui/react/color-picker";
import { useState } from "react";
import { ColorPicker } from "@/components/starwind/color-picker";

export function Example() {
  const [value, setValue] = useState<ColorPickerColor | null>(parseColor("#4f46e5"));
  const [format, setFormat] = useState<ColorPickerFormat>("hex");
  const color = value?.toString("hex") ?? "transparent";

  return (
    <div className="grid gap-5 rounded-lg border p-5 sm:grid-cols-[8rem_1fr]">
      <div
        className="aspect-square rounded-md border shadow-sm"
        style={{ backgroundColor: color }}
        aria-hidden="true"
      />
      <div className="space-y-3">
        <ColorPicker
          inline
          label="Preview color"
          value={value}
          onValueChange={setValue}
          format={format}
          onFormatChange={setFormat}
          alpha={false}
          formatControl="native"
          showEyeDropper={false}
          swatches={[
            { value: "#10b981", label: "Emerald" },
            { value: "#0ea5e9", label: "Sky" },
            { value: "#8b5cf6", label: "Violet" },
          ]}
        />
        <output className="text-muted-foreground block text-sm tabular-nums">
          {color}
        </output>
      </div>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import type { ColorPickerValueChangeDetails } from "@starwind-ui/vue/color-picker";
import { ColorPicker } from "@/components/starwind/color-picker";
import { ref } from "vue";

const swatches = [
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];

const color = ref("#4f46e5");
function updateColor(_value: unknown, detail: ColorPickerValueChangeDetails) {
  color.value = detail.valueAsString;
}
</script>

<template>
  <div class="grid gap-5 rounded-lg border p-5 sm:grid-cols-[8rem_1fr]">
    <div
      class="aspect-square rounded-md border shadow-sm"
      :style="{ backgroundColor: color }"
      data-color-preview
      aria-hidden="true"
    />
    <div class="space-y-3">
      <ColorPicker
        inline
        id="preview-color"
        label="Preview color"
        defaultValue="#4f46e5"
        @value-change="updateColor"
        :alpha="false"
        formatControl="native"
        :showEyeDropper="false"
        :swatches="swatches"
      />
      <output class="text-muted-foreground block text-sm tabular-nums" data-color-value>
        {{ color }}
      </output>
    </div>
  </div>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Inline Editor

Set `inline` when people benefit from seeing the full editor without opening a popover, such as in
a theme builder or design settings panel.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { ColorPicker } from "@/components/starwind/color-picker";
---

<section class="space-y-4 rounded-lg border p-5">
  <div>
    <h3 class="font-medium">Theme accent</h3>
    <p class="text-muted-foreground text-sm">
      Used for links, focus rings, and primary actions.
    </p>
  </div>
  <ColorPicker
    inline
    label="Accent color"
    defaultValue="#7c3aed"
    alpha={false}
    showEyeDropper={false}
    swatches={[
      { value: "#10b981", label: "Emerald" },
      { value: "#0ea5e9", label: "Sky" },
      { value: "#8b5cf6", label: "Violet" },
    ]}
  />
</section>
```
  </div>
  <div slot="react">
```tsx
import { ColorPicker } from "@/components/starwind/color-picker";

export function Example() {
  return (
    <section className="space-y-4 rounded-lg border p-5">
      <div>
        <h3 className="font-medium">Theme accent</h3>
        <p className="text-muted-foreground text-sm">
          Used for links, focus rings, and primary actions.
        </p>
      </div>
      <ColorPicker
        inline
        label="Accent color"
        defaultValue="#7c3aed"
        alpha={false}
        showEyeDropper={false}
        swatches={[
          { value: "#10b981", label: "Emerald" },
          { value: "#0ea5e9", label: "Sky" },
          { value: "#8b5cf6", label: "Violet" },
        ]}
      />
    </section>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { ColorPicker } from "@/components/starwind/color-picker";
</script>

<template>
  <section class="space-y-4 rounded-lg border p-5">
    <div>
      <h3 class="font-medium">Theme accent</h3>
      <p class="text-muted-foreground text-sm">Used for links, focus rings, and primary actions.</p>
    </div>
    <ColorPicker
      inline
      label="Accent color"
      defaultValue="#7c3aed"
      :alpha="false"
      :showEyeDropper="false"
      :swatches="[
        { value: '#10b981', label: 'Emerald' },
        { value: '#0ea5e9', label: 'Sky' },
        { value: '#8b5cf6', label: 'Violet' },
      ]"
    />
  </section>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Format Controls and Optional Features

- `format` accepts `"hex"`, `"rgb"`, `"hsl"`, or `"hsb"` and defaults to `"hex"`.
- `formatControl="select"` uses the styled selector and is the default. Use `"native"` for a
browser `<select>` or `"none"` to omit the selector.
- `formats` limits the available formats. Duplicate entries are removed, and the active format
remains available even if it was omitted from the array.
- `alpha` defaults to `true`. Set `alpha={false}` when transparency is not valid.
- `showEyeDropper` defaults to `true`. The action also hides automatically when the browser or
security context does not support the EyeDropper API.
- `showValueText={false}` creates a swatch-only default trigger.
- `clearable` allows an empty value and adds the default Clear action. It replaces the old styled
`allowEmpty` and `showClear` combination.
- `swatches` accepts color strings or `{ value, label, disabled? }` objects. String swatches use the
color value as their accessible label.

<FrameworkCodeSwitcher>
<div slot="astro">
```astro
---
import { ColorPicker } from "@/components/starwind/color-picker";
---

<ColorPicker
  label="Accent color"
  defaultValue="rgb(37, 99, 235)"
  formats={["rgb", "hex"]}
  formatControl="native"
  alpha={false}
  showEyeDropper={false}
  clearable
/>
```
</div>
<div slot="react">
```tsx
import { ColorPicker } from "@/components/starwind/color-picker";

export function Example() {
  return (
    <ColorPicker
      label="Accent color"
      defaultValue="rgb(37, 99, 235)"
      formats={["rgb", "hex"]}
      formatControl="native"
      alpha={false}
      showEyeDropper={false}
      clearable
    />
  );
}
```
</div>
<div slot="vue">
```vue
<script setup lang="ts">
import { ColorPicker } from "@/components/starwind/color-picker";
</script>

<template>
  <ColorPicker
    label="Accent color"
    defaultValue="rgb(37, 99, 235)"
    :formats="['rgb', 'hex']"
    formatControl="native"
    :alpha="false"
    :showEyeDropper="false"
    clearable
  />
</template>
```
</div>
</FrameworkCodeSwitcher>

## Forms and Reset

Put `name`, `form`, and `required` directly on `ColorPicker`. Its automatic hidden input owns the
submitted value, native validity, and form association. Resetting the form restores the initial
color and format.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
import { ColorPicker } from "@/components/starwind/color-picker";

const swatches = [
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];
---

<form class="space-y-5" data-color-picker-form>
  <ColorPicker
    label="Accent color"
    name="accent"
    defaultValue="#2563eb"
    required
    swatches={swatches}
  />

  <div class="flex flex-wrap items-center gap-3">
    <Button type="submit">Save settings</Button>
    <Button type="reset" variant="outline">Reset</Button>
    <output class="text-muted-foreground text-sm" aria-live="polite">
      Not submitted
    </output>
  </div>
</form>

<script>
  const form = document.querySelector<HTMLFormElement>("[data-color-picker-form]");
  const result = form?.querySelector<HTMLOutputElement>("output");

  form?.addEventListener("submit", (event) => {
    event.preventDefault();
    if (!form.reportValidity()) return;
    if (result) {
      result.value = `Saved accent: ${String(new FormData(form).get("accent") ?? "")}`;
    }
  });
  form?.addEventListener("reset", () => {
    window.setTimeout(() => {
      if (result) result.value = "Reset to default";
    }, 0);
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { useState } from "react";
import { Button } from "@/components/starwind/button";
import { ColorPicker } from "@/components/starwind/color-picker";

export function Example() {
  const [result, setResult] = useState("Not submitted");

  return (
    <form
      className="space-y-5"
      onSubmit={(event) => {
        event.preventDefault();
        if (!event.currentTarget.reportValidity()) return;
        const value = new FormData(event.currentTarget).get("accent");
        setResult(`Saved accent: ${String(value ?? "")}`);
      }}
      onReset={() => setResult("Reset to default")}
    >
      <ColorPicker
        label="Accent color"
        name="accent"
        defaultValue="#2563eb"
        required
        swatches={[
          { value: "#10b981", label: "Emerald" },
          { value: "#0ea5e9", label: "Sky" },
          { value: "#8b5cf6", label: "Violet" },
        ]}
      />

      <div className="flex flex-wrap items-center gap-3">
        <Button type="submit">Save settings</Button>
        <Button type="reset" variant="outline">Reset</Button>
        <output className="text-muted-foreground text-sm" aria-live="polite">
          {result}
        </output>
      </div>
    </form>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { ColorPicker } from "@/components/starwind/color-picker";
import { ref } from "vue";

const swatches = [
  { value: "#10b981", label: "Emerald" },
  { value: "#0ea5e9", label: "Sky" },
  { value: "#8b5cf6", label: "Violet" },
];

const result = ref("Not submitted");
function submit(event: Event) {
  const form = event.currentTarget as HTMLFormElement;
  if (form.reportValidity())
    result.value = `Saved accent: ${String(new FormData(form).get("accent") ?? "")}`;
}
</script>

<template>
  <form
    @submit.prevent="submit"
    @reset="result = 'Reset to default'"
    class="space-y-5"
    data-color-picker-form
  >
    <ColorPicker
      label="Accent color"
      name="accent"
      defaultValue="#2563eb"
      required
      :swatches="swatches"
    />

    <div class="flex flex-wrap items-center gap-3">
      <Button type="submit">Save settings</Button>
      <Button type="reset" variant="outline">Reset</Button>
      <output class="text-muted-foreground text-sm" aria-live="polite">
        {{ result }}
      </output>
    </div>
  </form>
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Custom Composition

Supplying children replaces the visible default editor. Use this for authored trigger layouts,
input-only pickers, swatch-only triggers, or custom channel arrangements. The hidden form input is
still appended automatically.

<FrameworkCodeSwitcher>
<div slot="astro">
```astro
---
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";
---

<ColorPicker label="Brand color" defaultValue="#0ea5e9">
  {(initial) => (
    <>
      <span class="text-sm font-medium" data-slot="color-picker-label">Brand color</span>
      <ColorPickerTrigger
        initial={initial}
        showValueText={false}
        aria-label="Open brand color picker"
      />
      <ColorPickerContent initial={initial} aria-label="Brand color editor" />
    </>
  )}
</ColorPicker>
```
</div>
<div slot="react">
```tsx
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";

export function Example() {
  return (
    <ColorPicker label="Brand color" defaultValue="#0ea5e9">
      <span className="text-sm font-medium" data-slot="color-picker-label">
        Brand color
      </span>
      <ColorPickerTrigger showValueText={false} aria-label="Open brand color picker" />
      <ColorPickerContent aria-label="Brand color editor" />
    </ColorPicker>
  );
}
```
</div>
<div slot="vue">
```vue
<script setup lang="ts">
import {
  ColorPicker,
  ColorPickerContent,
  ColorPickerTrigger,
} from "@/components/starwind/color-picker";
</script>

<template>
  <ColorPicker label="Brand color" defaultValue="#0ea5e9">
    <span class="text-sm font-medium" data-slot="color-picker-label">Brand color</span>
    <ColorPickerTrigger :showValueText="false" aria-label="Open brand color picker" />
    <ColorPickerContent aria-label="Brand color editor" />
  </ColorPicker>
</template>
```
</div>
</FrameworkCodeSwitcher>

Use `ColorPickerArea`, `ColorPickerChannelSlider`, `ColorPickerChannelInput`, `ColorPickerInput`,
`ColorPickerValueSwatch`, `ColorPickerSwatchGroup`, `ColorPickerSwatch`, `ColorPickerEyeDropper`,
and `ColorPickerClear` for more specialized compositions. Use the [Primitive
reference](/docs/primitives/color-picker/) when you need to replace only an internal area thumb,
format-selector part, or hidden input.

## Migrate the Previous Styled API

| Previous API | Replacement |
| --- | --- |
| `ColorPickerRoot` | `<ColorPicker inline>` |
| `ColorPickerLabel` | The `label` prop or an authored label |
| `ColorPickerControl` | The default wrapper or an authored container |
| `ColorPickerAreaThumb` | Included by `ColorPickerArea` |
| `ColorPickerSliders` | The default editor or explicit channel sliders |
| `ColorPickerValueInput` | `<ColorPickerInput formatControl="none" />` |
| Native or styled format-select parts | `ColorPickerInput` or the root `formatControl` prop |
| `ColorPickerHiddenInput` | Automatically rendered by `ColorPicker` |
| `allowEmpty` plus `showClear` | `clearable` |
| Content swatch slot or React node | The root or content `swatches` array |
| Inner anatomy `size` props | Set `size` on `ColorPicker` or `ColorPickerContent` |
| `ColorPickerInput size` | `ColorPickerInput formatContentSize` for its nested Select popup |

## Accessibility

- Use `label` for the common composition or author an accessible label for a custom layout.
- Keep the area and channel controls available so the editor remains keyboard operable.
- Give object swatches names that identify the choice; do not rely on color alone.
- Preserve visible focus styles and sufficient contrast around thumbs, swatches, and controls in
custom themes.
- Use `required`, `disabled`, and `readOnly` according to the form's intent.

## API Reference
### ColorPicker
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `align` | `"start" \| "center" \| "end"` | No | `"start"` | Wrapper prop | Aligns the component within its available axis. |
| `avoidCollisions` | `boolean` | No | `true` | Wrapper prop | Repositions floating content to keep it inside the collision boundary. |
| `clearable` | `boolean` | No | `false` | Wrapper prop | Allows an empty value and includes the default Clear action. |
| `closeDelay` | `number` | No | `200` | Wrapper prop | Sets the delay in milliseconds before closing. |
| `closeOnEscape` | `boolean` | No | `true` | Wrapper prop | Allows the surface to close when Escape is pressed. |
| `closeOnOutsideInteract` | `boolean` | No | `true` | Wrapper prop | Allows the surface to close after an outside interaction. |
| `defaultOpen` | `boolean` | No | `false` | Wrapper prop | Sets the initial open state when the component is uncontrolled. |
| `defaultValue` | `string \| ColorPickerColor \| null` | No | `"#000000"` | Primitive override | Sets the initial value when the component is uncontrolled. |
| `dir` | `"ltr" \| "rtl"` | No | - | Primitive override | Sets the picker direction explicitly. |
| `disablePortal` | `boolean` | No | `false` | Wrapper prop | Keeps the public Portal wrapper inline instead of moving it to a target. |
| `format` | `"hex" \| "rgb" \| "hsl" \| "hsb"` | No | - | Wrapper prop | Sets the editable color format. |
| `formatControl` | `"select" \| "native" \| "none"` | No | `"select"` | Wrapper prop | Chooses a styled, native, or absent format control. |
| `formats` | `readonly ColorPickerFormat[]` | No | `["hex","rgb","hsl","hsb"]` | Wrapper prop | Restricts and orders the available color formats. |
| `inline` | `boolean` | No | `false` | Wrapper prop | Renders the complete editor without a Popover shell. |
| `label` | `string` | No | - | Wrapper prop | Provides accessible text for the component. |
| `modal` | `boolean` | No | `false` | Wrapper prop | Controls whether interaction outside the surface is blocked while open. |
| `openOnHover` | `boolean` | No | `false` | Wrapper prop | Allows pointer hover to open the surface. |
| `portalContainer` | `string` | No | - | Wrapper prop | Sets the CSS selector for the public Portal wrapper target. |
| `showEyeDropper` | `boolean` | No | `true` | Wrapper prop | Shows the EyeDropper trigger when supported. |
| `showValueText` | `boolean` | No | `true` | Wrapper prop | Shows the formatted value beside the trigger swatch. |
| `side` | `"top" \| "right" \| "bottom" \| "left"` | No | `"bottom"` | Wrapper prop | Selects the preferred side for floating content. |
| `sideOffset` | `number` | No | `4` | Wrapper prop | Sets the distance in pixels between floating content and its anchor. |
| `size` | `"sm" \| "md" \| "lg"` | No | `"md"` | Styled variant | Selects the component's visual size. |
| `swatches` | `readonly (ColorPickerValue \| { value: ColorPickerValue; label: string; disabled?: boolean })[]` | No | `[]` | Wrapper prop | Adds suggested colors to the default editor. |
- Inherits div attributes. Omits `defaultValue`, `dir`, `onChange`, and `value`.

### ColorPickerInput
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `disablePortal` | `boolean` | No | `false` | Wrapper prop | Keeps the public Portal wrapper inline instead of moving it to a target. |
| `formatContentSize` | `"sm" \| "md" \| "lg"` | No | `"md"` | Wrapper prop | Sets the independently portaled format Select popup size. |
| `formatControl` | `"select" \| "native" \| "none"` | No | `"select"` | Wrapper prop | Chooses a styled, native, or absent format control. |
| `formats` | `readonly ColorPickerFormat[]` | No | `["hex","rgb","hsl","hsb"]` | Wrapper prop | Restricts and orders the available color formats. |
| `portalContainer` | `string` | No | - | Wrapper prop | Sets the CSS selector for the public Portal wrapper target. |
- Inherits div attributes.

### ColorPickerTrigger
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `showValueText` | `boolean` | No | `true` | Wrapper prop | Shows the formatted value beside the trigger swatch. |
- Inherits PopoverTrigger props.

### ColorPickerContent
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `formatControl` | `"select" \| "native" \| "none"` | No | `"select"` | Wrapper prop | Chooses a styled, native, or absent format control. |
| `formats` | `readonly ColorPickerFormat[]` | No | `["hex","rgb","hsl","hsb"]` | Wrapper prop | Restricts and orders the available color formats. |
| `showEyeDropper` | `boolean` | No | `true` | Wrapper prop | Shows the EyeDropper trigger when supported. |
| `size` | `"sm" \| "md" \| "lg"` | No | `"md"` | Styled variant | Selects the component's visual size. |
| `swatches` | `readonly (ColorPickerValue \| { value: ColorPickerValue; label: string; disabled?: boolean })[]` | No | `[]` | Wrapper prop | Provides suggested values for the generated swatch group. |
- Inherits PopoverContent props.

### ColorPickerArea
- Inherits div attributes.

### ColorPickerChannelSlider
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `channel` | `"hue" \| "saturation" \| "brightness" \| "lightness" \| "red" \| "green" \| "blue" \| "alpha"` | Yes | - | Primitive override | Selects the channel rendered by this slider. |
- Inherits div attributes.

### ColorPickerChannelInput
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `channel` | `"hue" \| "saturation" \| "brightness" \| "lightness" \| "red" \| "green" \| "blue" \| "alpha"` | Yes | - | Primitive override | Selects the channel edited by this input. |
- Inherits input attributes.

### ColorPickerValueSwatch
- Inherits span attributes.

### ColorPickerSwatchGroup
- Inherits div attributes.

### ColorPickerSwatch
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `disabled` | `boolean` | No | `false` | Wrapper prop | Disables interaction with the component. |
| `value` | `string \| ColorPickerColor \| null` | Yes | - | Wrapper prop | Controls or identifies the component value. |
- Inherits button attributes. Omits `value`.

### ColorPickerEyeDropper
- Inherits button attributes.

### ColorPickerClear
- Inherits button attributes.
### Primitive And Runtime API
Behavior, state, events, form participation, and imperative methods are documented in the lower-level references.
- Primitive: [Color Picker Primitive](/docs/primitives/color-picker/)
- Runtime factory: [`createColorPicker`](/docs/runtime/#create-color-picker) from `@starwind-ui/runtime/color-picker`

## Changelog

### v2.1.0

- Added `portalContainer` and `disablePortal` to the root and content APIs for custom portal
targets and inline rendering, including the nested format selector.

### v2.0.2

- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.
- Accepted raw color values and labeled descriptors in generated Astro and React swatch arrays without JavaScript or TypeScript compile errors.
- Applied the configured format selection before first interaction in React so controls such as HEX show their selected styling immediately.

### v2.0.1

- Removed unused generated bindings from the Astro and React components so strict consumer builds
pass without unused import or local errors.

### v2.0.0

- Adopted Tailwind CSS v4 custom-property shorthand throughout the installed component classes;
this is a source-level cleanup with no API or visual change.
- Simplified the styled API around a complete zero-child popup or inline editor.
- Centralized visual sizing on `ColorPicker` and independently portaled `ColorPickerContent`, both
defaulting to `md`; default composition forwards the root size to its owned content.
- Removed `size` from inner anatomy. Move it to the owning root/content scope, or replace
`ColorPickerInput size` with `formatContentSize` when sizing only the nested format popup.
- Added convenience props for labels, format controls, format lists, EyeDropper visibility,
value text, clearing, and swatch data while keeping alpha enabled by default.
- Folded labels, control wrappers, area thumbs, sliders, format selectors, value inputs, and hidden
form inputs into their owning components.
- Custom children now replace the visible default anatomy; use the [Color Picker
Primitive](/docs/primitives/color-picker/) for raw anatomy customization.

### v0.1.0

- Added the Runtime-backed Astro and React Color Picker with popup and inline compositions, alpha,
swatches, HEX, RGB, HSL, and HSB editing, and native form participation.