スウォッチグループSwatchGroupExperimental

Selectable color swatch group (single-select) with roving keyboard focus and disabled out-of-stock swatches, for product variant and theme pickers.

プレビュー

状態とバリエーション

SwatchGroup が変えられるのは、丸の大きさ(size)、選択を誰が持つか(value と onValueChange)、そして選べない色をどう扱うか(options[].disabled)です。丸の中には文字を置かないので、名前は options[].label だけが持ちます。

丸の大きさ

size は sm・default・lg の3段です。一覧のカードに何色あるかだけを見せるなら sm、商品ページで実際に選ばせるなら default か lg を使います。当たり判定も一緒に変わるので、指で押す画面では小さくしすぎないようにします。

選択を必ず1つ残す

value と onValueChange を渡すと選択が画面側のものになり、選んだ色を名前で出したり、その色の写真へ切り替えたりできます。disallowEmpty を足すと、いま選ばれている丸をもう一度押しても外れません。色を選ばないと注文できない商品はこの形にします。

色: アズール

品切れの色を残したまま出す

disabled にした丸は押せず、矢印キーでも飛ばされます。消さずに残すのは、その色が存在すること自体が買う人には情報だからです。薄く見えることだけが手がかりにならないよう、品切れは label にも書きます。矢印キーで端まで動かすと、選択が品切れの色を飛び越えるのが見えます。

色: インク

Props

表は横にスクロールできます
プロパティ型初期値説明
optionsSwatchOption[]-Swatches: { value, label, color, disabled? }.
valuestring-Selected swatch value (controlled).
onValueChange(value: string) => void-Selection change handler.
size"sm" | "default" | "lg""default"Swatch size.
disallowEmptyboolean-Keep a selection — clicking the active swatch won't clear it.
classNamestring-Additional CSS class names.

Usage

"use client";

import { SwatchGroup } from "@gunjo/ui"

const options = [
  { value: "ink", label: "Ink", color: "hsl(var(--foreground))" },
  { value: "primary", label: "Primary", color: "hsl(var(--primary))" },
  { value: "muted", label: "Muted (sold out)", color: "hsl(var(--muted))", disabled: true },
]

export function Example() {
  const [color, setColor] = React.useState("ink")
  return <SwatchGroup options={options} value={color} onValueChange={setColor} disallowEmpty />
}