# Color Picker

> People choose a color from the colorspace, fine-tune hue and opacity, type a HEX value or reuse a saved swatch. In Arabic the field row, the header row and the swatches mirror, while the hue and opacity bars keep running left to right: they map a color scale, not reading order.

Source: https://ritla.app/ui/color-picker

## Installation

Installing from the registry is coming soon. Until then, these are the commands you will run.

```bash
npx ritla add color-picker
```

With the shadcn CLI instead:

```bash
npx shadcn@latest add @ritla/color-picker
```

Dependencies: `@base-ui/react`, `@phosphor-icons/react`

## Usage

```tsx
import { ColorPicker } from "@/components/ui/color-picker";

const [color, setColor] = useState("#4F46E5");

<ColorPicker aria-label="Brand color" value={color} onValueChange={setColor} />
```

## Examples

### In a popover, with a contrast check

The field shows the color and its code and opens the picker in a `Popover`. `contrastWith` measures white text on the chosen color, warns below 4.5:1 (`contrastTarget={3}` for icons and borders) and offers the nearest shade that passes, without blocking the choice. `showAlpha={false}` for colors that are always opaque.

Live preview: https://ritla.app/_kanz/preview/ltr/color-picker-popover

## API reference

### `ColorPicker`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value / onValueChange` | `string / (value: string) => void` | None | The color: `#RRGGBB`, or `#RRGGBBAA` when it isn't fully opaque. |
| `swatches` | `{ value, name? }[]` | None | The saved colors: a short row, most recent first. `name` is read with the code ("Brand indigo, #4F46E5"). Leave it out to hide the row. |
| `onAddSwatch` | `(value: string) => void` | None | The Add link: saves the current color. |
| `showAlpha` | `boolean` | `true` | The opacity bar and its field. |
| `contrastWith / contrastTarget` | `string / number` | `contrastTarget: 4.5` | The color that will sit with the chosen one (the text on it). Below the target a warning shows with the nearest shade that passes. |
| `aria-label` | `string` | None | The picker's name ("Brand color"). |

## Accessibility

Keyboard (keys as in left-to-right; arrows swap in right-to-left):

- `Tab`: The colorspace, then hue, then opacity, then the fields, then the swatches.
- `ArrowLeft` + `ArrowRight`: In the colorspace: saturation; on a bar: its value. Right raises it in both languages, since the bars run left to right.
- `ArrowUp` + `ArrowDown`: In the colorspace: brightness; with Shift, in 10% steps.
- `PageUp` + `PageDown` + `Home` + `End`: On a bar: a tenth of the range, and the ends.
- `Enter`: In the HEX field, applies the value.

ARIA:

- The colorspace and both bars are `role="slider"` with their values in words ("Saturation 70%, brightness 90%").
- The swatches are a radio group, each named with its name and code; the selected one keeps a visible ring, never color alone.
- The HEX field is the precise keyboard way in: it takes the code with or without #, in any case, and the short form.

## Arabic and RTL notes

Mirrors:

- The field row (the HEX format, then the code, then opacity), the Saved colors row with Add, and the swatches.

Does not mirror:

- The colorspace and the hue and opacity bars: a fixed color scale, red at the left in both languages.
- The HEX code stays left to right, with Latin letters and Western digits.

Numerals: Percentages (opacity, saturation, brightness, contrast) follow `numerals`; the HEX code never does.

Arabic typography: The fields are `label-14` Medium and the swatch heading `label-12`; no fixed heights on Arabic text.
