Field
1 個のフォームコントロール(input/textarea/select)を label・helper_text・error_text と一貫して結び付ける入力ラッパーです。disabled/invalid/required/readonly の各フラグから for/id/aria-describedby/aria-invalid を決定的に合成します。値の検証処理(バリデーションロジック)自体は利用者側の通常の Rust コードが担い、本部品はその結果(invalid/エラーメッセージ)を受け取って構造・ARIA へ反映するだけです。
ark-ui 準拠の 8 パーツに加え、イシュー #2185 で group(複数 root の縦積みコンテナ)・content/title(<label for> を結び付けにくい場面向けの見出し + 補助テキスト列)・separator(内部パーツ separator-line/separator-content から成るテキスト付き区切り線)の 6 パーツを純追加しました(shadcn/ui FieldGroup/FieldContent/FieldTitle/FieldSeparator 相当)。title は for/id を自動導出しないため、呼び出し側が title の id を対応するコントロールの aria-labelledby へ渡して結び付けます。
fandhe-frontend-headless-ui の field mod が提供する構造・アクセシビリティ(WAI-ARIA・キーボード操作)・表示状態(data-*)のみを持つ unstyled 部品です。fandhe-frontend-pre-styled-ui に対応するスタイル済み部品があります。Themes 版は Field を参照してください。
関連 API: fandhe-frontend-headless-ui API
Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Or continue with
Features
- root/label/input/textarea/select/helper_text/error_text/required_indicator の 8 パーツ anatomy を持ち、1 個のコントロールへ label・helper_text・error_text を一貫して結び付ける(ark-ui Field と一致。field.rs:1-10, 54)。純追加のイシュー #2185 で group/content/title/separator(内部パーツ separator-line/separator-content)の 6 パーツを拡張した(shadcn/ui FieldGroup/FieldContent/FieldTitle/FieldSeparator 相当)。
- disabled/invalid/required/readonly の 4 種の data-* 存在属性を 8 パーツすべてへ一貫して付与する(zag.js Field の dataAttrs 規約と一致、field.rs::state_data_attrs)。data-state/data-orientation/data-motion 等の局所操作状態・レイアウト計測の関心は出力しない(chakra-ui の orientation バリアントは styled 層の関心として Themes 側の検討事項、
docs/policy/intentional-non-adoption.md§3.25 規則 2)。Radix Form.Field の data-valid も Form 自体の不採用(同 §3.25 規則 1)に伴い導入しない。 - aria-describedby は invalid のとき error id を先頭に、has_helper_text のとき helper id を続けて空白区切りで決定的に合成する(field.rs:249-258, 305-311)。
- invalid のとき input/textarea/select へ aria-invalid="true" を付与し、error_text を表示状態にする(field.rs:118-119)。
- select はネイティブ readonly を出力しない(HTML 仕様上 <select readonly> が無効なため、data-readonly は他コントロール同様に出力する、field.rs:60-63)。バリデーションの実行自体は利用者側の通常の Rust コードが担い、本モジュールはその結果(invalid/エラーメッセージ)を構造・ARIA へ反映するのみである(
docs/policy/intentional-non-adoption.md§3.25)。 - error_text/required_indicator は非該当状態で hidden 存在属性を付与する fail-closed 描画とする(ark-ui の条件描画を SSR で静的に写像したもの、field.rs::error_text/required_indicator)。has_helper_text は zag.js の MutationObserver による動的検知を静的フラグへ写像したものであり、呼び出し側は実際に helper_text パーツを描画するかどうかと整合させる契約を持つ。
Anatomy
group
root
label
required-indicator
input
helper-text
error-text
textarea
select
separator
separator-line
separator-content
content
titleAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
props.id | &str | — | ベース id。control/label/helper_text/error_text の派生 id 生成に使う(field.rs:103-108)。 |
props.disabled / props.invalid / props.required / props.readonly | bool | false | FieldProps の各フラグ(field.rs:112-135)。data-*・ネイティブ属性・aria-invalid へ反映される(代表 1 行に集約)。 |
props.has_helper_text | bool | false | aria-describedby の合成に helper id を含めるかどうか(field.rs:249-258)。 |
input(props, extra_attrs) / textarea(props, autoresize, extra_attrs, children) / select(props, extra_attrs, children) | &FieldProps, .. | — | 同一の aria-describedby/aria-invalid 合成則に従う 3 種のコントロールパーツ(field.rs:311-374)。 |
group(attrs, children) / separator(attrs, content) | Vec<(&str, &str)>, .. | — | イシュー #2185 で純追加。group は FieldProps を取らず data-* を出力しない。separator は content が空なら線のみ、非空なら separator-content を追加描画する。 |
content(props, attrs, children) / title(props, attrs, children) | &FieldProps, .. | — | イシュー #2185 で純追加。title は for/id を自動導出しないため、呼び出し側が attrs で id を渡しコントロールへ aria-labelledby で結び付ける。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
error-text | data-invalid | (値なし) |
helper-text | data-invalid | (値なし) |
input | data-disabled | (値なし) |
input | data-invalid | (値なし) |
input | data-readonly | (値なし) |
input | data-required | (値なし) |
label | data-disabled | (値なし) |
label | data-invalid | (値なし) |
label | data-readonly | (値なし) |
label | data-required | (値なし) |
required-indicator | data-disabled | (値なし) |
required-indicator | data-invalid | (値なし) |
required-indicator | data-readonly | (値なし) |
required-indicator | data-required | (値なし) |
root | data-disabled | (値なし) |
root | data-invalid | (値なし) |
root | data-readonly | (値なし) |
root | data-required | (値なし) |
textarea | data-autoresize | (値なし) |
Examples
Required + helper text
required_indicator・helper_text・error_text を併用した例です。
required かつ helper_text 併用の Field(バリデーション結果は利用者が渡す)の組み立て例です。
自前 CSS の最小例
data-scope / data-part / data-invalid / data-disabled / data-required 属性セレクタで見た目を組み立てる最小例です。
利用者が data-scope / data-part / data-invalid / data-disabled / data-required 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。
[data-scope="field"][data-part="input"] {
border: 1px solid #888;
border-radius: 4px;
padding: 0.375rem 0.5rem;
}
[data-scope="field"][data-part="input"][data-invalid] {
border-color: #dc2626;
}
[data-scope="field"][data-part="root"][data-disabled] {
opacity: 0.5;
}
[data-scope="field"][data-part="error-text"] {
color: #dc2626;
font-size: 0.875rem;
}
[data-scope="field"][data-part="label"][data-required]::after {
content: " *";
color: #dc2626;
}
group + separator
複数の Field を group で縦積みし、線のみ/テキスト付きの separator を挟む最小例です(イシュー #2185)。
複数の Field を group で縦積みし、線のみの separator とテキスト付き separator を挟む最小例です(イシュー #2185)。
Or continue with
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| Tab / 文字入力 / (select) ↑↓ Space Enter | input/textarea/select がいずれもネイティブ要素であるため、ブラウザ標準のフォーカス移動・入力操作が働く(field.rs:311-374)。select は ↑/↓/Space/Enter によるネイティブの開閉・選択が働く。参照サイト(ark-ui / chakra-ui)の Field も独自のキー操作を持たない。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-describedby | invalid のとき error id、has_helper_text のとき helper id を空白区切りで合成する(field.rs:249-258)。 |
| aria-invalid | props.invalid が true のとき input/textarea/select へ "true" を付与する(field.rs:118-119)。 |
| role="alert" / aria-live="polite" | error_text パーツへ固定付与する。role="alert" の暗黙 aria-live="assertive" は明示 polite で上書きされるため両者は併用でき、読み上げの割り込み度合いは polite のまま shadcn/ui FieldError とのロール語彙パリティを純追加する(field.rs:427-430、イシュー #2184)。 |
| aria-hidden="true" | required_indicator パーツへ固定付与する(装飾目的の印のため、field.rs:399-402)。 |
| label[for] / control id | label の for と input/textarea/select の id は同一 props から決定的に対応する(ids 上書き時も一貫して伝播する、field.rs::control_id/label_id)。 |
| role="group" | group パーツへ固定付与する(イシュー #2185)。 |
| role="separator" / aria-orientation="horizontal" | separator-line(hr)へ固定付与する。テキストは presentational な子孫にならないよう別要素(separator-content)へ分離する(イシュー #2185)。 |