axiom-ux-flow-audit について
iOS の UX 監査スキルで、ユーザーが操作を完了し、画面から戻り、アプリの状態を把握できるか確認します。ナビゲーション、空・エラー状態、アクセシビリティ、プラットフォーム適応を調べ、重大な欠陥と状況依存の確認を分けます。
主な機能
- 01行き止まり画面と閉じられないモーダルの検出
- 02主要アクションの隠れやラベル不一致の確認
- 03ディープリンクと空状態の監査
- 04ローディングとエラー表示の確認
- 05アクセシビリティ操作フローの確認
- 06プラットフォーム適応とオンボーディングの確認
活用シーン
- 01iOS リリース前のナビゲーション監査
- 02戻る手段や次の操作がない画面の発見
- 03ディープリンクと検索結果なしの体験確認
- 04非同期処理の表示と VoiceOver 対応の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-ux-flow-auditインストール後、Claude Code で/axiom-ux-flow-auditを入力して読み込まれたか確認します。
詳細
UX フロー監査
UX の問題は単なる仕上げの問題ではありません。サポートへの問い合わせ、低評価、ユーザー離れにつながる欠陥です。
Axiom のコードレベルの監査ではパターンを確認します。このスキルでは、ユーザーが実際に体験することを確認します。タスクを完了できますか?元の画面に戻れますか?何が起きているか分かりますか?
iOS UX の 6 原則(検出の基準)
これらの原則は、すべての検出カテゴリの基準となります。原則に違反すると、ユーザーは操作に行き詰まり、混乱したり、いら立ったりします。
1. 表示内容と実際の動作を一致させる
ボタンやタイトルの説明は、ユーザーが実際に得る結果と一致している必要があります。「設定」ボタンでプロフィールページが開くと、信頼を損ないます。
2. 画面から抜け出せるようにする
すべてのモーダル(シート、fullScreenCover、アラート)には、終了する方法が必要です。閉じるボタンもスワイプで閉じる方法もないシートでは、ユーザーが画面から抜け出せません。
3. 主要なアクションを見つけやすくする
ユーザーが実行しようとしている主要な操作は、すぐに見えてタップできる必要があります。CTA を表示するのにスクロールやメニューの操作が必要だと、ユーザーは見つけられません。
4. 行き止まりを防ぐ
すべてのビューには、次に進む方法(次のステップ)か、完了状態(成功メッセージ、開始地点への復帰)が必要です。アクションもナビゲーションもないビューは行き止まりです。
5. 段階的に情報を開示する
最初の画面でユーザーを圧倒しないでください。まず必要な情報を表示し、詳細は必要に応じて提示します。最初のページに設定を 12 個も並べるオンボーディングフローでは、ユーザーが離れてしまいます。
6. 状況を常に伝える
非同期処理中に何が起きているか、ユーザーが分かるようにする必要があります。読み込み状態がないと「壊れているのかな?」と思わせます。エラー状態がないと「何が問題だったの?」と思わせます。空の状態がないと「この機能はないのかな?」と思わせます。
検出カテゴリ
中核となる欠陥 8 件(必ず確認してください。これらは意見の違いではなく、UX の不具合です):
- 行き止まりになるビュー(重大)
- 画面から抜け出せない状態(重大)
- CTA が見つけにくい(高)
- 表示内容と実際の動作の不一致(高)
- ディープリンクの行き止まり(高)
- 空の状態の欠落(高)
- 読み込み状態/エラー状態の欠落(高)
- アクセシビリティ上の行き止まり(高)
状況に応じた確認項目 3 件(製品の状況に応じて確認してください。これらには設計上の判断が伴います):
- オンボーディングの不足(中) — 製品のオンボーディング戦略を把握する必要があります
- データフローの不具合(中) — コードの正確性と重複するため、UX から見える場合にのみ含めてください
- プラットフォーム間の対応差(中) — 対象デバイスの戦略によって異なります
中核となる欠陥は、常に報告する価値があります。状況に応じた確認項目には製品の知識が必要です。問題があるように見える場合は指摘してください。ただし、意図的な決定である可能性も明記してください。
1. 行き止まりになるビュー(重大)
先に進むナビゲーションもアクションも完了状態もないビューです。
検出方法:
- SwiftUI:
NavigationLink、Button、.sheet、.fullScreenCover、.navigationDestination、または閉じるアクションがないビュー - UIKit:
IBAction、addTarget、画面遷移や表示の呼び出し、UIBarButtonItemがないビューコントローラー - ナビゲーション先になっているものの、先に進む方法も戻る方法もないビュー/VC を確認します
よくある原因:開発中のプレースホルダービューを、そのまま本番環境に出してしまうことです。
2. 画面から抜け出せない状態(重大)
閉じる方法がないシートや fullScreenCover です。
検出方法:
- SwiftUI:
@Environment(\.dismiss)や明示的な閉じるボタンがない.fullScreenCover。代わりの閉じる方法がない.interactiveDismissDisabled(true)を設定した.sheet。キャンセルアクションがないアラート/確認ダイアログ - UIKit:表示された VC に閉じるボタンがない状態で、
modalPresentationStyle = .fullScreenを設定したpresent(_:animated:)。代わりの閉じる方法がないisModalInPresentation = true
重大な理由:ユーザーは文字どおり、その画面から離れられません。唯一の脱出方法は、アプリを強制終了することです。
3. 埋もれたCTA(高)
主要なアクションが画面下部、メニュー内、またはナビゲーションの奥に隠れています。
検出方法:
- 主要なアクションボタンが長い
ScrollViewコンテンツの後に配置されている - 重要なアクションが
.toolbarのオーバーフローメニュー(.secondaryAction)からしか実行できない - CTA が展開可能な
DisclosureGroupセクション内にある - メインタブのルートビューに目立つアクションがない
埋もれたCTAに該当しないケース:意図的に画面下部へ配置している場合。たとえば、購入確認(「注文内容を確認してから確定する」)、規約への同意(「読んでから同意する」)、ユーザーがアクションを起こす前に目を通すべきコンテンツなどです。判断基準は、画面下部への配置がユーザーの役に立っている(先に状況を把握する必要がある)か、妨げになっている(アクションを見つけられない)かです。
4. 表示内容と約束の不一致(高)
ナビゲーションタイトル、ボタンラベル、またはタブ名がコンテンツと一致していません。
検出方法:
- ビューのコンテンツが明らかに Y の内容なのに、
.navigationTitle("X")となっている NavigationLink("Settings")がプロフィール/アカウントのビューに遷移する- タブラベルがタブのコンテンツと一致しない
- ボタンのテキストが示すアクションと、実際に実行されるアクションが異なる
5. ディープリンクの行き止まり(高)
URL は開くものの、空または壊れた状態にたどり着きます。
検出方法:
- データの存在を確認せずにビューへ遷移する
.onOpenURLハンドラー - 事前に読み込まれた状態があることを前提とするディープリンク先
- エンティティ ID を検証しないユニバーサルリンクの処理
- ディープリンク先のコンテンツを利用できない場合のフォールバックがない
関連項目:axiom-swiftui-nav ではディープリンクのアーキテクチャを扱います。このカテゴリでは UX の結果を確認します。
6. 空の状態がない(高)
リスト、グリッド、またはコンテンツビューにデータがないと、画面が空白になります。
検出方法:
- 空の状態を表示する
if items.isEmpty { ... }または.overlayがないListやForEach - 空かどうかを確認せずに表示される
@Queryの結果 - 「結果なし」のビューがない検索結果
- アイテム数がゼロになる可能性のあるフィルタービュー
7. 読み込み/エラー状態がない(高)
非同期処理のフィードバックがありません。
検出方法:
- SwiftUI:データを取得する
.task { }またはTask { }に読み込みインジケーターがない。エラーを表示する処理のないtry await(.alertもエラー状態変数もない)。状態 enum に.loadingまたは.errorケースがない - UIKit:
UIActivityIndicatorViewまたは進行状況 UI のないURLSession呼び出し。エラー時に UI を更新しない完了ハンドラー。失敗時のUIAlertControllerがない - 両方:タイムアウトや再試行 UI のないネットワーク呼び出し
- 両方:ユーザーにわかるフィードバックがなく、
#if DEBUG内でprint/ログを出力するだけのcatchブロック。ユーザーには処理が失敗したことが何も通知されない
ネットワーク処理/書き込み処理に注目する:100ms 未満で完了する高速なローカル読み込み(GRDB クエリ、UserDefaults、キャッシュ済みデータ)には、読み込みインジケーターを追加しないでください。こうした処理にスピナーを表示すると、画面がちらつきます。ネットワーク呼び出し、データベースへの書き込み、または実質的に失敗する可能性のある処理に注目してください。
体系的にスキャンする:あるファイルでサイレントエラーのパターン(例:ユーザーへのフィードバックがない catch { print(...) })を見つけたら、同じパターンがないか、類似するファイルをすべて確認してください。catch ブロックの問題が一つ見つかった場合、通常はコードベース全体に同様の慣習があることを示しています。
8. アクセシビリティ上の行き止まり(高)
ジェスチャーや視覚的な手がかりからしか実行できないアクションは、支援技術から認識できません。
検出方法:
- 同等の
.accessibilityActionがない.onLongPressGesture/.swipeActions/DragGesture .accessibilityLabelまたは.accessibilityHintのないカスタムコントロール- 色だけに頼るナビゲーション(例:「緑のボタンをタップ」)
- VoiceOver で利用できる代替手段のないプルして更新(
refreshable)(注:refreshableは自動的にアクセシブルです。カスタム実装を確認してください)
関連項目:axiom-accessibility-diag では WCAG 準拠全般を扱います。このカテゴリでは、支援技術から UX フローを利用できるかを重点的に確認します。
9. オンボーディングの不足(MEDIUM)
初回起動時のフローが不完全、または煩雑です。
検出項目:
@AppStorageで制御されるオンボーディングのチェックがない- スキップ/後で行うオプションのないオンボーディングフロー
- オンボーディング画面が5画面を超える
- アプリの価値を示す前にアカウント作成を求めるオンボーディング
10. データパスの破損(MEDIUM)
UX上の問題として現れる状態/バインディングの配線の問題です(ビューに古いデータが表示される、編集内容が保存されない、データが存在するのにビューが空に見える)。
検出項目:
@Bindingを受け取るビューが、プレビュー以外のコードで.constant()を使って初期化されている- ビューが必要とする
@Environmentの値が親から提供されていない - 注入すべき場所で
@Observableモデルがローカルに作成されている - 変更を上位へ伝えるべき場所で
@Stateが使われている
対象範囲に関する注記:この項目は、一般的な SwiftUI の正しさ(axiom-swiftui-debugging)と重複します。データパスの破損が、空白画面、古いコンテンツ、保存されない編集など、目に見える UX の問題を引き起こす場合に限り、ここに所見を含めてください。コードレビューの対象となるコンパイラレベルまたはクラッシュレベルの問題は除外してください。
11. プラットフォーム間の対応状況の不足(MEDIUM)
iPad でサイドバーがない、横向き表示が崩れる、Mac Catalyst の問題などです。
検出項目:
- iPad 向けの代替手段として
NavigationSplitViewを備えていないNavigationStack - アダプティブレイアウトのための
.horizontalSizeClassチェックがない - 横向き表示で崩れるビュー(固定の高さ、スクロールなし)
- iPad/Mac でのキーボードショートカット対応がない
監査プロセス
ステップ 1:エントリーポイントを把握する
ユーザーがアプリに入るすべての方法を見つけます:
@mainApp struct/SceneDelegate.onOpenURLハンドラー(ディープリンク)- ウィジェットの
Link遷移先 - 通知レスポンスハンドラー(
UNUserNotificationCenterDelegate) - Spotlight/Siri のインテントハンドラー
ステップ 2:ナビゲーションコンテナーを把握する
すべてのナビゲーション構造を見つけます:
NavigationStack/NavigationSplitView- タブ構造を持つ
TabView .sheet/.fullScreenCoverによる表示- カスタムのモーダル表示
ステップ 3:フローをたどる
各エントリーポイントから完了までの経路について:
- ユーザーは目的を達成できますか?
- ユーザーは元に戻れますか?
- 各ステップで何が起きているか、ユーザーに分かりますか?
ステップ 4:データの配線を確認する
@Binding変数は実際に親から渡されていますか?@Observableオブジェクトは環境経由で注入されていますか?@Queryの結果について、空の場合が処理されていますか?
ステップ 5:プラットフォームへの適応性を確認する
- iPad:サイドバー/分割ビューは機能しますか?
- 横向き:レイアウトは適応しますか?
- Mac Catalyst/Designed for iPad:キーボードショートカットはありますか?
ステップ 6:アクセシビリティのフローを確認する
- VoiceOver ユーザーはすべてのフローを完了できますか?
- ジェスチャーだけで行う操作に、アクセシビリティアクションが用意されていますか?
監査間の相関
所見が他の Axiom 監査と重複する場合は、相関を記載し、重要度を引き上げます:
| UX の所見 | 重複する監査 | 複合的な影響 | 重要度の引き上げ |
|---|---|---|---|
| 行き止まり+NavigationPath の欠落 | swiftui-nav-auditor | プログラムによる修正が不可能 | CRITICAL |
ジェスチャーのみの操作+.accessibilityAction がない | accessibility-auditor | VoiceOver ユーザーが行き止まりになる | CRITICAL |
| ローディング状態の欠落+未処理の非同期エラー | concurrency-auditor | クラッシュ+ユーザーへのフィードバックなし | CRITICAL |
| 空状態の表示欠落+結果のない @Query | swiftdata-auditor | データ移行後に空白画面になる | HIGH |
| ディープリンクの行き止まり+URL の検証なし | swiftui-nav-auditor | 外部リンクからの遷移が無言で失敗する | HIGH |
出力形式
拡張評価テーブル(CRITICAL および HIGH の所見向け)
| 所見 | 緊急度 | 影響範囲 | 修正工数 | ROI |
|---|---|---|---|---|
| 支払い後に行き止まりになる | リリース阻止要因 | すべてのユーザー | 30 min | Critical |
| 検索時の空状態の表示がない | 次回リリース | 検索するユーザー | 15 min | High |
緊急度:リリース阻止要因/次回リリース/バックログ
影響範囲:すべてのユーザー/特定のフロー/エッジケース
修正工数:修正にかかる時間の見積もり
ROI:緊急度 × 影響範囲 ÷ 工数から算出
ナビゲーション到達性スコア
監査の最後に、次を出力します。
## Navigation Reachability
- Total screens found: [N] (views with navigation presentation)
- Deep-linkable screens: [N] (.onOpenURL can reach them)
- Widget-reachable screens: [N] (widget Link destinations)
- Notification-reachable screens: [N] (notification handlers)
- Coverage: [N]% of screens are externally reachable
修正工数の現実的な確認
UX フローの不具合の多くは、すぐに修正できます。「大きな変更が必要」と言われたら、この表を確認してください。
| 不具合 | 一般的な修正 | 時間 |
|---|---|---|
| 閉じる手段がない(閉じるボタンがない) | ツールバーにキャンセルボタンを追加して、dismiss() を呼び出す | 10-15 分 |
| 空の状態が表示されない | if items.isEmpty { ContentUnavailableView(...) } を追加する | 15-20 分 |
| CTA が見つけにくい(配置の問題) | ボタンを .secondaryAction から .primaryAction に移動する | 20-30 分 |
| 行き止まりの画面(次に進む方法がない) | NavigationLink またはアクションボタンを追加する | 15-30 分 |
| 読み込み状態が表示されない | @State var isLoading を追加して、ProgressView をオーバーレイ表示する | 15-20 分 |
| エラーが通知されない(ユーザーへのフィードバックがない) | catch ブロックで .alert を表示する | 10-15 分 |
| ジェスチャーだけで実行するアクション | .accessibilityAction と、代わりに使える表示ボタンを追加する | 15-20 分 |
修正しない場合のコスト:支払い後に閉じる手段がなかったり、行き止まりになったりすると、リリースから数時間以内に星 1 つのレビューが投稿されます。そのレビューを相殺するには、肯定的なレビューが 10~20 件必要です。15 分の修正で、何週間にもわたる事後対応を防げます。
正当化を防ぐ
| 考え | 実情 |
|---|---|
| 「UX の問題は見た目を整えるだけなので、後で修正すればよい」 | UX の行き止まりは星 1 つのレビューにつながります。これは機能強化ではなく、不具合です。今すぐ 15 分かけて修正すれば、何週間にもわたる事後対応を防げます。 |
| 「ユーザーが使い方を理解してくれる」 | ユーザーは使い方を理解しようとしません。アプリを削除します。ユーザーが試す時間は平均 30 秒です。 |
| 「リリース後に空の状態を追加しよう」 | 空の状態は、新規ユーザーが最初に目にするものです。これを用意せずにリリースするのは、壊れた状態でリリースすることです。 |
| 「この修正は大きなデザイン変更だ」 | UX の修正の多くは配置または状態の変更です(10~30 分)。上記の「修正工数」の表を確認してください。 |
| 「アクセシビリティは別の問題だ」 | VoiceOver のユーザーがフローを完了できないなら、それは行き止まりです。同じ不具合でも、ユーザーが異なるだけです。 |
| 「この画面は一時的なものだ」 | 一時的な画面もリリースされます。必ず確認してください。 |
| 「閉じるジェスチャーで対応できる」 | fullScreenCover には閉じるジェスチャーがありません。それが問題の原因です。 |
リソース
スキル:axiom-swiftui-nav、axiom-accessibility-diag、axiom-hig、axiom-swiftui-debugging
エージェント:ux-flow-auditor(自動スキャン)、swiftui-nav-auditor(ナビゲーションアーキテクチャ)、accessibility-auditor(WCAG 準拠)