フィールド
hc-field は、ラベル・コントロール・任意のヘルプまたはエラーメッセージを
まとめる薄い合成クラスです。妥当性は、入力側の標準 aria-invalid 属性と、
ラッパー側の data-invalid="true" で表現します。これによりメッセージの
色と枠線の色が一緒に更新されます。
別名: フォームフィールド、フォームグループ。
基本の HTML
Section titled “基本の HTML”<div class="hc-field"> <label class="hc-field__label" for="email">Email</label> <input id="email" class="hc-input" name="email" type="email"> <p class="hc-field__message">Use your work email.</p></div>無効(invalid)状態
Section titled “無効(invalid)状態”<div class="hc-field" data-invalid="true"> <label class="hc-field__label" for="email">Email</label> <input id="email" class="hc-input" name="email" type="email" aria-invalid="true" aria-describedby="email-error"> <p id="email-error" class="hc-field__message"> Enter a valid email address. </p></div>2 つの属性が連携します:
- ラッパーの
data-invalid="true"はメッセージの色を切り替え、入力欄の 枠線を強調します。これは視覚用のフックです。 - 入力側の
aria-invalid="true"がアクセシビリティ上のシグナルで、aria-describedbyがエラーメッセージを指します。
サーバレンダリングされるフォームでは、バリデーション失敗時にこの 2 つを アトミックに設定してください。
ヒントとエラーの区別
Section titled “ヒントとエラーの区別”data-invalid はすべての .hc-field__message の色を切り替えます —
メッセージがバリデーション結果そのものであることが多いための設計です。
妥当性に関係なく常に真である案内(「We never share it.」)は
.hc-field__hint に置いてください。invalid なフィールドの中でも
ミュート色を保つため、読者は「助言」と「問題」を見分けられます:
We never share it.
<div class="hc-field" data-invalid="true"> <label class="hc-field__label" for="email">Email</label> <input id="email" class="hc-input" name="email" type="email" aria-invalid="true" aria-describedby="email-hint email-error"> <p id="email-hint" class="hc-field__hint">We never share it.</p> <p id="email-error" class="hc-field__message"> Enter a valid email address. </p></div>適用中の条件: data-applied
Section titled “適用中の条件: data-applied”行が 8 つある検索パネルでは、「いま何が設定されているか」は 8 行すべて
読まないと分かりません。フィールドに data-applied を付けると、ラベルに
点が付きます。
<div class="hc-field" data-applied> <label class="hc-field__label" for="f-buyer">Buyer code</label> <input class="hc-input" id="f-buyer" name="f-buyer" value="A-100"></div>点は走査の補助であって通知ではありません。適用中の条件はデータの
上にコントロールの一覧として既に出ており
(datagrid-filter)、
スクリーンリーダーが読むのはそちらです。色とサイズは
--hc-field-applied-marker-color / --hc-field-applied-marker-size
です。
フォームを組み立てる
Section titled “フォームを組み立てる”完全なフォームに必要なのはキットのクラスだけです — ラベルのレイアウト、 コントロールの幅、必須マーカー、ヘルプテキスト、アクション行のための アプリ側 CSS は不要です:
<form> <div class="hc-field"> <label class="hc-field__label" for="realm">Realm id</label> <input class="hc-input" id="realm" name="realmId" required placeholder="local" aria-describedby="realm-help"> <p class="hc-field__message" id="realm-help">Lowercase letters only.</p> </div>
<div class="hc-field"> <label class="hc-field__label" for="display">Display name</label> <input class="hc-input" id="display" name="displayName"> </div>
<!-- Related radios/checkboxes: the field is a <fieldset> --> <fieldset class="hc-field"> <legend class="hc-field__label">Mode</legend> <label><input type="radio" name="mode" value="standard" checked> Standard</label> <label><input type="radio" name="mode" value="strict"> Strict</label> </fieldset>
<!-- Actions row --> <div class="hc-cluster"> <button type="submit" class="hc-button" data-variant="primary">Create realm</button> <button type="button" class="hc-button" data-variant="ghost">Cancel</button> </div></form>このフォームのすべてはデフォルトの挙動です:
- ラベルの関連付けはネイティブ —
for/id。ラベルをクリックすると コントロールにフォーカスが移ります。(暗黙のラップも動きますが、明示的な 形のほうがスタイルもターゲットもしやすいです。) - 必須アスタリスクは自動 —
[required]コントロールを含むフィールドは ラベルに印を付けます。<span class="req">*</span>は不要です。 - コントロールはフィールドいっぱいに広がる —
.hc-fieldはグリッド (アイテムは伸長)で、hc-input/hc-selectはデフォルトでinline-size: 100%です。form .hc-input { width: 100% }のような アプリ CSS は不要です。 - ヘルプテキストは
.hc-field__message(状態連動 — フィールドと 一緒に赤くなる)または.hc-field__hint(恒常 — ミュート色を保つ。 ヒントとエラーの区別参照)。エラースロット (.hc-field__error)はクライアントサイドバリデーション またはサーバが埋めます — 領域を確保したい場合にだけ書いてください。 - ラジオ / チェックボックスのグループは
fieldset.hc-field— キットが ネイティブ fieldset の装飾を取り除き、<legend>がラベルクラスを 受け持ちます。 - アクション行は
.hc-cluster(折り返すフレックス行)です。端寄せやキーボード操作可能なコントロール列にはdata-hc-spacerつきのツールバーを 使ってください。
フィールド間の余白はフォームの責務で、フィールドの責務ではありません —
フォーム側で .hc-stack
(または display:grid; gap ルール)を使ってください。
htmx での利用
Section titled “htmx での利用”サーバサイドバリデーションでは、フィールド全体をサーバから返して同じ場所に
スワップします。返す HTML に data-invalid と aria-invalid を設定して
おけば、フィールドは自動で再スタイルされます。
<form data-hx-post="/users" data-hx-target="this" data-hx-swap="outerHTML"> <div class="hc-field" id="email-field"> <label class="hc-field__label" for="email">Email</label> <input id="email" class="hc-input" name="email" type="email"> <p class="hc-field__message">Use your work email.</p> </div>
<button class="hc-button" data-variant="primary" type="submit"> Create account </button></form>サーバは同じ <form>(または失敗した
<div class="hc-field" id="email-field" data-invalid="true">… だけ)を、
適切な属性と説明的なメッセージつきで返します。
クライアントサイドバリデーション
Section titled “クライアントサイドバリデーション”ネイティブの HTML 制約バリデーション(required、type="email"、
pattern、min / max、minlength…)は、フィールドごとのコードなしで
フィールドに配線されます。
スタイリングに JavaScript は不要です。 各コントロールは標準の
:user-invalid
疑似クラスに反応します — ユーザーが操作した後(フィールドからフォーカスを
外した、またはフォームを送信した)にだけ invalid になり、初回描画では
なりません。必須コントロールは、そのフィールドのラベルに自動で
アスタリスクを付けます。
メッセージと ARIA は installValidation() が担当します(自動初期化の
/behaviors バンドルに
含まれます)。フォーカスが外れたとき — 以降はリアルタイムに — コントロールの
ネイティブでローカライズ済みの validationMessage を .hc-field__error
要素(なければ作成)へ書き込み、コントロールに aria-invalid="true"、
フィールドに data-invalid="true" を設定し、コントロールの
aria-describedby をエラーへ向けます。コントロールが再び valid になると
すべてを解除します。送信時は、ブラウザ標準のバルーンがインラインメッセージに
置き換わり、無効な送信は引き続きブロックされます。
<form> <div class="hc-field"> <label class="hc-field__label" for="email">Email</label> <input id="email" class="hc-input" name="email" type="email" required> <!-- installValidation() fills this on demand; you can also author it --> <p class="hc-field__error" aria-live="polite"></p> </div> <button class="hc-button" data-variant="primary" type="submit">Submit</button></form>メッセージテキスト(--hc-field-invalid-message-color)と :user-invalid
の枠線は、手動の aria-invalid / data-invalid フックと同じエラートークンを
共有するので、サーバレンダリングのエラーとクライアントサイドのエラーは
見た目が揃います。両者は組み合わせられます: ネイティブ制約はクライアントが
即座に捕まえ、一意性などサーバにしか検査できないルールはサーバが
data-invalid="true" を返します。
サーバサイドバリデーションエラー
Section titled “サーバサイドバリデーションエラー”サーバにしか検査できないルール(一意性、競合)については、
field-errors レシピが、
送信失敗時にサーバが返す小さなアラートフラグメントを定義しています。
installFieldErrors()(同じく自動初期化バンドルに含まれます)が各エラーを
対応するフィールドの .hc-field__error へ、上で説明したとおりの ARIA
配線つきで振り分け、ユーザーがフィールドを編集するとクリアし、
data-message-key を i18n カタログで
解決できるようにします。同じコントロールではネイティブ制約メッセージが
優先されます。
アクセシビリティ
Section titled “アクセシビリティ”<label>はforで入力のidを参照する必要があります。暗黙のラベル (<label>で入力を包む)も妥当ですがスタイルしにくいため、明示的な形を 推奨します。- 無効なフィールドでは
aria-invalid="true"を設定し、aria-describedbyでメッセージ要素を指して、スクリーンリーダーがエラーを読み上げられるように してください。 - メッセージはヘルプテキストに
--hc-field-message-color、エラーに--hc-field-invalid-message-colorを使います — どちらもデフォルトの トークンで--hc-color-surfaceに対して WCAG AA コントラストを 満たします。 - 色だけに頼らないでください。エラーメッセージのテキストそのものが第一の アクセシビリティシグナルです。
テーマ用トークン
Section titled “テーマ用トークン”component トークン(component.tokens.json):
| トークンパス | 用途 |
|---|---|
field.gap | 縦方向の間隔。 |
field.label-color | ラベルの色。 |
field.label-weight | ラベルのフォントウェイト。 |
field.label-font-size | ラベルのフォントサイズ。 |
field.message-color | ヘルプテキストの色。 |
field.message-font-size | ヘルプテキストのフォントサイズ。 |
field.invalid-message-color | エラーメッセージの色。 |
field.applied-marker-color | data-applied ドットの色。 |
field.applied-marker-size | data-applied ドットのサイズ。 |
CSS 変数
Section titled “CSS 変数”生成される CSS 変数を表示
--hc-field-gap--hc-field-label-color | -label-weight | -label-font-size--hc-field-message-color | -message-font-size--hc-field-invalid-message-color--hc-field-applied-marker-color | -applied-marker-size--hc-field-required-color /* the required asterisk; defaults to --hc-color-error */