# or
yarn add @zag-js/color-picker @zag-js/solid
```

## Anatomy

To set up the color picker correctly, you'll need to understand its anatomy and
how we name its parts.

> Each part includes a `data-part` attribute to help identify them in the DOM.



## Usage

First, import the color picker package into your project

```jsx
import * as colorPicker from "@zag-js/color-picker"
```

The color picker package exports these functions:

- `machine` â The state machine logic for the color picker widget.
- `connect` â The function that translates the machine's state to JSX attributes
  and event handlers.
- `parse` - The function that parses a color string to an Color object.

Next, import the required hooks and functions for your framework and use the
color picker machine in your project ð¥

```jsx
import * as colorPicker from "@zag-js/color-picker"
import { normalizeProps, useMachine } from "@zag-js/solid"
import { createMemo, createUniqueId } from "solid-js"

function ColorPicker() {
  const service = useMachine(colorPicker.machine, {
    id: createUniqueId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = createMemo(() => colorPicker.connect(service, normalizeProps))

  return (
    <div {...api().getRootProps()}>
      <label {...api().getLabelProps()}>
        Select Color: {api.valueAsString}
      </label>

      <input {...api().getHiddenInputProps()} />

      <div {...api().getControlProps()}>
        <button {...api().getTriggerProps()}>
          <div {...api().getTransparencyGridProps({ size: "10px" })} />
          <div {...api().getSwatchProps({ value: api.value })} />
        </button>
        <input {...api().getChannelInputProps({ channel: "hex" })} />
        <input {...api().getChannelInputProps({ channel: "alpha" })} />
      </div>

      <div {...api().getPositionerProps()}>
        <div {...api().getContentProps()}>
          <div {...api().getAreaProps()}>
            <div {...api().getAreaBackgroundProps()} />
            <div {...api().getAreaThumbProps()} />
          </div>

          <div {...api().getChannelSliderProps({ channel: "hue" })}>
            <div {...api().getChannelSliderTrackProps({ channel: "hue" })} />
            <div {...api().getChannelSliderThumbProps({ channel: "hue" })} />
          </div>

          <div {...api().getChannelSliderProps({ channel: "alpha" })}>
            <div {...api().getTransparencyGridProps({ size: "12px" })} />
            <div {...api().getChannelSliderTrackProps({ channel: "alpha" })} />
            <div {...api().getChannelSliderThumbProps({ channel: "alpha" })} />
          </div>
        </div>
      </div>
    </div>
  )
}
```

### Setting the initial color

To set the initial color of the color picker, use the `defaultValue` context
property.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  defaultValue: colorPicker.parse("#ff0000"),
})
```

### Controlled color picker

To control the color value programmatically, pass the `value` and
`onValueChange` properties to the machine function.

> **Note:** We recommend preserving the value as a `Color` object rather than a
> string to prevent calculation errors by converting back and forth.

```tsx
import { createSignal } from "solid-js"
import * as colorPicker from "@zag-js/color-picker"

export function ControlledColorPicker() {
  const [value, setValue] = createSignal(colorPicker.parse("#ff0000"))

  const service = useMachine(colorPicker.machine, {
    get value() {
      return value()
    },
    onValueChange(details) {
      setValue(details.value)
    },
  })

  return (
    // ...
  )
}
```

### Listening for change events

When the user selects a color using the color picker, the `onValueChange` and
`onValueChangeEnd` events will be fired.

- `onValueChange` â Fires in sync as the user selects a color
- `onValueChangeEnd` â Fires when the user stops selecting a color (useful for
  debounced updates)

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  onValueChange: (details) => {
    // details => { value: Color, valueAsString: string }
  },
  onValueChangeEnd: (details) => {
    // details => { value: Color, valueAsString: string }
  },
})
```

### Using a custom color format

By default, the color picker's output format is `rgba`. You can change this
format to either `hsla` or `hsba` by using the `format` context property.

When this property is set, the `value` and `valueAsString` properties of the
`onValueChange` event will be updated to reflect the new format.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  format: "hsla",
  onValueChange: (details) => {
    // details => { value: HSLAColor, valueAsString: string }
  },
})
```

### Showing color presets

Adding color presets in form of swatches can help users pick colors faster. To
support this, use the `getSwatchTriggerProps(...)` and `getSwatchProps(...)` to
get the props needed to show the swatches buttons.

```jsx {18-31}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: createUniqueId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = createMemo(() => colorPicker.connect(service, normalizeProps))

  const presets = ["#ff0000", "#00ff00", "#0000ff"]

  return (
    <div {...api().getRootProps()}>
      {/* ... */}
      <div {...api().getPositionerProps()}>
        <div {...api().getContentProps()}>
          <div {...api().getSwatchGroupProps()}>
            <Index each={preset}>
              {(preset) => (
                <button {...api().getSwatchTriggerProps({ value: preset() })}>
                  <div style={{ position: "relative" }}>
                    <div {...api().getTransparencyGridProps({ size: "4px" })} />
                    <div {...api().getSwatchProps({ value: preset() })} />
                  </div>
                </button>
              )}
            </Index>
          </div>
        </div>
      </div>
    </div>
  )
}
```

### Disabling the color picker

To disable user interactions with the color picker, set the `disabled` context
property to `true`.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  disabled: true,
})
```

### Controlling the open and closed state

To control the open and closed state of the color picker, use the `open` and
`onOpenChange` context properties.

```jsx
const [current, send] = useMachine(colorPicker.machine, {
  open: true,
  onOpenChange: (details) => {
    // details => { open: boolean }
  },
})
```

You can also leverage the `api.setOpen(...)` method to control the open and
closed state of the color picker.

### Controlling individual color channel

In some cases, you may want to allow users to control the values of each color
channel individually. You can do this using an input element or a slider
element, or both.

To support this, use the `getChannelInputProps(...)` to show the channel inputs.

> Note: Make sure you only render the channel inputs that match the `format` of
> the color picker.

```jsx {16-38}
import { Show } from "solid-js"

const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: createUniqueId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = createMemo(() => colorPicker.connect(service, normalizeProps))

  return (
    <div {...api().getRootProps()}>
      {/* ... */}
      <div {...api().getPositionerProps()}>
        <div {...api().getContentProps()}>
          <Show when={api().format === "rgba"}>
            <div>
              <div>
                <span>R</span>
                <input {...api().getChannelInputProps({ channel: "red" })} />
              </div>

              <div>
                <span>G</span>
                <input {...api().getChannelInputProps({ channel: "green" })} />
              </div>

              <div>
                <span>B</span>
                <input {...api().getChannelInputProps({ channel: "blue" })} />
              </div>

              <div>
                <span>A</span>
                <input {...api().getChannelInputProps({ channel: "alpha" })} />
              </div>
            </div>
          </Show>
        </div>
      </div>
    </div>
  )
}
```

### Showing a color preview

To display the value of a color, use the `getSwatchProps(...)` and pass the
color value. To show the current color value, use the `api.value`

```jsx {13-16}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: createUniqueId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = createMemo(() => colorPicker.connect(service, normalizeProps))

  return (
    <div {...api().getRootProps()}>
      <div>
        <div {...api().getTransparencyGridProps({ size: "4px" })} />
        <div {...api().getSwatchProps({ value: api().value })} />
      </div>
      {/* ... */}
    </div>
  )
}
```

> You can pass `respectAlpha: false` to show the color value without the alpha
> channel

### Adding an eyedropper

The eye dropper tool is a native browser feature that allows a user pick a color
from a current page's canvas. To support this, use the
`getEyeDropperTriggerProps(...)`.

> **Note:** The eye dropper tool only works in Chrome and Edge browsers

```jsx {14-16}
const ColorPicker = () => {
  const service = useMachine(colorPicker.machine, {
    id: createUniqueId(),
    defaultValue: colorPicker.parse("hsl(0, 100%, 50%)"),
  })

  const api = createMemo(() => colorPicker.connect(service, normalizeProps))

  return (
    <div {...api().getRootProps()}>
      {/* ... */}
      <div {...api().getPositionerProps()}>
        <div {...api().getContentProps()}>
          <button {...api().getEyeDropperTriggerProps()}>
            <EyeDropIcon />
          </button>
        </div>
      </div>
    </div>
  )
}
```

### Usage within forms

To use the color picker within a form, add the `name` context property to the
machine and render the visually hidden input using the `hiddenInputProps`.

```jsx {2}
const service = useMachine(colorPicker.machine, {
  name: "color-preference",
})
```

## Styling guide

Each color picker part has a `data-part` attribute added to them to help you
identify and style them easily.

### Open and closed state

When the color picker is open or closed, the `data-state` attribute is added to
the trigger, content, control parts.

```css
[data-part="control"][data-state="open|closed"] {
  /* styles for control open or state */
}

[data-part="trigger"][data-state="open|closed"] {
  /* styles for control open or state */
}

[data-part="content"][data-state="open|closed"] {
  /* styles for control open or state */
}
```

### Focused State

When the color picker is focused, the `data-focus` attribute is added to the
control and label parts.

```css
[data-part="control"][data-focus] {
  /* styles for control focus state */
}

[data-part="label"][data-focus] {
  /* styles for label focus state */
}
```

### Disabled State

When the color picker is disabled, the `data-disabled` attribute is added to the
label, control, trigger and option parts.

```css
[data-part="label"][data-disabled] {
  /* styles for label disabled state */
}

[data-part="control"][data-disabled] {
  /* styles for control disabled state */
}

[data-part="trigger"][data-disabled] {
  /* styles for trigger disabled state */
}

[data-part="swatch-trigger"][data-disabled] {
  /* styles for item disabled state */
}
```

### Swatch State

When a swatch's color value matches the color picker's value, the
`data-state=checked` attribute is added to the swatch part.

```css
[data-part="swatch-trigger"][data-state="checked|unchecked"] {
  /* styles for swatch's checked state */
}
```

## Methods and Properties

### Machine Context

The color picker machine exposes the following context properties:

**`ids`**
Type: `Partial<{ root: string; control: string; trigger: string; label: string; input: string; hiddenInput: string; content: string; area: string; areaGradient: string; positioner: string; formatSelect: string; areaThumb: string; channelInput: (id: string) => string; channelSliderTrack: (id: ColorChannel) => string; channelSliderThumb: (id: ColorChannel) => string; }>`
Description: The ids of the elements in the color picker. Useful for composition.

**`value`**
Type: `Color`
Description: The controlled color value of the color picker

**`defaultValue`**
Type: `Color`
Description: The initial color value when rendered.
Use when you don't need to control the color value of the color picker.

**`disabled`**
Type: `boolean`
Description: Whether the color picker is disabled

**`readOnly`**
Type: `boolean`
Description: Whether the color picker is read-only

**`required`**
Type: `boolean`
Description: Whether the color picker is required

**`invalid`**
Type: `boolean`
Description: Whether the color picker is invalid

**`onValueChange`**
Type: `(details: ValueChangeDetails) => void`
Description: Handler that is called when the value changes, as the user drags.

**`onValueChangeEnd`**
Type: `(details: ValueChangeDetails) => void`
Description: Handler that is called when the user stops dragging.

**`onOpenChange`**
Type: `(details: OpenChangeDetails) => void`
Description: Handler that is called when the user opens or closes the color picker.

**`name`**
Type: `string`
Description: The name for the form input

**`positioning`**
Type: `PositioningOptions`
Description: The positioning options for the color picker

**`initialFocusEl`**
Type: `() => HTMLElement`
Description: The initial focus element when the color picker is opened.

**`open`**
Type: `boolean`
Description: The controlled open state of the color picker

**`defaultOpen`**
Type: `boolean`
Description: The initial open state of the color picker when rendered.
Use when you don't need to control the open state of the color picker.

**`format`**
Type: `ColorFormat`
Description: The controlled color format to use

**`defaultFormat`**
Type: `ColorFormat`
Description: The initial color format when rendered.
Use when you don't need to control the color format of the color picker.

**`onFormatChange`**
Type: `(details: FormatChangeDetails) => void`
Description: Function called when the color format changes

**`closeOnSelect`**
Type: `boolean`
Description: Whether to close the color picker when a swatch is selected

**`openAutoFocus`**
Type: `boolean`
Description: Whether to auto focus the color picker when it is opened

**`inline`**
Type: `boolean`
Description: Whether to render the color picker inline

**`id`**
Type: `string`
Description: The unique identifier of the machine.

**`getRootNode`**
Type: `() => Node | ShadowRoot | Document`
Description: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

**`dir`**
Type: `"ltr" | "rtl"`
Description: The document's text/writing direction.

**`onPointerDownOutside`**
Type: `(event: PointerDownOutsideEvent) => void`
Description: Function called when the pointer is pressed down outside the component

**`onFocusOutside`**
Type: `(event: FocusOutsideEvent) => void`
Description: Function called when the focus is moved outside the component

**`onInteractOutside`**
Type: `(event: InteractOutsideEvent) => void`
Description: Function called when an interaction happens outside the component

### Machine API

The color picker `api` exposes the following methods:

**`dragging`**
Type: `boolean`
Description: Whether the color picker is being dragged

**`open`**
Type: `boolean`
Description: Whether the color picker is open

**`inline`**
Type: `boolean`
Description: Whether the color picker is rendered inline

**`value`**
Type: `Color`
Description: The current color value (as a string)

**`valueAsString`**
Type: `string`
Description: The current color value (as a Color object)

**`setValue`**
Type: `(value: string | Color) => void`
Description: Function to set the color value

**`getChannelValue`**
Type: `(channel: ColorChannel) => string`
Description: Function to set the color value

**`getChannelValueText`**
Type: `(channel: ColorChannel, locale: string) => string`
Description: Function to get the formatted and localized value of a specific channel

**`setChannelValue`**
Type: `(channel: ColorChannel, value: number) => void`
Description: Function to set the color value of a specific channel

**`format`**
Type: `ColorFormat`
Description: The current color format

**`setFormat`**
Type: `(format: ColorFormat) => void`
Description: Function to set the color format

**`alpha`**
Type: `number`
Description: The alpha value of the color

**`setAlpha`**
Type: `(value: number) => void`
Description: Function to set the color alpha

**`setOpen`**
Type: `(open: boolean) => void`
Description: Function to open or close the color picker

### Data Attributes

**`Root`**

**`data-scope`**: color-picker
**`data-part`**: root
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid

**`Label`**

**`data-scope`**: color-picker
**`data-part`**: label
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid
**`data-required`**: Present when required
**`data-focus`**: Present when focused

**`Control`**

**`data-scope`**: color-picker
**`data-part`**: control
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid
**`data-state`**: "open" | "closed"
**`data-focus`**: Present when focused

**`Trigger`**

**`data-scope`**: color-picker
**`data-part`**: trigger
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only
**`data-invalid`**: Present when invalid
**`data-placement`**: The placement of the trigger
**`data-state`**: "open" | "closed"
**`data-focus`**: Present when focused

**`Content`**

**`data-scope`**: color-picker
**`data-part`**: content
**`data-placement`**: The placement of the content
**`data-nested`**: popover
**`data-has-nested`**: popover
**`data-state`**: "open" | "closed"

**`ValueText`**

**`data-scope`**: color-picker
**`data-part`**: value-text
**`data-disabled`**: Present when disabled
**`data-focus`**: Present when focused

**`Area`**

**`data-scope`**: color-picker
**`data-part`**: area
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only

**`AreaBackground`**

**`data-scope`**: color-picker
**`data-part`**: area-background
**`data-invalid`**: Present when invalid
**`data-disabled`**: Present when disabled
**`data-readonly`**: Present when read-only

**`AreaThumb`**

**`data-scope`**: color-picker
**`data-part`**: area-thumb
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`ChannelSlider`**

**`data-scope`**: color-picker
**`data-part`**: channel-slider
**`data-channel`**: The color channel of the channelslider
**`data-orientation`**: The orientation of the channelslider

**`ChannelSliderTrack`**

**`data-scope`**: color-picker
**`data-part`**: channel-slider-track
**`data-channel`**: The color channel of the channelslidertrack
**`data-orientation`**: The orientation of the channelslidertrack

**`ChannelSliderLabel`**

**`data-scope`**: color-picker
**`data-part`**: channel-slider-label
**`data-channel`**: The color channel of the channelsliderlabel

**`ChannelSliderValueText`**

**`data-scope`**: color-picker
**`data-part`**: channel-slider-value-text
**`data-channel`**: The color channel of the channelslidervaluetext

**`ChannelSliderThumb`**

**`data-scope`**: color-picker
**`data-part`**: channel-slider-thumb
**`data-channel`**: The color channel of the channelsliderthumb
**`data-disabled`**: Present when disabled
**`data-orientation`**: The orientation of the channelsliderthumb

**`ChannelInput`**

**`data-scope`**: color-picker
**`data-part`**: channel-input
**`data-channel`**: The color channel of the channelinput
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`EyeDropperTrigger`**

**`data-scope`**: color-picker
**`data-part`**: eye-dropper-trigger
**`data-disabled`**: Present when disabled
**`data-invalid`**: Present when invalid
**`data-readonly`**: Present when read-only

**`SwatchTrigger`**

**`data-scope`**: color-picker
**`data-part`**: swatch-trigger
**`data-state`**: "checked" | "unchecked"
**`data-value`**: The value of the item
**`data-disabled`**: Present when disabled

**`Swatch`**

**`data-scope`**: color-picker
**`data-part`**: swatch
**`data-state`**: "checked" | "unchecked"
**`data-value`**: The value of the item

### CSS Variables

<CssVarTable name="color-picker" />

## Accessibility

### Keyboard Interactions

**`Enter`**
Description: <span>When focus is on the trigger, opens the color picker<br />When focus is on a trigger of a swatch, selects the color (and closes the color picker)<br />When focus is on the input or channel inputs, selects the color</span>

**`ArrowLeft`**
Description: <span>When focus is on the color area, decreases the hue value of the color<br />When focus is on the channel sliders, decreases the value of the channel</span>

**`ArrowRight`**
Description: <span>When focus is on the color area, increases the hue value of the color<br />When focus is on the channel sliders, increases the value of the channel</span>

**`ArrowUp`**
Description: <span>When focus is on the color area, increases the saturation value of the color<br />When focus is on the channel sliders, increases the value of the channel</span>

**`ArrowDown`**
Description: <span>When focus is on the color area, decreases the saturation value of the color<br />When focus is on the channel sliders, decreases the value of the channel</span>

**`Esc`**
Description: Closes the color picker and moves focus to the trigger
A combobox is an input widget with an associated popup that enables users to
select a value from a collection of possible values.

## Resources


[Latest version: v1.33.1](https://www.npmjs.com/package/@zag-js/combobox)
[Logic Visualizer](https://zag-visualizer.vercel.app/combobox)
[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/combobox)



**Features**

- Support for selecting multiple values
- Support for disabled options
- Support for custom user input values
- Support for mouse, touch, and keyboard interactions
- Keyboard support for opening the combo box list box using the arrow keys,
  including automatically focusing the first or last item accordingly

## Installation

To use the combobox machine in your project, run the following command in your
command line:

```bash
npm install @zag-js/combobox @zag-js/solid