# GradientPicker

Gradient picker: a stop strip with draggable thumbs, an editable CSS value
field, a fully accessible colour-stop list (each stop opens a `ColorPicker` in a popover), and per-type geometry controls (linear angle +
dial, radial size/position, conic position).

The value contract is a CSS gradient string — `linear-gradient(…)`,
`radial-gradient(…)` or `conic-gradient(…)` — accepted (pasted or typed)
and emitted. Stops keep whatever colour strings the ColorPicker accepts,
including `var(--x)` references. An unparseable value falls back to a
default gradient in the controls; committing any edit replaces it.

```tsx
import { GradientPicker, GradientBar } from '@tangible/ui';
```

Interactive docs and examples: [GradientPicker in Storybook](https://storybook-tangible-ui.pages.dev/?path=/docs/forms-gradientpicker--docs).

## GradientPicker props

| Prop | Type | Default | Description |
| - | - | - | - |
| `alpha?` | `boolean` | `true` | Show alpha in the per-stop colour pickers. |
| `aria-label?` | `string` | | Accessible name for the picker group. Takes precedence over `labels.group`. Defines a string value that labels the current element. |
| `className?` | `string` | | |
| `defaultValue?` | `string` | `a two-stop linear gradient` | Uncontrolled initial value. |
| `disabled?` | `boolean` | | |
| `formats?` | `ColorFormat[]` | `all` | Formats offered in the per-stop colour pickers. |
| `labels?` | `GradientPickerLabels` | | Override any user-facing string for i18n. |
| `onValueChange?` | `(value: string) => void` | | |
| `value?` | `string` | | Controlled value — a CSS gradient string. |

Also accepts the standard attributes of `HTMLAttributes` (`data-*`, `aria-*`, event handlers), passed to the element it renders.

## GradientBar props

The stop strip — stops rendered left-to-right as a linear gradient with a draggable thumb per stop, regardless of the gradient's actual type (the strip edits the stop list, not the geometry). Each thumb is a `role="slider"` for its position: arrows nudge (Shift = ×10), Home/End jump, Delete removes, Enter/Space opens the stop's colour editor. Clicking the track between thumbs adds a stop there. The stop LIST rendered by GradientPicker remains the fully accessible editing surface; the bar is the direct-manipulation view of the same data.

| Prop | Type | Default | Description |
| - | - | - | - |
| `stops` | `GradientStop[]` | | Expected sorted by position — thumbs render (and tab) in array order. |
| `activeIndex?` | `number \| null` | | Highlighted stop (the one being edited). |
| `aria-label?` | `string` | | |
| `className?` | `string` | | |
| `disabled?` | `boolean` | | |
| `labels?` | `GradientBarLabels` | | |
| `onActiveIndexChange?` | `(index: number) => void` | | |
| `onStopActivate?` | `(index: number) => void` | | Enter/Space or click on a thumb — open this stop's colour editor. |
| `onStopAdd?` | `(position: number) => void` | | Track click between thumbs. The owner inserts and seeds the colour. |
| `onStopPositionChange?` | `(index: number, position: number) => void` | | Raw position from drag / keyboard — the owner clamps (e.g. to neighbours). |
| `onStopRemove?` | `(index: number) => void` | | Delete/Backspace on a thumb. The owner enforces the two-stop minimum. |

## Other exports

- `defaultGradientPickerLabels`: `Required<GradientPickerLabels>`

## Examples

- [Conic](https://storybook-tangible-ui.pages.dev/?path=/story/forms-gradientpicker--conic): A parsed `from` angle survives the round-trip even though the panel has no control for it yet.

- [var() stop colors](https://storybook-tangible-ui.pages.dev/?path=/story/forms-gradientpicker--variable-stops): Stop colours can be `var(--x)` references — kept verbatim in the emitted value, rendered by CSS wherever the variable resolves.

- [GradientBar (primitive)](https://storybook-tangible-ui.pages.dev/?path=/story/forms-gradientpicker--bar-primitive): The stop strip is exported standalone (like `ColorArea`/`ColorSlider`) for custom compositions. The owner clamps positions and owns the stop data.

- [Pasted CSS normalises](https://storybook-tangible-ui.pages.dev/?path=/story/forms-gradientpicker--paste-anything): The value field accepts hand-written CSS — `to right`, missing stop positions, double-position stops — and normalises it into the canonical emitted form.

Other stories: Full picker (linear), Radial, Many stops + alpha, Disabled ([interactive page](https://storybook-tangible-ui.pages.dev/?path=/docs/forms-gradientpicker--docs)).

## Component API tokens

Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.

- `--tui-gradient-bar-height`
- `--tui-gradient-bar-radius`
- `--tui-gradient-bar-thumb-size`
- `--tui-angle-dial-size`

---

Interactive version: https://storybook-tangible-ui.pages.dev/?path=/docs/forms-gradientpicker--docs
