デザイントークンとコンポーネント/フォームルールを使ったプロンプトで、AI生成の React 画面がスペーシング、タイポ、フォーム挙動まで一致するようにする方法を解説します。

UI の不一致は、クリックして回ると違和感につながる小さな差異として現れます。あるページは余裕のあるパディングで、別のページは窮屈に感じる。見出しがサイズを行き来し、ボタンの形や色が変わり、同じ入力が画面ごとに挙動を変える。
多くの場合、その原因は基本的な要素が揺らいでいることです:
別々のプロンプトから画面を生成するとこれはよく起きます。各プロンプトは事実上のゼロからの開始なので、モデルは不足する決定を推測で埋めます。「モダンなスタイルを使って」と言っても、8px と 12px のギャップ、14px と 16px の本文、いつエラーを表示するか、プライマリボタンの見た目など、何百もの小さな判断が残ります。
2〜3ページを手作業で整えることはできますが、スケールしません。ワンオフの CSS 修正を追いかけ、ファイル間でスタイルをコピーし、フォームを何度も直すことになります。ルールはプロジェクトの外にあって頭の中にしかありません。
今日ログイン画面を生成して、明日プロフィール画面を生成したと想像してください。1つは submit のみでエラーを出し、もう1つは blur でエラーを出すと、ユーザーは気づきます。画面間でプライマリボタンの高さが変わると、アプリは継ぎ接ぎに見えます。
すべての画面が同じ共有システムに従うと、一貫性がデフォルトになります:デザイントークン(スペーシング、タイポ、カラー)と、小さなコンポーネントおよびフォームのルールセットです。
デザイントークンは UI 全体で再利用する単純な名前付きの値です。毎回「快適なパディング」と頼む代わりに、space-4 のようなトークンを使います。「やや丸める」と言う代わりに radius-md を使います。名前は安定して、後で対応先を変えても名前は変わりません。
トークンは、すべての画面で共有したい決定の集合です。味付けや推測を取り除くことで、生成や新しいページの作成時に生じるドリフトを防ぎます。
典型的なトークンはスペーシング、タイポグラフィ、色、形、そして少量のエレベーションをカバーします。実利としては:ヘッダーは常に同じサイズ、カードは常に同じパディング、プライマリボタンは同じ色と角丸を保つ、ということです。
プロダクト全体の雰囲気に影響するものをトークン化してください:スペーシングスケール、フォントサイズと行の高さ、コアカラー(テキスト、背景、プライマリ、デンジャー、ボーダー)、そして少数のボーダー半径。
コピーの長さ、どのアイコンを使うか、セクションにカードが2つ必要か3つ必要かなど、コンテンツに依存する選択は柔軟にしておきます。
画面を生成する際(Koder.ai のようなツールを使う場合も含む)、事前に小さなトークンセットを与えると推測の余地が減り、出力が明らかに一貫します。
トークンセットは、許可する値の短いメニューにすぎません。小さいほどランダムな選択の余地が減るが、画面を台無しにする基本はカバーしている必要があります。
まずスペーシングから始めます。1つのスケールを選び、パディング、ギャップ、レイアウトにそこを使います。4、8、12、16、24、32 のようなセットは多くの UI をカバーします。デザインで 10px や 18px が要求されたら、新しい値を導入する代わりに近いトークンに丸めてください。
次にタイポグラフィのデフォルトを定義して、見出しや本文のぶれを止めます。大規模なタイプシステムは必要ありませんが、明確で再現可能な段階が必要です。
無駄に膨らまないコンパクトなセットの例:
アクセシビリティもシステムに含めます。フォーカスアウトラインのスタイル(色、太さ、オフセット)を定義してキーボードユーザーに一貫したフォーカス状態を提供します。モバイル向けの最小タップターゲット(44x44 など)も設定します。テキスト色は信頼できる少数に限定してコントラストを予測可能に保ちます。
ボタンが狭く見える原因は、ある画面でパディングが 10 を使い、別の画面で 12 を使ったことにあることが多いです。トークンを使えば「ボタンは paddingY=8, paddingX=16, radius=12, フォーカストークン, 最小高さ44 を使う」と決められます。数値を固定すれば、ジェネレーターは即興をやめます。
トークンは数値を与えます。コンポーネントルールは習慣を定めます。
コアコンポーネントの小さなセットを選び、画面の構築ブロックはそれだけにします。退屈で再利用可能なものにしてください:Button、Input、Select、Checkbox、Card。TextArea や Modal は追加できますが、ラベル、間隔、状態は同じシステムに従わせます。
次にバリアントを制限し、使用を定義します。例えば:Button は primary、secondary、danger。Primary は画面上の主要アクション(通常は1つ)に使います。Secondary はキャンセルや優先度の低いアクションに。Danger は削除のような破壊的アクションのみにします。正当化できないバリアントはデフォルトで secondary にします。
スペーシングルールは微妙なズレを防ぎます。コンポーネント内のデフォルトを定義してください:ボタンのパディング、入力の高さ、ラベルとフィールドの間隔、積み重なったフィールド間の標準ギャップ。レイアウトルールも少し追加します:カードは内部パディングが固定、ヘッダ/ボディの間隔が一貫、モーダルは幅のステップとフッターの整列が同じ。
最後に状態を非交渉にします。ここが UI がランダムに見え始める箇所です:
「Create project」のようなフォーム中心の画面を生成するとき、これらのルールが混在するボタンサイズやラベル位置のズレ、画面にしかない“特別な”カードの出現を防ぎます。
視覚が安定していても、多くの「違和感」の原因はフォーム挙動にあります。各画面でラベル、エラー、フォーカスの扱いが異なると、ユーザーは違和感を覚えます。
フォームパターンを一つ選び、どこでもそれを使ってください:ラベル、オプション/必須マーカー、ヘルパーテキスト、その後にエラーテキスト。文言も揃えてください(例えばラベルは文の先頭のみ大文字、ヘルパーは短く、エラーメッセージは動詞で始める等)。
ドリフトを防ぐルールの例:
サイズとレイアウトを固定して、画面ごとに「呼吸」が違わないようにします。入力の高さ1つ、ボタンの高さ1つ、デフォルトのフィールド幅1つを定義してください。デスクトップではフィールドを一貫したグリッドに揃えてラベルは上に、モバイルではフィールドを全幅にして二列フォームは本当に必要な場合だけにします。
簡単な例:「Create project」画面に Name、Region、Description があるとします。Region が select であっても他のフィールドと同じ扱い:同じ高さ、同じラベル位置、同じエラー行。ユーザーが Name を空で送信すると Name にフォーカスが移り、その下にエラーが出てレイアウトは安定したままです。
Koder.ai で画面を生成するなら、これらのフォームルールをプロンプトに一度入れて機能全体で再利用すれば、新しいフォームも繰り返し修正する必要がなくなります。
プロンプトを小さな UI 契約のように扱ってください。短く、具体的で再利用可能にすれば、各画面が同じスペーシング、タイポ、コンポーネント、挙動にスナップします。
実用的なパターンは、リクエストの先頭にコンパクトな UI 仕様を貼り、その下に画面を平易に記述する方法です。
UI SPEC (apply to every screen)
Tokens:
- Spacing: 4, 8, 12, 16, 24, 32
- Radius: 8
- Typography: H1 24/32, H2 18/26, Body 14/20
- Colors: text, muted, bg, primary, danger (no custom hex)
Components (must use): PageShell, Section, Card, Button, Input, Select, TextArea, FormRow, HelperText, Toast
Layout rules:
- Page padding: 24 desktop, 16 mobile
- Section spacing: 24
- Card padding: 16
- Grid: 12 cols desktop, 4 cols mobile, gap 16
Do:
- Reuse components and tokens only
- Keep labels above inputs, helper text below
Do not:
- Invent new spacing values, font sizes, or one-off CSS
- Mix different button heights or input styles
If a new component is needed:
- Extend an existing component pattern and document it in the output
- Do not create new visual styles outside tokens
仕様の後に、ドリフトを早期に検出するいくつかの受け入れチェックを加えてください:
チャットベースのジェネレーターを使うなら、この仕様をリクエスト間で安定させてください。毎回変えると意味がありません。
何も生成する前に UI 契約を書きます:小さなトークンセット(スペーシング、タイプ、カラー、半径、シャドウ)と短いコンポーネント目録(Button, Input, Select, Card, Modal, Table, Toast)。トークンやコンポーネントが欠けていると、モデルはそれを発明して UI がドリフトします。
次に、ルールを検証するリファレンス画面を一つ作ります。フォーム中心のページは良いストレステストです。ヘッダ、ヘルパー、検証エラー、プライマリ/セカンダリボタン、成功トーストを含むためです。その画面を基準として扱います。
そこから、新しい画面は既に定義したもので構成して作っていきます。「新しいスタイリングを」と頼むのではなく、同じ Card、同じスペーシングスケール、同じタイポグラフィ段階、同じフィールドパターンを使うように依頼します。
シンプルなワークフロー:
「Search users」画面のスペーシングがリファレンスよりタイトになっていたら、個別にマージしてマージ先を直すのではなく、スペーシングトークンや Card のパディングルールを1回更新して再生成してください。
Koder.ai を使っている場合、スナップショットとロールバックが役立ちます:ベースラインをロックし、安全に実験して、変更がドリフトを招いたらすぐ戻せます。
トークンとルールを「提案」扱いにするのが一番速く一貫性を失う方法です。小さな例外が積み重なって新しい画面ごとに倍増します。
よくある落とし穴の一つは、プロジェクト途中でスペーシングスケールを変えることです。初期の画面は 8, 16, 24 を使っていたのに、新しい画面が「こっちの方が良く見える」と 10 や 18 を導入すると、ドリフトが許されることになりますし、古い画面は更新されません。
別のドリフト源は、ジェネレーターに新しいコンポーネントスタイルを発明させることです。「ボタンのバリアントだけを許可する」と明記しないと、新しい画面で別の角丸や入力パディングが作られてしまいます。
状態(Loading、Empty、Error)も頻繁に見落とされます。後付けすると、通常は急いで作られたパターンが他と合いません。
また「soft shadows でモダンに」といった曖昧な指定は避け、代わりに「エラーはフィールド下に表示」「無効ボタンでもフォーカススタイルは残す」「Enter は最後のフィールドでのみ送信」といった具体的で再現可能な振る舞いルールを与えてください。
プロンプトに貼る軽量のガードレールを作るなら短くします:
生成された画面をマージする前に、2分で目を通してください。
スペーシングから始めます。13px のようなランダムな値や「合わせるために加えた」一時的なマージンを探してください。トークンを使っているなら、すべてのギャップが承認されたセットから来ているはずです(ガター、カードパディング、フォームフィールド間の間隔を含む)。
次にタイポグラフィをタイプスケールと照らし合わせます。見出しは予測可能に段階を踏んでいるか。類似のセクション間で本文のサイズが切り替わっていないか。行の高さも重要です、特に設定ページのような密な画面では。
ボタンをチェックします。バリアントとサイズはルール通りか:主要アクションには primary、重要度の低いアクションには secondary、削除には danger。ボタン高さ、アイコンの配置、ラベルスタイルが一致しているか。
フォームは構造の一貫性が重要です。ラベルの位置、必須表示のルール、ヘルパーとエラーの競合がないか、エラーが一貫した場所に出るか。
短いチェックリスト:
最後にモバイルでの簡単な確認を行います。幅を狭めてレイアウトが新しいフォントサイズやスペーシングを勝手に作り出さずに順応するかを確認してください。
3つの画面(Profile、Preferences、Confirm)と後で Settings ページがあるシンプルなオンボーディングフローを想像してください。各画面は別々のランで生成されても、同じデザイナーが作ったように見えることを望んでいます。
何も生成する前に、小さなトークンセットといくつかのコンポーネントルールを提供します:
TOKENS
- spacing: xs=4, sm=8, md=12, lg=16, xl=24
- radius: sm=8, md=12
- type: body=14/20, title=20/28, label=12/16
- layout: pageMax=960, sectionGap=24, fieldGap=12
COMPONENT RULES
- Page: max width=pageMax, padding=xl, sectionGap between blocks
- Card: padding=lg, radius=md
- Field: label above, helper below, fieldGap between fields
- Button row: primary on right, gap=sm
- Errors: shown under field, same copy style, no alerts
これで “Profile” と “Preferences” を別々に生成しても、両方とも Page、Card、Field、Button row を定義どおりに使うため、同じマージン、ラベル間隔、ボタン配置になります。Confirm ステップは読み取り専用テキストが多くても収まります。
フォームの挙動はドリフトが忍び込みやすい場所なので、一度定義して再利用してください:有効になるまで送信ボタンを無効にする、エラーは blur または submit 後のみ表示、Enter は最後のステップでのみ送信、Back ボタンは既に入力した値を消さない。
新しい UI 部品が必要になったら、モデルにその場で即興させないでください。1つルールを追加し、再生成して再利用を意識します:
トークンとルールを実際に使う再利用可能な仕様にします。貼るには長すぎると守られないので、実用的な仕様は短くまとめてください。
一般的に含めるべきは:トークン表(spacing、type、radii、colors)、短いコンポーネントルールセット(buttons、inputs、cards、headings)、フォーム挙動ルール(検証タイミング、エラー、disabled/loading)、レイアウトのデフォルト(ページパディング、最大幅、セクション間隔)、そして短い「やってはいけないこと」リスト(ランダムなマージン、アドホックなフォントサイズ)です。
そして1つの習慣を作ります:個別のピクセルを先に変えるのではなく、まず仕様を更新すること。
Koder.ai (koder.ai) を使っているなら、planning mode は仕様を再確認するのに良い場所です。代替案を試したいときは snapshots と rollback によって安定したベースラインを失わずに実験できます。
各画面のリクエストがその都度「ゼロからの開始」になるためです。共有システムを与えないと、ジェネレーターは不足している細部を推測して埋めます—スペーシング、フォントサイズ、ボタンのパディング、影、フォームの振る舞いなど。小さな差が積み重なって全体の一貫性が失われます。
デザイントークンは、スペーシング、フォントサイズ、色、角丸などの名前付きで再利用可能な値です。
「快適なパディング」の代わりに space-md のようなトークンを使います。名前が安定していれば、すべての画面で同じ決定が再利用されるため、UIのドリフトが止まります。
目に見えるドリフトを引き起こす要素だけをカバーする小さめのセットから始めてください:
新しい値が必要な場合は、10px や 18px をそのまま導入するのではなく、最も近いトークンに丸めてください。
各リクエストの先頭に小さなUI仕様ブロックを置き、それを契約のように扱ってください:
その下に画面の説明を置きます。重要なのは、この仕様を画面ごとに変えずに維持することです。
トークンは数値を決めます。コンポーネントルールは習慣を決めます。以下のようなルールが有効です:
正当な理由がないバリアントは標準にフォールバックする、というルールが有効です。
一つのパターンを選び、どこでもそれを崩さないことです:
これで「ある画面は blur で検証、別の画面は送信時のみ」といった不一致を避けられます。
次のような状態ルールを決めておくと画面がバラバラに見えません:
状態を指定しないと、画面ごとに勝手なパターンが生まれます。
即興でスタイルを作らせないことです。新しいコンポーネントは、既存のパターンの拡張としてドキュメント化して追加してください:
トークンで説明できないなら、それはたいていカスタムすぎてドリフトの原因になります。
システムをストレステストする“リファレンス”画面(フォーム中心のページが良い)を一つ作っておき、それを基準にして同じ仕様を再利用します。
Koder.ai を使う場合は、planning mode で仕様を再確認し、snapshots と rollback を使って安定したベースラインを保ちながら実験できます。
マージ前の短いスキャンチェックリスト:
ズレがあれば個別のマージ修正をせず、仕様/トークンを更新して再生成するのが推奨です。