# ColorPicker

> Swatch trigger that opens a popover with a swatch grid (tag palette by default), a validated hex field and an optional native colour input.

Source: https://docs.nasaqui.com/components/color-picker

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/color-picker.json
```

A form control for choosing one colour. The trigger looks like an input and shows the current swatch and its
name. It opens a popover with a grid of swatches (the `--nq-tag-*` palette by default), a hex field that
validates what the user types, and an optional "Custom" button that opens the browser's native colour input.

## When to use

- Colouring a label, a tag, a calendar or a chart series.
- Letting users choose a brand colour, with a few approved swatches plus a free hex value.

## When not to use

- Picking one of a few named options with no colour meaning: use a [`RadioGroup`](https://docs.nasaqui.com/components/radio-group) or a `Select`.
- Editing tags themselves: use a [`TagInput`](https://docs.nasaqui.com/components/tag-input).

## Import

```tsx
import { ColorPicker } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { ColorPicker, Field, FieldLabel } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function LabelColor() {
  const [color, setColor] = useState<string | null>("--nq-tag-teal");
  return (
    <Field>
      <FieldLabel>Label colour</FieldLabel>
      <ColorPicker value={color} onValueChange={setColor} aria-label="Label colour" />
    </Field>
  );
}
```

## Value format

The value is a plain string, and it is one of two things:

| Kind | Example | When |
| --- | --- | --- |
| CSS custom property name | `--nq-tag-red` | A swatch from the default palette, or any swatch whose `value` is a `--var` name. It follows the theme and brand, so store it when the colour is a design decision. |
| Hex string | `#1a73e8` | Anything typed in the hex field, picked with the native input, or a swatch given as hex. Always lower-case and 6 digits when it comes from the picker (`#abc` is stored as `#aabbcc`). |

`null` means no colour. Turn a value into a CSS colour with `colorToCss(value)`: a hex string stays as is, and
`--nq-tag-red` becomes `var(--nq-tag-red)`.

```tsx
import { colorToCss } from "@fadymondy/nasaq/web";

export const Dot = ({ color }: { color: string }) => <span className="size-3 rounded-full" style={{ backgroundColor: colorToCss(color) }} />;
```

## Anatomy

```
ColorPicker
├─ trigger                 button rendered through Field.Control      data-slot="color-picker-trigger"
│  └─ chip + name          data-slot="color-picker-chip"
└─ popover                 aria-label "Choose colour"
   ├─ swatch grid          radiogroup                                 data-slot="color-picker-swatches"
   │  └─ swatch            role="radio"                               data-slot="color-picker-swatch"
   ├─ hex field            dir="ltr" text input                       data-slot="color-picker-hex"
   │  └─ error             role="alert"                               data-slot="color-picker-error"
   └─ Custom button        opens <input type="color">                 data-slot="color-picker-custom"
```

## API

### `ColorPicker`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value?` | `string \| null` | none | Controlled value (hex or `--var` name). |
| `defaultValue?` | `string \| null` | `null` | Initial value when uncontrolled. |
| `onValueChange?` | `(value: string) => void` | none | Called with the chosen swatch value, or a lower-case 6 digit hex. |
| `swatches?` | `readonly ColorSwatch[]` | `tagSwatches(locale)` | Choices in the grid. `[]` hides the grid cleanly. |
| `mode?` | `"swatches" \| "hex"` | `"swatches"` | `"hex"` is hex-only: no swatch grid, only the hex field and the "Custom" button. |
| `columns?` | `number` | `5` | Swatches per row. |
| `allowHex?` | `boolean` | `true` | Show the hex field. |
| `allowNative?` | `boolean` | `true` | Show the "Custom" button for the native colour input. |
| `disabled?` | `boolean` | `false` | Disables the trigger. |
| `invalid?` | `boolean` | `false` | Marks the trigger invalid (`aria-invalid`, danger border). |
| `name?` | `string` | none | Renders a hidden input carrying the value for forms. |
| `id?` | `string` | none | Id of the trigger. |
| `placeholder?` | `string` | "No colour" | Trigger text when there is no value. |
| `locale?` / `dir?` | `string` / `"ltr" \| "rtl"` | from the provider | Override for the popup strings and direction. |
| `aria-label?` | `string` | "Choose colour" | Name of the trigger; the current colour name is appended. |
| `className?` | `string` | none | Merged onto the trigger. |

### Types and helpers

| Export | Signature |
| --- | --- |
| `ColorSwatch` | `{ value: string; label: string }`. `label` is the swatch's accessible name. |
| `tagSwatches(locale?)` | `ColorSwatch[]`: gray, red, orange, amber, green, teal, blue, violet, pink as `--nq-tag-*` names. |
| `isHexColor(value)` | `boolean`: true for `#rgb` or `#rrggbb`. |
| `normalizeHexColor(input)` | `string \| null`: lower-case `#rrggbb`; accepts a missing `#` and 3 digit shorthand. |
| `colorToCss(value)` | `string`: `--nq-tag-red` to `var(--nq-tag-red)`, hex unchanged. |

## Examples

### Your own swatches

```tsx
import { ColorPicker } from "@fadymondy/nasaq/web";

export function BrandColor() {
  return (
    <ColorPicker
      aria-label="Brand colour"
      columns={3}
      allowNative={false}
      swatches={[
        { value: "--nq-tag-blue", label: "Brand blue" },
        { value: "--nq-tag-green", label: "Success green" },
        { value: "--nq-tag-red", label: "Alert red" },
      ]}
    />
  );
}
```

### In a form

```tsx
import { ColorPicker, Field, FieldError, FieldLabel } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function Required() {
  const [color, setColor] = useState<string | null>(null);
  return (
    <Field invalid={!color}>
      <FieldLabel>Colour</FieldLabel>
      <ColorPicker name="color" value={color} onValueChange={setColor} invalid={!color} aria-label="Colour" />
      <FieldError match>Choose a colour.</FieldError>
    </Field>
  );
}
```

### Arabic

```tsx
import { ColorPicker, Field, FieldLabel, NasaqProvider } from "@fadymondy/nasaq/web";

export function LabelColorAr() {
  return (
    <NasaqProvider locale="ar" target="scope">
      <Field>
        <FieldLabel>لون الوسم</FieldLabel>
        <ColorPicker defaultValue="--nq-tag-red" aria-label="لون الوسم" />
      </Field>
    </NasaqProvider>
  );
}
```

## Accessibility

The trigger is a button with `aria-label` "Choose colour: Teal". The popover is labelled "Choose colour". The
swatch grid is a `radiogroup` (Base UI `RadioGroup`), each swatch is a `role="radio"` with an accessible name
from its `label`, and the selected swatch also gets a ring, so the state is not colour only.

| Key | Action |
| --- | --- |
| `Enter` / `Space` on the trigger | Opens the popover. |
| `Left` / `Right` in the grid | Previous / next swatch and select it. They follow the reading direction, so `Right` goes to the previous swatch in RTL. |
| `Up` / `Down` in the grid | Previous / next swatch and select it. |
| `Tab` | Grid, hex field, Custom button. |
| `Enter` in the hex field | Validates and applies the value. |
| `Esc` | Closes and returns focus to the trigger. |

- The hex field has an accessible name; an invalid entry sets `aria-invalid` and shows an announced error.
- Caller must localise: `aria-label`, `placeholder`, and the `label` of every custom swatch. The built-in strings and the tag palette names come in English and Arabic.

## RTL & i18n

- The grid, trigger and buttons use logical layout, so they mirror with `dir`.
- The hex field is always `dir="ltr"`; hex digits never reverse in Arabic.
- Palette names and every built-in string switch to Arabic when the locale is `ar`.

## Styling & tokens

- Default swatches are `--nq-tag-*` variables. There are no hex colours in the component; hex only ever comes from the user's data.
- Surfaces use `bg-card`, `border-input`, `border-nq-line-strong`, the popover uses `bg-popover`; the focus ring is `nq-focus`; errors use `nq-danger`.
- Slots: `color-picker-trigger`, `color-picker-chip`, `color-picker-swatches`, `color-picker-swatch` (`data-checked`), `color-picker-hex`, `color-picker-error`, `color-picker-custom`.
- Extend the trigger with `className`; never override colours with raw hex.

## Do / Don't

- **Do** store a `--nq-tag-*` name when the colour is a design choice, so it adapts to dark mode and brands.
- **Do** give custom swatches a `label`; without it a screen reader has nothing to say.
- **Don't** assume the value is hex: pass it through `colorToCss` before using it in a style.
- **Don't** save the resolved colour of a token as hex unless you want it frozen.

## Related

- [Popover](https://docs.nasaqui.com/components/popover) · [RadioGroup](https://docs.nasaqui.com/components/radio-group) · [Field](https://docs.nasaqui.com/components/field) · [TagInput](https://docs.nasaqui.com/components/tag-input)

## Lab

https://docs.nasaqui.com/?path=/docs/components-pickers-color-picker--docs

## Code

### React

```tsx
import { ColorPicker, Field, FieldLabel } from "@fadymondy/nasaq/web";
import { useState } from "react";

export function LabelColor() {
  const [color, setColor] = useState<string | null>("--nq-tag-teal");
  return (
    <Field>
      <FieldLabel>Label colour</FieldLabel>
      <ColorPicker value={color} onValueChange={setColor} aria-label="Label colour" />
    </Field>
  );
}
```

### shadcn

```tsx
import { ColorPicker } from "@/components/ui/color-picker";
import { Field, FieldLabel } from "@/components/ui/field";
import { useState } from "react";

export function LabelColor() {
  const [color, setColor] = useState<string | null>("--nq-tag-teal");
  return (
    <Field>
      <FieldLabel>Label colour</FieldLabel>
      <ColorPicker value={color} onValueChange={setColor} aria-label="Label colour" />
    </Field>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { ref } from "vue";
import { NqColorPicker, NqField, NqFieldLabel } from "@fadymondy/nasaq/vue";

const color = ref<string | null>("--nq-tag-teal");
</script>

<template>
  <NqField>
    <NqFieldLabel>Label colour</NqFieldLabel>
    <NqColorPicker v-model="color" aria-label="Label colour" />
  </NqField>
</template>
```

### Blade

```blade
<x-nq::field class="max-w-sm">
    <x-nq::field.label>Label colour</x-nq::field.label>
    <x-nq::color-picker value="--nq-tag-teal" aria-label="Label colour" />
</x-nq::field>
```

### HTML + Alpine

```html
<div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     class="flex flex-col gap-1.5 max-w-sm">
    <label data-slot="field-label"  class="text-label text-foreground data-disabled:opacity-50">Label colour</label>
    <div data-slot="color-picker" x-data="nqColorPicker(JSON.parse('{\u0022value\u0022:\u0022--nq-tag-teal\u0022,\u0022swatches\u0022:[{\u0022value\u0022:\u0022--nq-tag-gray\u0022,\u0022label\u0022:\u0022Gray\u0022},{\u0022value\u0022:\u0022--nq-tag-red\u0022,\u0022label\u0022:\u0022Red\u0022},{\u0022value\u0022:\u0022--nq-tag-orange\u0022,\u0022label\u0022:\u0022Orange\u0022},{\u0022value\u0022:\u0022--nq-tag-amber\u0022,\u0022label\u0022:\u0022Amber\u0022},{\u0022value\u0022:\u0022--nq-tag-green\u0022,\u0022label\u0022:\u0022Green\u0022},{\u0022value\u0022:\u0022--nq-tag-teal\u0022,\u0022label\u0022:\u0022Teal\u0022},{\u0022value\u0022:\u0022--nq-tag-blue\u0022,\u0022label\u0022:\u0022Blue\u0022},{\u0022value\u0022:\u0022--nq-tag-violet\u0022,\u0022label\u0022:\u0022Violet\u0022},{\u0022value\u0022:\u0022--nq-tag-pink\u0022,\u0022label\u0022:\u0022Pink\u0022}],\u0022placeholder\u0022:\u0022No colour\u0022,\u0022none\u0022:\u0022No colour\u0022,\u0022choose\u0022:\u0022Label colour\u0022,\u0022rtl\u0022:false}'))" x-modelable="color" class="contents">
    <div data-slot="popover" x-data="nqPopover(false)" x-modelable="open" x-id="['nq-popover']" class="contents">
    <button type="button" x-ref="trigger" data-slot="color-picker-trigger" aria-haspopup="dialog" x-on:click="toggle()"
            :aria-expanded="open" x-bind:data-popup-open="open ? '' : undefined" x-bind:aria-label="triggerLabel"
                                    class="flex h-control w-full min-w-0 items-center gap-2 rounded-control border border-input bg-card px-3 text-body text-foreground min-h-[var(--nq-touch-min,0px)] cursor-default select-none outline-none transition-colors duration-150 ease-nq focus-visible:border-nq-focus focus-visible:outline-1 focus-visible:outline-nq-focus data-popup-open:border-nq-focus data-invalid:border-nq-danger aria-invalid:border-nq-danger data-disabled:cursor-not-allowed data-disabled:opacity-50 disabled:cursor-not-allowed disabled:opacity-50 pointer-coarse:text-[16px]">
            <span aria-hidden="true" data-slot="color-picker-chip" x-bind:style="color ? { backgroundColor: css(color) } : null"
                x-bind:class="color ? '' : 'border-dashed bg-transparent'" class="inline-block size-5 shrink-0 rounded-[6px] border border-nq-line-strong"></span>
            <span class="min-w-0 flex-1 truncate text-start" x-bind:class="label ? '' : 'text-muted-foreground'" dir="auto" x-text="label ?? placeholder">No colour</span>
            <svg aria-hidden="true" class="size-4 shrink-0 text-muted-foreground" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m7 15 5 5 5-5"/>
  <path d="m7 9 5-5 5 5"/>
</svg>        </button>
                <template x-teleport="body">
    <div data-slot="popover-content" x-bind="popup" x-init="popupEl = $el" x-nq-presence="open" x-anchor.bottom-start.offset.6="$refs.trigger"
        dir="ltr" lang="en" aria-label="Choose colour" x-effect="open &amp;&amp; $nextTick(() =&gt; syncDraft())" class="z-50 max-w-[var(--available-width)] rounded-floating border border-border bg-popover text-body-sm text-popover-foreground shadow-floating outline-none transition-opacity duration-150 ease-nq data-starting-style:opacity-0 data-ending-style:opacity-0 w-64 p-3"><div class="flex flex-col gap-3">
                                    <div role="radiogroup" aria-label="Colours" dir="ltr" data-slot="color-picker-swatches" class="grid gap-2"
                        style="grid-template-columns: repeat(5, minmax(0, 1fr))" x-on:keydown="swatchKey($event)">
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-gray" aria-label="Gray" title="Gray"
                                style="background-color: var(--nq-tag-gray)"
                                x-bind:aria-checked="isOn('--nq-tag-gray')" x-bind:tabindex="tab('--nq-tag-gray')"
                                x-bind:data-checked="isOn('--nq-tag-gray') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-gray') ? null : ''"
                                x-on:click="pick('--nq-tag-gray')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-red" aria-label="Red" title="Red"
                                style="background-color: var(--nq-tag-red)"
                                x-bind:aria-checked="isOn('--nq-tag-red')" x-bind:tabindex="tab('--nq-tag-red')"
                                x-bind:data-checked="isOn('--nq-tag-red') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-red') ? null : ''"
                                x-on:click="pick('--nq-tag-red')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-orange" aria-label="Orange" title="Orange"
                                style="background-color: var(--nq-tag-orange)"
                                x-bind:aria-checked="isOn('--nq-tag-orange')" x-bind:tabindex="tab('--nq-tag-orange')"
                                x-bind:data-checked="isOn('--nq-tag-orange') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-orange') ? null : ''"
                                x-on:click="pick('--nq-tag-orange')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-amber" aria-label="Amber" title="Amber"
                                style="background-color: var(--nq-tag-amber)"
                                x-bind:aria-checked="isOn('--nq-tag-amber')" x-bind:tabindex="tab('--nq-tag-amber')"
                                x-bind:data-checked="isOn('--nq-tag-amber') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-amber') ? null : ''"
                                x-on:click="pick('--nq-tag-amber')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-green" aria-label="Green" title="Green"
                                style="background-color: var(--nq-tag-green)"
                                x-bind:aria-checked="isOn('--nq-tag-green')" x-bind:tabindex="tab('--nq-tag-green')"
                                x-bind:data-checked="isOn('--nq-tag-green') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-green') ? null : ''"
                                x-on:click="pick('--nq-tag-green')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-teal" aria-label="Teal" title="Teal"
                                style="background-color: var(--nq-tag-teal)"
                                x-bind:aria-checked="isOn('--nq-tag-teal')" x-bind:tabindex="tab('--nq-tag-teal')"
                                x-bind:data-checked="isOn('--nq-tag-teal') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-teal') ? null : ''"
                                x-on:click="pick('--nq-tag-teal')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-blue" aria-label="Blue" title="Blue"
                                style="background-color: var(--nq-tag-blue)"
                                x-bind:aria-checked="isOn('--nq-tag-blue')" x-bind:tabindex="tab('--nq-tag-blue')"
                                x-bind:data-checked="isOn('--nq-tag-blue') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-blue') ? null : ''"
                                x-on:click="pick('--nq-tag-blue')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-violet" aria-label="Violet" title="Violet"
                                style="background-color: var(--nq-tag-violet)"
                                x-bind:aria-checked="isOn('--nq-tag-violet')" x-bind:tabindex="tab('--nq-tag-violet')"
                                x-bind:data-checked="isOn('--nq-tag-violet') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-violet') ? null : ''"
                                x-on:click="pick('--nq-tag-violet')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                                    <button type="button" role="radio" data-slot="color-picker-swatch" data-value="--nq-tag-pink" aria-label="Pink" title="Pink"
                                style="background-color: var(--nq-tag-pink)"
                                x-bind:aria-checked="isOn('--nq-tag-pink')" x-bind:tabindex="tab('--nq-tag-pink')"
                                x-bind:data-checked="isOn('--nq-tag-pink') ? '' : null" x-bind:data-unchecked="isOn('--nq-tag-pink') ? null : ''"
                                x-on:click="pick('--nq-tag-pink')" class="relative aspect-square w-full cursor-default rounded-control border border-nq-line-strong outline-none transition-shadow duration-150 ease-nq hover:shadow-[0_0_0_2px_var(--nq-line-strong)] data-checked:shadow-[0_0_0_2px_var(--popover),0_0_0_4px_var(--foreground)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus"></button>
                                            </div>
                                                    <div class="flex flex-col gap-1">
                        <div class="flex h-control items-center gap-2 rounded-control border border-input bg-card px-2 focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus"
                            x-bind:class="showError ? 'border-nq-danger' : ''">
                            <span aria-hidden="true" data-slot="color-picker-chip" x-bind:style="draftColor ? { backgroundColor: css(draftColor) } : null"
                                x-bind:class="draftColor ? '' : 'border-dashed bg-transparent'" class="inline-block size-5 shrink-0 rounded-[6px] border border-nq-line-strong"></span>
                            <input type="text" dir="ltr" inputmode="text" autocomplete="off" spellcheck="false" maxlength="7" aria-label="Hex value"
                                data-slot="color-picker-hex" x-bind:value="draft" x-bind:aria-invalid="showError ? 'true' : null"
                                x-on:input="onHex($event)" x-on:blur="submitDraft()" x-on:keydown.enter.prevent="submitDraft()"
                                class="h-full min-w-0 flex-1 border-0 bg-transparent text-start font-mono text-body-sm text-foreground outline-none pointer-coarse:text-[16px]">
                        </div>
                        <p x-show="showError" style="display: none" role="alert" data-slot="color-picker-error" class="text-caption text-nq-danger-text">Use 3 or 6 hex digits, for example 1A73E8.</p>
                    </div>
                                                    <div class="contents">
                        <button type="button" data-slot="color-picker-custom" x-on:click="openNative()"
                            class="inline-flex h-control-sm min-h-[var(--nq-touch-min,0px)] items-center justify-center gap-2 rounded-control border border-border bg-card px-2.5 text-label text-foreground outline-none transition-colors duration-150 ease-nq hover:bg-nq-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus [&_svg]:size-4">
                            <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="m12 9-8.414 8.414A2 2 0 0 0 3 18.828v1.344a2 2 0 0 1-.586 1.414A2 2 0 0 1 3.828 21h1.344a2 2 0 0 0 1.414-.586L15 12"/>
  <path d="m18 9 .4.4a1 1 0 1 1-3 3l-3.8-3.8a1 1 0 1 1 3-3l.4.4 3.4-3.4a1 1 0 1 1 3 3z"/>
  <path d="m2 22 .414-.414"/>
</svg>                            Custom
                        </button>
                        <input type="color" tabindex="-1" aria-hidden="true" class="sr-only" x-on:change="onNative($event)">
                    </div>
                            </div></div>
</template>
</div>
</div>
</div>
```
