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.
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).
labelswrites the names under the swatches (coats, where the names matter: Tabby, Calico).- A patterned option passes
pattern(stripes,patches,spots) and themarkscolours drawn over its base. - Put it in a
Fieldwith its label; a free description can follow it in the same field.
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
optionsrequiredSwatchOption[]labelstringvaluestringlabelsbooleanEach swatch's name under it.
columnsnumberonChange(value: string) => voidclassNamestringTypes
interface SwatchOption { label: string; value?: string; color: string; pattern?: 'stripes' | 'patches' | 'spots'; marks?: string[]; }
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-gapgap-md8px
swatches-named-row-gapgap-md8px
swatches-named-column-gapgap-sm6px
swatches-item-gapgap-xs4px
swatch-active-scalescale-press-sm.94
swatch-sizeits own value
32px
swatch-radiusradius-full9999px
swatch-inset-ring-widthline-hairline1px
swatch-checked-ring-widthline-strong2px
swatch-checked-outer-ring-widthring-outercalc(2px + 2px)
swatch-focus-outline-offsetfocus-ring-offset3px
swatch-forced-checked-widthline-strong2px
swatch-forced-checked-offsetring-gap2px
Type
swatches-item-fonttext-small-strong600 12px/16px "Funnel Sans", system-ui, -apple-system, "Segoe UI", sans-serif
Motion
swatch-press-durationmotion-fast160ms
swatch-press-easingease-standardcubic-bezier(0.2, 0, 0, 1)
swatch-active-durationmotion-instant100ms
swatch-durationmotion-fast160ms
swatch-easingease-standardcubic-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
labeland 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.