

# ColorInput

Hex text field with a swatch button that opens a full HSV `ColorPicker` popover. Accepts controlled (`value` / `onChange`) or uncontrolled (`defaultValue`) hex strings. Invalid typed hex is ignored until blur, when the field snaps back to the last valid color.

## Examples

### Default

Pass a `label` and seed with `defaultValue` (or control via `value` / `onChange`).

```tsx
import { ColorInput } from '@var-ui/react';

<ColorInput label="Brand" defaultValue="#6366f1" />
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

### Controlled value

Drive the field with `value` and `onChange` when the hex must stay in sync with app state — typing a valid hex or picking from the popover both update the same value.

```tsx
import { ColorInput } from '@var-ui/react';
import { useState } from 'react';

const [color, setColor] = useState('#e11d48');

<ColorInput label="Accent" value={color} onChange={setColor} />
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

## Props

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| className | string \| undefined | no |  |  |
| defaultValue | string \| undefined | no |  | Uncontrolled initial hex color. |
| description | string \| undefined | no |  | Helper text shown below the control when there is no error. |
| errorMessage | string \| undefined | no |  | Validation message; when set, the field is shown in an error state. |
| isDisabled | boolean \| undefined | no |  |  |
| isRequired | boolean \| undefined | no |  |  |
| label | string \| undefined | no |  | Visible label rendered above the control. |
| name | string \| undefined | no |  |  |
| onChange | ((value: string) => void) \| undefined | no |  |  |
| placeholder | string \| undefined | no |  |  |
| portalContainer | Element \| undefined | no |  | Element the picker popover portals into instead of `document.body`. Needed when a subtree renders under a different theme than the page ambient. |
| size | ControlSize \| undefined | no |  |  |
| swatches | string[] \| undefined | no | Mantine-compatible preset palette | Preset swatches below the sliders. |
| swatchesPerRow | 7 \| 10 \| undefined | no | 7 | Swatches per row. |
| value | string \| undefined | no |  | Controlled hex color value (e.g. `#6366f1`). |
| withAlpha | boolean \| undefined | no | false | Show an alpha slider and emit 8-digit hex. |

## Accessibility

The text control is a labeled native input (`aria-invalid` when `errorMessage` is set). The swatch is a separate button with `aria-label="Open color picker"` that opens a dialog popover containing the picker. Keep `label` visible, and use `description` / `errorMessage` so assistive tech gets the same help and validation copy as sighted users.
