ComponentsInputs and forms

Color swatch picker

Picks a colour from a fixed set, for a mail tag or a select option. People pick a hue to tell things apart; they never type a hex.

Playground

Change the controls to try each prop. The code under the preview updates as you go and lists only the props you changed; copy it into your page.

States
import { ColorSwatchPicker } from '@/ui/color-swatch-picker';<ColorSwatchPicker label="Colour" />

Swatch row

Where the colour is one field among others, as in the tag form: eight 16px dots on 24px targets. The picked one carries a white check, and the preview shows the tag as it will read.

PreviewWork permit
import { useState } from 'react';
import { ColorSwatchPicker } from '@/ui/color-swatch-picker';
import { Field, FieldLabel } from '@/ui/field';
import { Input } from '@/ui/input';
import { Tag, type TagColor } from '@/ui/tag';

// The tag form: name, colour, and a preview of the tag as it will read.
export default function TagColour() {
  const [name, setName] = useState('Work permit');
  const [color, setColor] = useState<TagColor>('teal');
  return (
    <div className="flex w-full max-w-125 flex-col gap-150">
      <div className="flex flex-wrap items-end gap-200">
        <Field className="w-50">
          <FieldLabel htmlFor="new-tag-name">New tag</FieldLabel>
          <Input id="new-tag-name" value={name} onChange={(event) => setName(event.target.value)} />
        </Field>
        <ColorSwatchPicker value={color} onValueChange={setColor} />
      </div>
      <div className="flex items-center gap-100 text-body-small leading-body-small font-medium text-text-subtle">
        Preview
        <Tag color={color}>{name.trim() || 'Untitled tag'}</Tag>
      </div>
    </div>
  );
}

Option colour

Where the colour belongs to a pill already on screen, as a select option in field settings: the pill opens a radio list of the six option colours, each drawn as the pill would read and named by its hue.

import { OptionColorPicker } from '@/ui/color-swatch-picker';

// Field settings: each select option's pill opens its colours.
export default function OptionColour() {
  return (
    <div className="flex flex-wrap gap-200">
      <OptionColorPicker name="Permanent" defaultValue="blue" />
      <OptionColorPicker name="Contract" defaultValue="green" />
      <OptionColorPicker name="Retained search" defaultValue="plum" />
    </div>
  );
}

States

Disabled fades to 50% while the tag saves. A long option name ends in an ellipsis in its pill, with the full name in a tooltip; names in any script keep their characters.

import { ColorSwatchPicker, OptionColorPicker } from '@/ui/color-swatch-picker';

// While the tag saves, the row waits at 50%. A long option name ends in an ellipsis in its pill.
export default function States() {
  return (
    <div className="flex flex-col items-start gap-200">
      <ColorSwatchPicker label="Colour of Visa sponsor" defaultValue="amber" disabled />
      <OptionColorPicker name="Retained search with exclusivity and a staged fee" defaultValue="amber" />
      <OptionColorPicker name="Nguyễn Thị Minh Khai" defaultValue="red" disabled />
    </div>
  );
}

On this page