Field
fandhe-frontend-pre-styled-ui の field mod が提供するスタイル済み Field 部品です。Root / Label / HelperText / ErrorText / RequiredIndicator の 5 パーツに加え、Group / Content / Title / Separator(内部パーツ SeparatorLine / SeparatorContent)の 6 パーツ(イシュー #2185 で純追加、shadcn/ui FieldGroup / FieldContent / FieldTitle / FieldSeparator 相当)の計 11 パーツ構成で、ラベル・補助テキスト・エラーテキスト・必須マークの型階層と root の余白レイアウトを提供します。配置軸は orientation(既定 vertical の縦積み、horizontal の横並び、responsive の 3 値)のみを持ちます。responsive(イシュー #2199)は Group(container)の内側に置いた場合にのみ意味を持ち、Group の inline サイズが 448px 以上のときだけ horizontal と同じ横並びへ切り替わります。Group の外に置いた場合は常に縦積みのままです。horizontal(および 448px 以上の responsive)のとき、HelperText は text-wrap: balance で行長を均して横並びレイアウトでの読みやすさを高めます(イシュー #2160、shadcn/ui FieldDescription 突合。未対応ブラウザでは通常の折り返しのまま変化しません)。
Group は複数の Field(Root)を縦に束ねる外側コンテナ、Separator は線のみ/テキスト付きの区切り線です。Content / Title は <label for> を結び付けにくい場面(複数コントロールの見出し等)で Label の代替として使う見出し + 補助テキストの列で、Title は for/id を自動導出しないため、呼び出し側が Title の id を対応するコントロールの aria-labelledby へ渡して結び付けます。
コントロール(input/textarea/select)は本部品が所有せず、Input / Textarea / Native Select の各部品が同じ headless-ui field scope を共有して提供します。data-invalid / data-disabled / data-required / data-readonly はいずれも headless 層が出力する状態を CSS セレクタとして参照して見た目を切り替えるだけで、値の妥当性判定・送信処理といったバリデーション自体はこの部品では実装しません。
root_with_label_placement を使うと、orientation とは独立なラベル配置(イシュー #3134)として inset(枠の内側・上部にラベルを置く)と overlap(ラベルを枠線の上へ重ねる)を選べます(既定 outside は従来の root と同じ出力)。inset は inset_stack wrapper の直下に縦に並べると枠線を共有して連結します(wrapper の外、group の中などでは連結しません)。overlap は --fandhe-field-label-bg でラベル背景を地の色に合わせられます。どちらも枠線は root が描くため、data-invalid(枠線色)とフォーカスリングは root 側で表示されます(data-disabled の半透明化は従来どおり各パーツ側のみ)。いずれも orientation = vertical での使用を前提とし、horizontal/responsive との併用は対象外です。
data-invalid が立っているとき、Label のテキスト色もエラー色(--fandhe-color-danger)へ切り替わります。エラー内容は ErrorText のテキストで別途伝わるため、色のみに依存した表示にはなりません。
ErrorText に単一のテキストではなく <ul>(各エラーを <li> で列挙)を子要素として渡すと、複数エラーメッセージ向けのリスト整形(縦積み・字下げ・disc マーカー)が適用されます。<ul>/<li> の組み立てや重複排除自体はこの部品の責務ではなく、呼び出し側が fandhe_frontend_core::el / text で構築して渡してください。
関連 API: fandhe-frontend-pre-styled-ui API / fandhe-frontend-headless-ui API
Demo
ラベル・補助テキスト・エラーテキスト・必須マークの型階層と余白を提供する静的コンテナ部品。コントロール(input/textarea/select)は各コントロール部品が所有し、data-invalid 等を CSS セレクタとして参照して見た目を切り替えるだけでバリデーション自体は実装しません。orientation="responsive" は group(container)を 448px 以上に広げると横並びへ切り替わります。forms_motion(イシュー #2545、motion feature opt-in)の下線伸長・フローティングラベルは末尾 2 件で実演します(Invalid インスタンスは shake・error-text の presence 遷移も同時に実演します)。
- Must be at least 8 characters.
- Must contain a number.
Or continue with
Features
- root/label/helper-text/error-text/required-indicator/group/content/title/separator/separator-line/separator-content の 11 slot に型階層と余白(
orientation:vertical(既定)/horizontal/responsive)を提供する(イシュー #2185 で group/content/title/separator の 6 slot を純追加)。コントロール(input/textarea/select)はinput/textarea/native_selectの各 recipe が同じ"field"scope を共有して所有するため、本モジュールは宣言しない(field.rsモジュール doc「本モジュールが宣言する slot」節)。 orientation="responsive"(イシュー #2199)はgroup(container slot、@containerクエリ)の inline サイズが 448px 以上のときのみhorizontalと同じ配置へ切り替わる。groupの外に置いた場合は常に縦積みのまま(mobile-first の安全な劣化)。orientation="horizontal"(および 448px 以上のresponsive)のとき、helper-textはtext-wrap: balanceで行長を均す(イシュー #2160、shadcn/uiFieldDescriptionのgroup-has-[[data-orientation=horizontal]]/field相当。未対応ブラウザでは宣言が無効値として破棄されるだけで劣化しない)。orientationのみを持つ variant 軸(size/colorPaletteは非提供。ラベル・補助テキストの文字サイズは固定の型階層で表現する設計判断)。data-invalid/data-disabled/data-required/data-readonlyはいずれも headless-uifield::rootが出力する状態を CSS セレクタとして参照するだけで、値の妥当性判定・送信処理といったバリデーション自体は実装しない(docs/policy/intentional-non-adoption.md§3.25 規則 1)。error-text/required-indicatorは非該当状態でhidden存在属性を付与する headless 側の fail-closed 描画に従い、[hidden] { display: none; }のみを重ねる(独自の表示切替ロジックは持たない)。- hover / focus ring / transition はいずれも意図的に非採用(実フォーカスはコントロール側にあり、状態遷移に伴う視覚変化がないため)。
groupは複数Field(root)を縦積みする外側コンテナ、separatorは線のみ/テキスト付きの区切り線(separator-line/separator-contentの 2 内部パーツから成る)、content/titleは<label for>を結び付けられない場面(複数コントロールの見出し等)でlabelの代替として使う見出し + 補助テキストの列(イシュー #2185、shadcn/uiFieldGroup/FieldSeparator/FieldContent/FieldTitle相当)。root_with_label_placementでorientationとは独立なラベル配置 variant(FieldLabelPlacement:Outside(既定)/Inset/Overlap)を選べる(イシュー #3134)。Insetはroot自身に枠線・背景を持たせ内側上部にラベルを置き、Overlapはラベルを枠線の上へ重ねる。どちらも枠線をrootが描くため、invalid の枠線色と:focus-withinのフォーカスリングをroot側で表示し、input自身のoutlineは打ち消す(disabled の半透明化は各パーツ側のみ)(モジュール doc「状態表示の対応表」節参照)。いずれもorientation = Verticalでの使用のみを前提とする。
Anatomy
root
label
required-indicator
input
helper-text
error-text
group
separator
separator-line
separator-content
content
titleAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
props | &FieldRootProps | — | orientation(vertical(既定)/horizontal/responsive)を束ねる構造体。responsive は group を container として 448px 以上で横並びに切り替わる(イシュー #2199)。 |
field | &FieldProps<'_> | — | id・disabled・invalid・required・readonly・has_helper_text 等、headless-ui field スコープ共通の状態。 |
attrs | Vec<(&str, &str)> | — | root へ合成する追加属性(class は recipe クラスへ置き換えられ除去される)。 |
children | Vec<Node> | — | root 配下の子ノード(label/コントロール/helper_text/error_text 等)。 |
group | fn(attrs, children) -> Node | — | 複数 root を縦積みする外側コンテナ(イシュー #2185)。FieldProps を取らず data-* を出力しない。 |
separator | fn(attrs, content: Vec<Node>) -> Node | — | テキスト付き区切り線(イシュー #2185)。content が空なら線のみ、非空なら separator-content を追加描画する。 |
content / title | fn(field, attrs, children) -> Node | — | 見出し(title)+ 補助テキストの列を束ねる content(イシュー #2185)。title は <label for> を自動導出しないため、呼び出し側が attrs で id を渡しコントロールへ aria-labelledby で結び付ける。 |
root_with_label_placement | fn(props, placement: FieldLabelPlacement, field, attrs, children) -> Node | — | root にラベル配置 variant を重ねて組み立てる(イシュー #3134)。placement が FieldLabelPlacement::Outside(既定)のときは root と完全に同じ出力になる。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
error-text | data-disabled | (値なし) |
error-text | data-invalid | (値なし) |
error-text | data-readonly | (値なし) |
error-text | data-required | (値なし) |
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 | (値なし) |
CSS Variables
| Variable | Default |
|---|---|
--fandhe-field-label-bg | var(--fandhe-color-bg) |
Examples
Field group + separator
複数の Field を group で縦積みし、線のみの separator とテキスト付き separator("Or continue with")を挟む合成例です(イシュー #2185、docs/design/reference-screenshots/shadcn-field-1.png の Payment Method フォーム相当)。
Or continue with
Content + title レイアウト
<label for> を結び付けにくいチェックボックス見出しを content/title で表現する合成例です(イシュー #2185、docs/design/reference-screenshots/shadcn-field-2.png の説明文配置に近い構成)。title の id をコントロールの aria-labelledby へ渡して結び付けます。
Responsive orientation(@container)
orientation="responsive" の 2 つの Field を group(container)の内側に配置した合成例です(イシュー #2199、docs/design/reference-screenshots/shadcn-field-3.png)。group の inline サイズが 448px 以上のときのみラベルと入力欄が横並びに切り替わり、未満のときは縦積みのままです。
Inset label
FieldLabelPlacement::Inset でラベルを枠の内側・上部に配置する例です(イシュー #3134)。root 自身が枠線・背景を持ち、input は枠内に溶け込むようリセットされます。
Inset labels with shared borders
Inset の 2 つの Field を field::inset_stack の直下へ縦に並べ、枠線を共有して連結する例です(イシュー #3134)。中間の境界線が 1 本になり、角丸は上下の端にのみ付きます。連結規則は inset_stack の中でだけ発動し、group など gap 付きコンテナへ直接並べても連結しません。
Overlapping label
FieldLabelPlacement::Overlap でラベルを root の枠線の上へ重ねる例です(イシュー #3134)。--fandhe-field-label-bg でラベル背景を地の色に合わせられます。
Accessibility
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-describedby | コントロール(input/textarea/select)側で、invalid のとき error id、has_helper_text のとき helper id を空白区切りで合成する(headless field::input 等の描画則)。 |
| aria-invalid | invalid が true のときコントロールへ "true" を付与する。 |
| role="alert" / aria-live="polite" | error_text パーツへ固定付与する。role="alert" の暗黙 aria-live="assertive" は明示 polite で上書きされ、shadcn/ui FieldError とのロール語彙パリティを純追加する(イシュー #2184)。 |
| aria-hidden="true" | required_indicator パーツへ固定付与する(装飾目的の印のため)。 |
| label[for] / control id | label の for とコントロールの id は同一 FieldProps から決定的に対応する。 |
| role="group" | group パーツへ固定付与する(イシュー #2185)。 |
| role="separator" / aria-orientation="horizontal" | separator-line(hr)へ固定付与する。テキストは presentational な子孫にならないよう別要素(separator-content)へ分離する(イシュー #2185)。 |
| aria-labelledby | title は for/id を自動導出しないため、呼び出し側が title の id をコントロールの aria-labelledby へ渡して結び付ける運用とする(イシュー #2185)。 |