Skip to content
fandhe-frontendcore v0.4.3
GitHub

Switch

fandhe-frontend-headless-ui の switch mod が提供するオン/オフ切り替えの unstyled 部品です。Root(<label>)/ Control / Thumb / Label / HiddenInput の 5 anatomy パーツを持ち、crate::state::Checkable を埋め込んだチェック状態機械(data-state は "checked"/"unchecked"、Checkbox/RadioGroup と共有語彙)を備えます。意味論・フォーム送信はネイティブ <input type="checkbox" role="switch">(HiddenInput)に委ねる構造です。

/themes/ 側の Switch(Chakra ライクな variant/size を持つスタイル層)と異なり、CSS を一切持ちません。

スタイル済みの表示例は Switch を参照してください。

関連 API: fandhe-frontend-headless-ui API

Demo

枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。

Features

  • Root(<label>)/ Control / Thumb / Label / HiddenInput の 5 anatomy パーツと、crate::state::Checkable を埋め込んだチェック状態機械を提供する。
  • data-state 値語彙は "checked"/"unchecked"(crate::state::Checkable が一元管理、Checkbox/RadioGroup と共有)。
  • hidden_input は <input type="checkbox" role="switch">(WAI-ARIA APG 準拠)。native の checked がブラウザによって aria-checked へ自動マップされるため、aria-checked を明示付与しない(二重読み上げ防止)。
  • root が <label> のため、内包する hidden_input との暗黙のラベル関連付けが JS なしで成立する(for/id の配線が不要)。
  • イシュー #1622(ark-ui / Radix Primitives との参照突合)で SwitchProps(disabled/readonly/invalid/required)を新設し、data-disabled/data-invalid/data-required/data-readonly を全 5 パーツへ一律反映するよう是正した(従来は root/control の data-disabled のみだった)。
  • 呼び出し側 attrs に data-state/data-disabled/data-invalid/data-required/data-readonly/aria-checked/aria-invalid/type/role/checked/name/value/disabled/required と同名キー(大文字小文字無視)を渡しても fail-closed で除去し、状態の偽装を防ぐ(イシュー #1622 で追加)。
  • 参考サイトとの意図的な差分(data-hover/data-active/data-focus 非出力、Enter キー非配線、readonly 時の native トグル抑止なし、Radix の button role="switch" パターン不採用)は crates/headless-ui/src/switch.rs モジュール doc「参考サイトとの意図的な差分」節を参照。

Anatomy

root
  hidden-input
  control
    thumb
  label

API Reference

Arguments

NameTypeDefaultDescription
root/control/thumb/label(checked)bool—data-state の checked/unchecked を決める。
root/control/thumb/label/hidden_input(props)&SwitchProps—disabled/readonly/invalid/required の 4 フラグ束。全パーツへ対応する data-* を一律反映する(イシュー #1622)。
hidden_input(name, value)&str, &str—ネイティブ name/value 属性。
hidden_input(checked)bool—true のときのみネイティブ checked 存在属性を出力する。
hidden_input(props.disabled)bool—true のときのみネイティブ disabled 存在属性を出力する。
hidden_input(props.required)bool—true のときネイティブ required + data-required を出力する。
hidden_input(props.invalid)bool—true のとき aria-invalid="true" + data-invalid を出力する(イシュー #1622 で追加)。
hidden_input(props.readonly)bool—true のとき data-readonly を出力する。ネイティブ readonly 属性はチェックボックス/スイッチに意味を持たないため付与しない(イシュー #1622 で追加)。

Data Attributes

PartAttributeObserved Values
controldata-disabled(値なし)
controldata-invalid(値なし)
controldata-readonly(値なし)
controldata-required(値なし)
controldata-statechecked, unchecked
hidden-inputdata-disabled(値なし)
hidden-inputdata-invalid(値なし)
hidden-inputdata-readonly(値なし)
hidden-inputdata-required(値なし)
hidden-inputdata-statechecked, unchecked
labeldata-disabled(値なし)
labeldata-invalid(値なし)
labeldata-readonly(値なし)
labeldata-required(値なし)
labeldata-statechecked, unchecked
rootdata-disabled(値なし)
rootdata-invalid(値なし)
rootdata-readonly(値なし)
rootdata-required(値なし)
rootdata-statechecked, unchecked
thumbdata-disabled(値なし)
thumbdata-invalid(値なし)
thumbdata-readonly(値なし)
thumbdata-required(値なし)
thumbdata-statechecked, unchecked

Examples

Disabled, checked

checked: true + props.disabled: true の組み合わせ。hidden_input にネイティブ checked/disabled の両方が存在属性として出力される。

自前 CSS の最小例

利用者が data-scope / data-part / data-state / data-focus-visible / data-disabled / data-invalid 属性セレクタで自前 CSS を当てる最小例です。

利用者が data-scope / data-part / data-state / data-focus-visible / data-disabled / data-invalid 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。

CSS
[data-scope="switch"][data-part="control"] {
  width: 2.5rem;
  height: 1.4rem;
  border-radius: 999px;
  background: #ccc;
}
[data-scope="switch"][data-part="control"][data-state="checked"] {
  background: #2563eb;
}
[data-scope="switch"][data-part="thumb"] {
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 999px;
  background: #fff;
}
[data-scope="switch"][data-part="thumb"][data-state="checked"] {
  transform: translateX(1.1rem);
}
[data-scope="switch"][data-part="control"][data-focus-visible] {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}
[data-scope="switch"][data-part="root"][data-disabled] {
  opacity: 0.5;
}
[data-scope="switch"][data-part="control"][data-invalid] {
  border: 2px solid #dc2626;
}

Accessibility

Keyboard Interactions

KeyDescription
Spacehidden_input はネイティブ <input type="checkbox"> であり、Space キーでのトグルはブラウザ標準操作として成立する(JS 配線不要)。
Enterark-ui / Radix は Enter でもトグルするが、本実装は native checkbox をそのまま使うため Enter では反応しない(意図的非採用。WAI-ARIA APG の Switch パターンでは Enter は Optional 扱い。詳細は crates/headless-ui/src/switch.rs モジュール doc 参照)。

WAI-ARIA

AttributeDescription
aria-hidden="true" (control)装飾専用パーツとして固定付与する(意味論は hidden_input が担う)。
aria-checkedhidden_input へ明示付与しない。native の <input type="checkbox" role="switch"> の checked 状態がブラウザにより自動マップされるため(二重読み上げ防止)。
aria-invalid="true" (hidden_input)props.invalid が true のときのみ出力する(イシュー #1622 で追加)。