AI に設定ウィザード(検証つき多段フォーム)を作らせてみた — "見た目" はあるが "form system" が無い(やってみた #29)
/setup375px のビューポートで撮影。縦長のページはフレーム内をスクロールします。
解説記事
AI に設定ウィザード(検証つき多段フォーム)を作らせてみた — "見た目" はあるが "form system" が無い(やってみた #29)
やってみたシリーズ: 自作のデザインシステム
@gunjo/ui(群青)を、文脈ゼロの cold な AI に実 UI で作らせる連載。今回は マルチステップの設定ウィザード(バリデーション+確認ステップ)。
条件はいつも通り(出荷物の npm パッケージ+docs サイトだけ。ソース非公開)。お題は「ワークスペース作成」4ステップ: アカウント→組織→設定→確認。Next 押下で必須/形式を検証→ブロック→インラインエラー表示→最初の不正フィールドへフォーカス移動、確認ステップで Edit ジャンプ+規約同意で submit。フォームのバリデーション軸を初めて深く突いた。
結果 — 3.5/5
検証付き4ステップウィザードは完璧に動いた(focus-first-error・aria-invalid↔error 連携・step 読み上げ・375px overflow 0・dark 完全)。個々の input は綺麗で a11y-ish。
そして前ラウンドの修正がまた検証された:
Checkboxのlabel/description(#149・前回!)とSwitch(#130)が genuinely nice——内部生成 id で aria を自動配線。RadioGroupも本物の WAI-ARIA。Inputは aria-invalid で赤枠が自動。
3.5 止まりの理由は品質じゃない。「form system」が無いから。
核心の穴 — Form は "見た目" だけ
Form/FormField/FormMessage は名前だけで中身がスタブ(#152・Major)。 context も state も aria も無い。FormMessage は素の <p class="text-destructive">——id も付かず、field に紐付かず、role も無い。shadcn/react-hook-form の FormField パターンを名前は約束するのに、中身が無い。
結果、フィールドごとに手巻き(~90行): id 生成・aria-describedby 組み立て・aria-invalid トグル・必須マーク・role="alert"・focus-first-error。「個々は a11y な input はある、でも label/control/description/error を協調させる層が無い」=form system の不在。
今ラウンドの修正(src で land)
エラー表示の不統一と Combobox の a11y を直した:
- #153:
Inputだけが持ってたaria-invalid:赤枠を Select/Textarea/PasswordInput にも。特に PasswordInput は className が wrapper に当たって input に届かず aria-invalid で赤枠が出ない実バグだった→ input に変種+inputClassNameprop。ブラウザ実証: aria-invalid 枠がrgb(252,176,176)(destructive)に。 - #155:
Comboboxが aria-invalid/describedby を受け取れず(HTMLAttributes 非継承)→ トリガーに forward。必須 Combobox を invalid にできるように。 - #156 Textarea の
w-[280px]固定(固定寸法系統)は style-hints ロック=.pen 案件→ Codex 指示書化。
headline の Form system(#152)は beta ゲート(FormField context を作る大物)。
学び — "accessible な部品" と "form system" は別物
持ってる: 個々に a11y な input(Input/Checkbox/Switch/RadioGroup)+ tone/error 視覚
無い: それらを協調させる form system(id/aria 配線・error state・validation・focus)
良い部品は揃ってる。足りないのは "つなぐ層"。 #28 の「選択を持つコレクション」、#27 の「scheduler view 層」と同じ——primitive は強い、欠けてるのは "上位の協調 primitive"。Form は名前が behavior を約束してるぶん、ギャップが一番くっきり出た。
次回予告(やってみた #30)
- エラー画面 / 通知トースト周り / ダッシュボード設定 ほか。
試す
まだ alpha。部品は a11y、次は "つなぐ form system"。
<!-- 公開前: 相互URL差込/スクショ確定/EN(dev.to)ミラー -->
使用した @gunjo/ui コンポーネント
この画面のソースが直接 import している部品です。
cold AI が組み上げた実コード
ファイル名をクリックでソースを展開できます。