Color Picker
HSV 色相環 + アルファ選択のポップオーバー型入力です。色領域・チャンネルスライダーの見た目は CSS グラデーションと thumb 位置のみで表現し、canvas/web-sys には依存しません(値の算出は決定的な純粋関数が担います)。
fandhe-frontend-headless-ui の color_picker mod が提供する構造・アクセシビリティ(WAI-ARIA・キーボード操作)・表示状態(data-*)のみを持つ unstyled 部品です。Themes 版が備える見た目(実際のグラデーション CSS 等)は持たず、anatomy・ARIA・data-* のみを提供します。CSS は利用者が当てます。
ColorPickerProps(disabled/readonly/invalid/required)が Root/Label/Control/Trigger/Area/AreaBackground/AreaThumb/ChannelInput へ data-disabled/data-readonly/data-invalid を一律付与し、Label のみ追加で data-required を付与します(required は <input type="hidden"> である HiddenInput には効果を持たせません)。ChannelSlider/ChannelSliderTrack/ChannelSliderThumb は Channel::as_str() の固定語彙(hue/saturation/value/alpha)による data-channel と、Orientation 引数による data-orientation を出力します(ChannelSliderThumb には aria-orientation も付与)。ChannelInput は data-channel="hex" 固定リテラルを出力し、readonly のときネイティブ readonly 属性、invalid のとき aria-invalid="true" を追加します(valid のときは aria-invalid 自体を省略します)。
キーボード操作
| キー | 対象 | 効果 |
|---|---|---|
| Enter | Trigger | popover を開く(dispatch "open") |
| Enter | ChannelInput | HEX 文字列を確定する(dispatch "set_hex") |
| Esc | Content | popover を閉じる(dispatch "close"。trigger へのフォーカス復帰は呼び出し側の DOM 配線が担います) |
| ArrowLeft / ArrowRight | ChannelSliderThumb | 該当チャンネルを 1 減らす/増やす(dispatch "decrement"/"increment"、0..=Channel::max() へ clamp、ラップしません) |
| ArrowUp / ArrowDown | AreaThumb | 彩度・明度をそれぞれ 1 単位変化させる(dispatch "set_channel" で表現) |
| Home / End | ChannelSliderThumb | 最小値・最大値へ設定する(dispatch "set_channel" の 0/最大値ペイロードで表現) |
ポインタ・キーボード操作の実際の DOM 配線(fandhe-frontend-wasm-full)は本イシューのスコープ外です。本部品は SSR 静的マークアップと dispatch 契約のみを提供します。
スタイル済みの表示例は Color Picker を参照してください。
関連 API: fandhe-frontend-headless-ui API
自前 CSS の最小例
Themes 版を使わず本部品を直接使う場合、[data-scope="color-picker"][data-part="..."] セレクタでスタイルを当てます。以下は area/area-thumb の配置、hue スライダーのグラデーション、状態セレクタの最小例です。
[data-scope="color-picker"][data-part="area"] {
position: relative;
width: 100%;
aspect-ratio: 4 / 3;
}
[data-scope="color-picker"][data-part="area-thumb"] {
position: absolute;
/* --fandhe-color-picker-x/-y は呼び出し側が area-thumb の attrs
経由で style 属性に設定する(例:
("style", "--fandhe-color-picker-x: 40%; --fandhe-color-picker-y: 30%"))。 */
left: var(--fandhe-color-picker-x, 0%);
top: var(--fandhe-color-picker-y, 0%);
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
border: 2px solid #fff;
transform: translate(-50%, -50%);
}
[data-scope="color-picker"][data-part="hue-slider-track"] {
height: 0.75rem;
border-radius: 999px;
background: linear-gradient(
to right,
red,
yellow,
lime,
cyan,
blue,
magenta,
red
);
}
[data-scope="color-picker"][data-part="root"][data-disabled] {
opacity: 0.5;
}
[data-scope="color-picker"][data-part="channel-input"][data-invalid] {
outline: 2px solid crimson;
}
[data-scope="color-picker"][data-part="trigger"][data-state="open"] {
outline: 2px solid #333;
}Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- root/label/control/trigger/positioner/content/area/area_background/area_thumb/channel_slider(+track/+thumb)/channel_input/value_text/hidden_input の anatomy を持ち、Disclosure(開閉)+ HSV + アルファの値状態機械と組み合わせる(color_picker.rs:1-9)。
- ColorPickerProps(disabled/readonly/invalid/required)を root/label/control/trigger/area/area_background/area_thumb/channel_input へ一律付与し、label のみ data-required を追加する(イシュー #1604 参照突合、color_picker.rs:277-291)。
- trigger は type="button" + aria-haspopup="dialog" を固定付与し、controls が Some のとき aria-controls で content と関連付ける(color_picker.rs:426-452)。
- content(role="dialog")・area_thumb/channel_slider_thumb(role="slider")が WAI-ARIA の該当パターンへ従う(color_picker.rs:470-489, 524-547, 592-628)。
- channel_slider(+track/+thumb) は Channel::as_str() 固定語彙による data-channel と、Orientation 引数による data-orientation(thumb には aria-orientation も)を出力する(color_picker.rs:549-628)。
- channel_input は data-channel="hex" 固定リテラルを出力し、readonly ネイティブ属性・aria-invalid(invalid のときのみ)を追加する(color_picker.rs:632-657)。
- increment/decrement dispatch(Channel 固定語彙 payload)は現在値を ±1 し 0..=Channel::max() へ clamp する(ラップしない、color_picker.rs:1049-1103)。
- 色領域・スライダーの見た目は CSS グラデーションと決定的な導出 getter のみで表現し、canvas/web-sys へ一切依存しない(color_picker.rs:11-18)。
Anatomy
root
label
control
trigger
positioner
content
area
area-background
area-thumb
hue-slider
hue-slider-track
hue-slider-thumb
channel-input
value-text
hidden-inputAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root(state) / control(state) / trigger(state) / content(state) | OpenState | OpenState::Closed | 開閉状態。data-state・aria-expanded・positioner の hidden 出力の判定に使われる(同じ型のため代表 1 行に集約)。 |
root/label/control/trigger/area/area_background/area_thumb/channel_input(props) | &ColorPickerProps | &ColorPickerProps::default() | disabled/readonly/invalid を一律付与する(label のみ追加で required→data-required)。 |
trigger(controls) | Option<&str> | None | Some のとき aria-controls で content と関連付ける(color_picker.rs:439-441)。 |
area_thumb(hex) | &str | — | 2 次元 slider(role="slider")の aria-valuetext。現在色の HEX 正規形(color_picker.rs:524-537)。 |
channel_slider/channel_slider_track/channel_slider_thumb(channel, orientation) | Channel, Orientation | — | data-channel(固定語彙)と data-orientation(thumb には aria-orientation も)を出力する(color_picker.rs:549-628)。 |
channel_slider_thumb(min, max, now) | &str, &str, &str | — | WAI-ARIA slider パターンの aria-valuemin/aria-valuemax/aria-valuenow(color_picker.rs:592-628)。 |
hidden_input(name, value, props) | &str, &str, &ColorPickerProps | — | フォーム送信用の実体(type="hidden"、props.disabled のときのみ disabled 属性、required は付けない、color_picker.rs:676-691)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
channel-input | data-channel | hex |
channel-input | data-invalid | (値なし) |
channel-input | data-readonly | (値なし) |
content | data-state | closed, open |
control | data-invalid | (値なし) |
control | data-readonly | (値なし) |
control | data-state | closed, open |
hue-slider | data-channel | hue |
hue-slider | data-orientation | horizontal |
hue-slider-thumb | data-channel | hue |
hue-slider-thumb | data-orientation | horizontal |
hue-slider-track | data-channel | hue |
hue-slider-track | data-orientation | horizontal |
label | data-invalid | (値なし) |
label | data-readonly | (値なし) |
label | data-required | (値なし) |
positioner | data-state | closed, open |
root | data-invalid | (値なし) |
root | data-readonly | (値なし) |
root | data-state | closed, open |
trigger | data-invalid | (値なし) |
trigger | data-readonly | (値なし) |
trigger | data-state | closed, open |
Examples
Closed trigger
aria-expanded="false" の閉じた Color Picker trigger/content の例です。
閉じた状態(aria-expanded="false")の Color Picker trigger/content の組み立て例です。
自前 CSS の最小例
headless-ui 自体はスタイルを持たないため、data-* 属性セレクタで見た目を組み立てる最小例です。
利用者が data-scope / data-part / data-state / data-disabled / data-invalid 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。
[data-scope="color-picker"][data-part="area"] {
position: relative;
width: 100%;
aspect-ratio: 4 / 3;
}
[data-scope="color-picker"][data-part="area-thumb"] {
position: absolute;
left: var(--fandhe-color-picker-x, 0%);
top: var(--fandhe-color-picker-y, 0%);
}
[data-scope="color-picker"][data-part="hue-slider-track"] {
background: linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red);
}
[data-scope="color-picker"][data-part="root"][data-disabled] {
opacity: 0.5;
}
[data-scope="color-picker"][data-part="channel-input"][data-invalid] {
outline: 2px solid crimson;
}
[data-scope="color-picker"][data-part="trigger"][data-state="open"] {
outline: 2px solid #333;
}
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Enter | trigger にフォーカス時: popover を開く(dispatch "open")。channel_input にフォーカス時: HEX 文字列を確定する(dispatch "set_hex")。 |
| Esc | content が開いているとき popover を閉じる(dispatch "close")。trigger へのフォーカス復帰は呼び出し側の DOM 配線が担う(スコープ外、モジュール doc「参照突合」節参照)。 |
| ArrowLeft / ArrowRight | channel_slider_thumb にフォーカス時: 該当チャンネルを 1 減らす/増やす(dispatch "decrement"/"increment"、0..=Channel::max() へ clamp、ラップしない)。 |
| ArrowUp / ArrowDown | area_thumb にフォーカス時: 彩度・明度をそれぞれ 1 単位変化させる(dispatch "set_channel" で表現)。 |
| Home / End | channel_slider_thumb にフォーカス時: 最小値・最大値へ設定する(dispatch "set_channel" の 0/最大値ペイロードで表現、専用 dispatch は追加しない)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-haspopup="dialog" | trigger パーツへ固定付与する(color_picker.rs:435)。 |
| aria-expanded | trigger の開閉状態(state.is_open())を反映する(color_picker.rs:436)。 |
| role="dialog" | content パーツへ固定付与する(color_picker.rs:478)。 |
| role="slider" / aria-valuetext | area_thumb・channel_slider_thumb の両方が role="slider" を固定付与する(area_thumb は aria-label="Color" + aria-valuetext のみ、channel_slider_thumb は aria-valuemin/max/now + aria-orientation も付与、color_picker.rs:524-547, 592-628)。 |
| aria-invalid="true" | channel_input が props.invalid のときのみ付与する(valid のときは属性自体を省略、color_picker.rs:632-657)。 |
| aria-disabled="true" | area_thumb・channel_slider_thumb が props.disabled のとき tabindex="-1" と対で付与する(color_picker.rs:524-547, 592-628)。 |