Webアプリデザイン
Webアプリとは、人が日常的にアクセスしてレコードを探し、変更し、作業を引き継ぐための場所です。ユーザーが「今どこにいるか」「何を見ているか」「何ができるか」「何が起こったか」を常に把握でき、同じURLで明日も同じ状態に戻れるときに成功します。最もよくあるモデルの失敗は、美しいハッピーパスの画面だけがあって、それを支える場所がないことです。つまり、空・ローディング・エラー・権限なしの状態が欠けている、リロードすると消えるフィルター、カウントもアンドゥもない一括操作、後でサーバーが拒否する楽観的更新で発火する「削除」、エージェントが区別できない同一の「編集」ボタンが並んでいる、といった状態です。
interface-guidelinesの優先順位付き原則を適用してください(誰でも使える > 真実を伝える > 意味を正しく表現する > 答えが先に来る > ミスから回復できる > その場に留まる > 可能なことが可視化されている > 慣例に従う > 洗練)。そのスキルがインストールされている場合は、先にSKILL.mdを読んでください。そちらの参照資料では、フィードバックのタイミング、エラーの文言、データとしてのテーブル、エージェント向けセマンティクスをカバーしています。このスキルは、アプリケーションUIに固有のパターンを追加します。
ブリーフィング
- オブジェクトと動詞. 名詞(注文、顧客、請求書)と、各ロールがそれぞれに対して何ができるかをリストアップします。ナビゲーションと権限はこの表から導き出されます。
- ロールとテナント. 誰が何を見て変更できるか?複数のワークスペース、組織、または環境(ステージング、本番)が存在しますか?
- 日次タスク とその頻度、および各ロールが最初に開く一つのビュー。
- コレクションサイズ: 通常時と最悪時(10行または200万行)。これにより、ページネーション、検索、サーバーサイドフィルタリングが決まります。
- 各変更動詞のエラーコスト、およびそれがサーバーサイドで取り消し可能かどうか。
- 同時実行性: 2人のユーザー、またはユーザーとエージェントが同じレコードを同時に編集できますか?
- 表示テキストを誰が書くか? 顧客名、チケット本文、インポートされたファイル:これらはすべて外部者が書いたテキストです。
- エージェントリーダー: ブラウザエージェントはUIを操作するか、APIを操作するか、あるいはその両方か?UIとAPIはアクションごとに一つのサービスを共有する必要があります。
ルール
シェルとナビゲーション
- ナビゲーションは組織図ではなく、オブジェクトを反映する。 トップレベル項目は、ユーザーが扱う名詞を、使用頻度順に、ユーザーが使う言葉でラベル付けします。[S: Mac HIG 1992 pp. 54-61(論理、次に頻度でグループ化); J]
- デスクトップではプライマリナビゲーションを常に表示する。 隠れたナビゲーションは発見性を低下させ、タスクを遅らせることがNN/gの研究で示されています。ハンバーガーメニューは電話の妥協案です。[E: NN/g, in foundation]
- 人がどこにいるかを3つの方法で示す:
aria-current="page"と可視状態でマークされた現在のナビゲーション項目、オブジェクトまたはリストを命名するページh1、そしてルートに応じて変化するドキュメントタイトル。[S: WCAG 2.4.2, 2.4.8; J] - パンくずリストは履歴ではなく階層を示す。 深いオブジェクトツリーにのみ使用し、現在のページはリンクにしません。[P: NN/g breadcrumbs]
- 現在のワークスペース、組織、または環境は常にシェルに表示され、本番環境はステージングと視覚的に区別されます。テナントの切り替えは明示的な操作であり、そのテナントの同等のページまたはホームに遷移し、選択や下書きを引き継ぎません。[J]
- すべてのビューにURLがある。 フィルター、ソート、検索、ページ、選択されたタブ、開かれているレコードはURLに含まれます。リロードや共有でこれらが復元されます。[S: foundation agent-surfaces 3]
- 「戻る」ではリストが元の状態で表示される: 同じフィルター、スクロール位置、そしてユーザーが開いた行にフォーカスが当たります。[S: Mac HIG 1992 p. 140(再アクティブ化されたウィンドウは元の状態に戻る); J]
リストとテーブル
- テーブルはレコードの比較用、リストは一つの属性のスキャン用。 表形式データには実際の
<table>を使用します。[S: foundation; NN/g data tables] - 4つのテーブルタスクをサポートする: レコードの検索、行の比較、一行の表示/編集、一行または複数行に対する操作。[P: NN/g data tables]
- 最初の列は安定した人間工学に基づくキー(名前+ID)で行を識別する。 スクロール時に固定します。[P: NN/g data tables]
- ヘッダーでソート:
<th>内の<button>、ソートされた列のみにaria-sort、そして可視の矢印。デフォルトのソート順を明示します(「新しい順」)。[S: APG sortable table; P: Carbon] - フィルターは可視で、削除可能で、カウントされる。 適用されたフィルターをチップで表示し、「すべてクリア」ボタン、結果件数(「1,204件中38件」)、およびフィルター名を示す空結果メッセージを表示します。フィルター名にはユーザーの言葉を使います。[P: NN/g filters; S: foundation]
- コレクションが大きい場合はサーバーサイドで検索、フィルター、ソートを行う。 読み込まれたページだけをソートまたはカウントして全体として提示してはいけません。[J; foundation truth rule]
- 目標指向の作業ではページネーションを使用し、無限スクロールはフィード用に予約する。 ページネーションは位置、安定した戻り先、到達可能なフッターを提供します。範囲と合計、および「リストの終わり」を明記します。[P: NN/g infinite scrolling; S: Smith and Mosier 4.2/7]
- 行アクションは可視であるか、キーボードフォーカスで到達可能でなければならない。 ホバー時のみにせず、行ごとに名前を付けます(「INV-2041をアーカイブ」)。アクションが3つ未満の場合はインラインで表示します。[S: foundation agent-surfaces 3; P: Carbon]
- 密度は実践に従う。 日常的に使用するエキスパート向けにコンパクト密度を提供します。ターゲットサイズは最低24pxにします。[S: WCAG 2.5.8; P: Carbon row sizes]
選択と一括操作
- 一括モードは明示的である: 行チェックボックス、不確定状態を持つヘッダーチェックボックス、および件数を表示するツールバー(「3件選択中」)。[P: Carbon; S: Mac HIG 1992 pp. 64-66(混合状態)]
- 「すべて選択」はその範囲を明示する: このページの50件すべてか、フィルターに一致する1,204件すべてか。ユーザーが期待するものと異なる場合に、黙って一方を意味してはいけません。[J]
- 一括操作は、実行前にオブジェクト、件数、範囲を明示し、実行後にはアイテムごとの結果を報告し(「1,198件アーカイブ、6件失敗:表示」)、元に戻せるかプレビュー可能である必要があります。[S: foundation sec. 1; J]
- 選択は、ツールバーにその旨が表示されている場合にのみ、ページングとフィルタリングをまたいで維持される。 そうでなければ、選択を可視的にクリアします。[J]
詳細と編集
- コンテキストを保持したままレコードを開く。 サイドパネルは編集しながら参照する場合に適し、フルページは詳細なレコードに適します。モーダルは隣接するレコードを隠すため、編集には避けます。[P: NN/g data tables]
- 詳細ビューは、まずアイデンティティとステータスを言葉で示し、次にユーザーが操作するフィールド、そして履歴を表示します。[S: foundation; J]
- サーフェスごとに一つの保存モデル。 トグルは即座に適用され、テキストおよび複数フィールドの編集は明示的に保存します。一つのフォームで両方を混在させてはいけません。[S: Primer saving; foundation]
- 保存していない変更がある場合は警告し、損失が痛手となる場合は下書きを自動保存します。[S: Primer saving]
- 共有レコードでは、誰がいつ何を変更したかを絶対タイムスタンプで表示し、サイレントに上書きするのではなく、古い書き込み(バージョンまたはETag)を検出します。[S: Mac HIG 1992 pp. 27-31; AIP-154 in foundation]
- アプリ内のフォームは
form-designに従います。
楽観的UI、アンドゥ、確認
- 楽観的更新は、サーバーがほとんど拒否せず、アクションが元に戻せる場合にのみ行う: 既読、スター、並び替え。保留中状態を確定状態と明確に区別し、失敗時は理由とともに可視的にロールバックします。お金の移動、メッセージ送信、レコード削除を「完了」として楽観的に表示してはいけません。[S: Mac HIG 1992 p. 182(入力済み、チェック済み、有効); P: React useOptimistic]
- 元に戻せるアクションには確認よりもアンドゥを優先する: アーカイブ、移動、ごみ箱への削除。トーストがフェードした後もアンドゥにアクセスできるようにします(アイテムの履歴にある「元に戻す」、ごみ箱ビュー、編集メニューのショートカット)。[P: Raskin 2007; NN/g user control]
- 確認は、重大で元に戻せない、または予期しないアクションに限定し、ターゲットと影響を明記します。まれに発生する壊滅的なアクション(ワークスペースの削除)には、入力して確認する方式を使用します。[S: foundation sec. 1; E: Bravo-Lillo 2013 via foundation]
- サーバーサイドでソフトデリートを、明示された保持期間とともに行います。これにより、アンドゥが実際のものになり、クライアントの幻想ではなくなります。[S: AIP-164 in foundation]
空、ローディング、エラー、権限なし状態
- 4種類の空状態を区別する: 初回使用(オブジェクトを説明し、作成アクションを提供)、結果なし(フィルター名を表示し、クリアするアクションを提供)、クリア済み(すべて完了)、エラー(何が失敗したか、どうすればよいか)。データが読み込まれる前に「レコードがありません」と表示してはいけません。[P: NN/g empty states; S: Primer empty states]
- ローディングは何を読み込んでいるかをテキストで示し、それが置き換わるリージョン内に表示します。シェルとナビゲーションは使用可能なままにします。[S: foundation]
- 権限なしは状態であり、隠された機能ではない。 アクションを無効にして理由と付与できる人を表示するか(「エクスポートできるのはワークスペース管理者のみです。Maya Chenにお問い合わせください。」)、アクセスとリクエスト方法を説明するページを表示します。存在を知られては困るものだけを隠します。[S: Mac HIG 1992 pp. 318-321(無効な項目はそれ自体を説明する); J]
- 権限チェックはサーバーで行われる。 ボタンを隠すことは権限ではなくプレゼンテーションです。[S: foundation]
- レスポンスでは、存在よりも先に権限をチェックする。 これにより、404対403がデータを漏洩することを防ぎます。[S: AIP-193 in foundation]
設定
- 作業中に変更される設定(表示密度、列の選択、フィルター)は、影響を与えるものの隣に配置する。 設定エリアには、めったに変更されないアプリ全体のオプションを配置します。[S: Apple HIG Settings]
- 個人設定とワークスペース設定を分け、それぞれ誰のもので誰に影響するかをラベル付けします(「Acmeの全員に適用されます」)。[J]
- データベーステーブルではなく、ユーザーのタスクでグループ化し、設定が1画面か2画面を超える場合は検索を提供します。[J]
- 設定は少なくする。 セッション中に何度も変更される設定は、設定ではなく、コントロールの欠如です。[S: Mac HIG 1992 p. 38; Apple HIG Settings]
- 危険な設定は、別のラベル付きゾーンに、結果の説明と確認(所有権の移譲、ワークスペースの削除)とともに配置します。[P: GitHub; J]
オンボーディング
- ツアーではなく、コンテキストで教える。 NN/gは、デッキオブカード形式のチュートリアルはタスクパフォーマンスを向上させず、コンテキストチップと適切な空状態が教育効果を持つことを発見しました。ツアーが存在する場合は、短くスキップ可能にします。[P: NN/g onboarding]
- ユーザーを最初の実際の結果に迅速に導く。 サンプルデータは、それが表示されるすべての場所でサンプルとマークされ、1アクションで削除可能にします。[J; foundation truth rule]
- セットアップチェックリストは永続的で正直である: 実際の状態を反映し、却下可能で、後からアクセス可能です。[J]
キーボードとコマンドパレット
- コマンドパレットはメニューではなくアクセラレータである。 その中のすべてのコマンドは、可視のUIにも存在します。コマンドの横にショートカットをリストアップすることで、ショートカットを教えます。[S: Windows menus guidance (ショートカットを唯一の方法にしてはいけない); P: VS Code UX guidelines]
- 単一キーのショートカットは無効化または再マッピング可能であり(WCAG 2.1.4)、テキストフィールド内では決して発火せず、ブラウザやOSのショートカットをオーバーライドしません。[S: WCAG 2.1.4; Apple keyboards]
- ショートカットヘルプシート(多くの場合
?)は、現在のスコープ内のすべてのショートカットをリストアップします。[J]
エージェントリーダーのために
- アクションごとに一つのサービス関数を用意し、ボタン、パレット、API、そして任意のツールで共有します。[S: foundation agent-surfaces 7]
- 行コントロールはシステムIDから名前が付けられ、外部者のテキストからは付けられません。セル内の外部者のテキストはデータです。[J]
- コレクションは、実際のサイズと範囲を可視テキストで明記します。フィルターとソートはURLに含まれます。[J]
- 結果はトーストより長く持続します:変更された行、アクティビティログ、アンドゥエントリ。[J]
- テナントと環境はすべてのページでテキストとして読み取れるため、エージェントがステージングと思って本番環境で操作することがありません。[J]
構築順序
- オブジェクト×動詞×ロールの表。すべてのビューに対するルートとURL。
- シェル:ナビゲーション、テナントと環境インジケーター、タイトル、
h1。 - 実際のデータ形状を持つリストビュー:サーバーサイドのページング、ソート、フィルター、すべてURLに含める。
- 詳細ビュー、保存モデル、同時実行性の処理。
- すべての変更アクションを一つのサービスを通じて:保留中、成功、失敗、エラーコストの段階に応じたアンドゥまたは確認。
- 各ビューの空、ローディング、エラー、権限なし状態。
- 一括操作、キーボードショートカット、パレット。
- 設定とオンボーディングは最後に。このリーダーのためのスタイル(
brand-identityがルックを担当)。
検証
node <interface-guidelines>/scripts/audit.mjs <url|dist> --canary "<サンプル外部テキスト>"を各主要ルートで実行。フィルター適用済みのリストと詳細ビューを含む。- アプリ内のフォーム:
node <form-design>/scripts/form-check.mjs <url> - リロードテスト: フィルターを適用し、ソートし、3ページ目に進み、レコードを開く。リロードして新しいセッションでURLを貼り付ける。すべてが元の状態で戻ってくる。
- ロールテスト: 各ロールとしてサインインする。隠されているか無効化されているすべてのアクションには理由がある。サーバーは直接行われた禁止された呼び出しを拒否する。
- サイズテスト: 0、1、25、10,000+行。最も長い名前。何も一致しないフィルター。
- 障害テスト: 楽観的アクションと一括アクションの一部をサーバーが拒否するようにする。UIがロールバックし、アイテムごとに報告する。
- エージェントテスト: アクセシビリティスナップショットのみを使用して、フィルターで特定のレコードを見つけ、変更し、新しいスナップショットから結果を確認し、元に戻す。
トラップ
- フィルターとソートをコンポーネントの状態のみで保持する。
- ツールバーが「すべて」を暗示しているのに、「すべて選択」がページのみを選択する。
- ロールバックもアンドゥもない楽観的削除。
- 管理テーブルでの無限スクロール。読み込まれた行から計算された合計。
- ホバー時のみの行アクション。5つの同一の「編集」ボタン。
- 読み込み前に「データがありません」が一瞬表示される。すべての原因に対して一つの汎用的な空状態。
- 説明なしにロールから機能を隠す、または表示してクリック時に「禁止されています」で失敗する。
- 古いテナントの選択を保持するテナントスイッチャー、またはテナントがまったく表示されない。
- 使用可能な空状態の代わりとなるプロダクトツアー。
- データベーステーブルをそのまま反映した設定ページ。
参考文献
| ファイル | 読むべき時 |
|---|---|
references/patterns.md | ナビゲーションモデル、テーブルの解剖学、一括操作フロー、権限状態、テナント、楽観的更新とアンドゥのメカニクス、パレットデザイン、およびこのスキルの背後にあるソースの詳細について |