フィルターを保ち、失敗した処理を正しく伝え、始めた作業へ戻れるようにする。小さな判断が実装で形になるとき、Muhitの設計の考え方が見えてくる。
最初の文章では、Muhitを共通の振る舞いの言語として考えた。インターフェースの一貫性は、色や書体と同じくらい、画面を移るなかで利用者の作業がどう続いていくかに関わっていた。
この考えが実装でどう現れるのか、小さな流れをたどってみたい。レコードを探し、開き、メモを書き、一覧に戻るという流れだ。
Muhitの現在の開発例の一つは、この流れを軸にしている。研究の枠組み、共有資料、判断のメモといった少数のレコードがある。利用者は検索で一覧を絞り、レコードを開いてメモを書く。一覧に戻って同じレコードを再び開くと、検索条件も書いたメモも残っている。
見た目にはありふれた操作だ。しかし実現するには、何を記憶し、いつ忘れ、利用者に何を伝えるのかを決める必要がある。
一つのレコードをめぐる判断
この例では、各レコードの下書きをそれぞれの識別子にひもづけて保持する。そのため、あるレコードに書いたメモが別のレコードの入力欄に現れることはない。一覧に戻っても下書きは消えず、検索欄も利用者が残した条件を保つ。
こうすれば、画面に戻るたびに作業を組み立て直さずに済む。検索語をもう一度入力し、正しいレコードを探し、直前に書いた一文を思い出そうとする必要がなくなる。
保持する時間も設計の一部だ。この例の下書きは、開いているページのメモリにだけ存在する。ページを再読み込みしたりタブを閉じたりすると失われる。その範囲は編集欄のそばに明記されている。
労力を守るという原則は、具体的な問いになる。どの情報を、どの範囲で、いつまで保持するのか。
もう一つの判断は、画面間のフォーカス移動にある。レコードを開くとキーボードフォーカスは詳細の見出しへ移る。一覧に戻ると、そのレコードのボタンへ戻る。
視覚的な切り替えに、キーボードで使う人にも分かる対応が生まれる。新しい表示がどこから始まり、戻ったときにどこにいるのかが明確になる。
検索結果がない場合にも専用の状態がある。条件に合うレコードがないことを伝え、検索を消去する手段を用意する。データの読み込み失敗としては扱わない。次の行動が異なるからだ。検索結果を変えるには条件を変える必要があり、リクエストの失敗なら再試行が適切な場合がある。
流れのなかのエラーとキャンセル
同じ例には、処理を意図的に失敗させる選択肢がある。順調に進む画面だけでなく、立て直すときの振る舞いを確かめるためだ。
利用者がメモを書いて処理を始めると、画面は待機状態になる。重複送信を防ぎ、処理中はメモを編集できなくし、キャンセルの操作を表示する。
例の処理が失敗しても、メモは残る。メッセージは起きたことと再試行の方法を伝える。ボタンの文言も新しい状態に合わせて変わる。
そのため、エラーは最初からすべてを繰り返させる中断にはならない。失敗した処理の周囲に、続けられる場所が残る。
キャンセルにも同じ注意を向ける。待機中に利用者が取りやめると、例の処理は止まり、下書きは残り、確認が行われなかったと伝える。以前の処理の遅れた結果が後から届いて、画面を成功状態に変えることもない。
実際のサーバーにつながるアプリケーションでは、ここにより慎重な扱いが必要になる。クライアント側でリクエストをキャンセルしても、サーバーですでに始まった処理が取り消された証拠にはならない。実際の結果は、アプリケーションが別途確認しなければならない。
この境界は、MuhitのReactとVueの参照実装にも現れる。フォームを再構築すると、実行中の処理に対してキャンセルのシグナルが発生する。アプリケーションには、そのシグナルを通信リクエストへ渡し、キャンセルされた応答で自身の状態を変更しないことが求められる。
ここでライブラリとアプリケーションの責任がつながる。コンポーネントは操作のライフサイクルを管理し、実際に保存されたかどうかはアプリケーションが把握する。
小さな実例のボタンが「ローカルで確認する」となっているのも、そのためだ。成功が意味するのは、そのタブのメモリ内での確認だけである。サーバーや永続ストレージに保存したという印象は与えない。
フィードバックが示す範囲は、実際に行われた処理の範囲と一致している必要がある。
この考えを別の画面へ運ぶ
こうした判断をプロジェクトごとに実装し直すのは、次第に難しくなる。言語、テーマ、表示が変わるときには、とくにコンポーネントの再構築が必要になることがある。
MuhitのReactとVueの参照実装では、テーブルを再構築するときに現在の表示のスナップショットを取得する。対応する流れでは、フィルター、選択、列の配置が新しいコンポーネントへ引き継がれる。アプリケーションが新しい値を明示した場合は、その値が優先される。
この細部は、状態を誰が管理するかを明確にする。アプリケーションが継続的に制御すべき情報は、対応する変更イベントを通じてアプリケーション自身の状態へ反映する必要がある。再描画のたびに維持したい振る舞いを、どこで管理するのかを把握しておく。
MuhitのJSONインターフェースアダプターにも同じ区別がある。無効な更新では現在の表示を維持し、有効な更新が成功すると表示を再構築する。この経路では、以前のテーブルのフィルターや選択は自動では引き継がれない。操作の連続性が必要なら、該当するコンポーネントのAPIを使ってアプリケーション側で整える必要がある。
テーマの判断も、定義された役割に沿っている。面の背景、読むための文字、操作の強調、キーボードフォーカスには、それぞれ別の変数がある。たとえば --mh-surface は --mh-text と組み合わせ、強調色のボタン上の文字には --mh-on-accent を使う。
これにより、パレットを変えてもコンポーネントの意味を追いやすくなる。それでも実際の画面を確かめる必要はある。選択中の項目は分かるか。フォーカスは見えるか。密度を上げても操作しやすいか。
だからMuhitをプロジェクトへ取り入れるときは、最も見栄えのする画面よりも、最初から最後までたどれる小さな作業から始めたい。レコードを探して編集するだけでも十分な場合がある。
そして同じ作業を、結果がないとき、処理に失敗したとき、利用者が取りやめたとき、言語を変えたとき、キーボードで操作したときにもたどる。
これらの例は、動作する振る舞いを示している。実機とスクリーンリーダーによる手動の受け入れ確認は、まだ完了すべき評価として残っている。
Muhitの実装で求めているものは、こうして形になる。利用者が始めた作業を続けられるとき、設計上の判断が見えてくる。メモがそこに残り、エラーを理解でき、画面の確認表示が実際に起きたことを伝えるときに。
この記事は、Muhitのローカルな0.16.0開発ソースにある設計原則、動作するレコード操作例、統合の契約に基づく。これらの例は、本番環境での利用や手動のアクセシビリティ受け入れ確認の完了を主張するものではない。
資料: Muhitのソースコード · JSONインターフェースの契約
続けて読む
共通するテーマを持つ文章。
インターフェースの提案は、処理の権限を与えるのか
Muhitを通して、AIによるインターフェースの提案、処理の権限、人の制御の境界を考える。
Muhit:インターフェースの一貫性は何から生まれるのか
Muhitを通して、視覚言語、ページの状態、文脈の保持、インターフェースの約束を考える。
つながり
Muhit:インターフェースの一貫性は何から生まれるのか
最初のMuhitの文章で考えた共通の振る舞いの言語を、下書き、フォーカス、エラー、キャンセル、テーマの動作例へと展開する。
インターフェースの提案は、処理の権限を与えるのか
動作するインターフェースの判断から、AIの提案、処理の権限、人の制御の間にある実装上の境界へ進む。