Sakuga Back to Sakuga
Theme
Sound
Jump to a component

Core · Forms

SwatchPicker

SwatchPicker chooses a colour by eye: round swatches, the chosen one ringed. Skin tone, a creature's coat.

@anicanon/sakuga/uiv1.0Used onWeb · iOS · Android

Live, from @anicanon/sakuga 2.0.0

Sakuga for iOS and Android is coming

iOS

Coming soon

SwatchPicker for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Android

Coming soon

SwatchPicker for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.

Use it for
A colour chosen by eye from round swatches: a skin tone, a creature's coat (Tabby, Calico).
Not for
  • A choice that reads best as an icon over a nameOptionTiles
  • A short list of plain wordsSelect
  • Any colour, typed or picked from the whole range (a brand colour)ColorPicker
  • Adjusting colour in the editorSliderRow

Guidelines

  • Options are {label, color}; each swatch is named by its label for screen readers.
  • With sound on, a new swatch plays the choose sound (README · Sound).
  • labels writes the names under the swatches (coats, where the names matter: Tabby, Calico).
  • A patterned option passes pattern (stripes, patches, spots) and the marks colours drawn over its base.
  • Put it in a Field with its label; a free description can follow it in the same field.
SwatchPickerExample.jsxReact
import { SwatchPicker } from '@anicanon/sakuga/ui';

const options = [
  { label: 'Black', color: '#1F1D22' },
  { label: 'Grey', color: '#8C8A92' },
  { label: 'Ginger', color: '#D2783A' },
  { label: 'Tabby', color: '#B08A5E', pattern: 'stripes', marks: ['#5C4128'] },
  {
    label: 'Calico',
    color: '#F7F6F2',
    pattern: 'patches',
    marks: ['#D2783A', '#1F1D22'],
  },
  { label: 'Spotted', color: '#E2C38E', pattern: 'spots', marks: ['#3B2B1E'] },
  { label: 'White', color: '#F7F6F2' },
];

export default function SwatchPickerExample() {
  return (
    <>
      <SwatchPicker
        label="Skin tone"
        value="Medium"
        options={[
          { label: 'Porcelain', color: '#f6e3d8' },
          { label: 'Fair', color: '#efd2bd' },
          { label: 'Light', color: '#e3b996' },
          { label: 'Medium', color: '#c99470' },
          { label: 'Olive', color: '#b98a5e' },
          { label: 'Tan', color: '#a8744d' },
          { label: 'Brown', color: '#8a5a3b' },
          { label: 'Deep', color: '#4a2c1c' },
        ]}
      />
      <SwatchPicker label="Coat" value="Black" labels options={options} />
    </>
  );
}

PropsSwatchPickerProps

optionsrequired
SwatchOption[]
label
string
value
string
labels
boolean
Each swatch's name under it.
columns
number
onChange
(value: string) => void
className
string

Types

interface SwatchOption {
    label: string;
    value?: string;
    color: string;
    pattern?: 'stripes' | 'patches' | 'spots';
    marks?: string[];
}
SwatchPickerExample.swiftiOS · coming soon
SwatchPickerExample.ktAndroid · coming soon

Each token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.

Space and shape

swatches-gap
gap-md
8px
swatches-named-row-gap
gap-md
8px
swatches-named-column-gap
gap-sm
6px
swatches-item-gap
gap-xs
4px
swatch-active-scale
scale-press-sm
.94
swatch-size
its own value
32px
swatch-radius
radius-full
9999px
swatch-inset-ring-width
line-hairline
1px
swatch-checked-ring-width
line-strong
2px
swatch-checked-outer-ring-width
ring-outer
calc(2px + 2px)
swatch-focus-outline-offset
focus-ring-offset
3px
swatch-forced-checked-width
line-strong
2px
swatch-forced-checked-offset
ring-gap
2px

Type

swatches-item-font
text-small-strong
600 12px/16px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif

Motion

swatch-press-duration
motion-fast
160ms
swatch-press-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)
swatch-active-duration
motion-instant
100ms
swatch-duration
motion-fast
160ms
swatch-easing
ease-standard
cubic-bezier(0.2, 0, 0, 1)

Checked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.

Result
No issues found, in light or in dark.
By design
A radio group named by label and one Tab stop: arrows move to a swatch and choose it, each a radio named by its option's label and "checked" when chosen. The visible names and pattern drawings are hidden.
Not tested
The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.