共通レイアウトのパンくず

パンくずの正本は BreadcrumbSegment[] で、各段は name、href、current を持つ。 現在地にも URL を保持し、画面では現在地をリンクにせず aria-current="page" 付きの文字として描く。 AppBreadcrumbs は配列を描画するだけで、ルートや API 応答から段を組み直さない。

段の出所と行き先

タスク詳細は「ホーム > プロジェクト名 > 親タスク名 > タスク名」と表示する。 親がなければプロジェクト名からタスク名へ続き、ホームを除く二段になる。 ホームは現在のテナントの /{tenant}/my-tasks、プロジェクト名はそのプロジェクトのボード入口 /{tenant}/projects/{projectKey}/tasks、親は同じプロジェクト内のタスク詳細へ進む。 ボード入口の現行表示形式は List で、別の board ルートはない。

テナントは既存のテナント一覧、プロジェクト名は UUID 解決に使うプロジェクト一覧、タスク名は詳細応答、親の名前と連番はサブタスク欄が既に取得する relations 応答から読む。 useBreadcrumbs は QueryCache の通知を購読して同じキーの状態を読み、追加の query observer や通信を作らない。 API と OpenAPI の変更は不要である。 テナントとプロジェクトのキーは現在のルートから毎回照合する。 Guest も利用できる My Tasks、所属プロジェクトの一覧、同じプロジェクトの親タスクにだけ案内し、テナント取得やメンバー管理の API を呼ばない。

二段以上深い親子関係でも、直近の親だけを表示してそれより上の祖先を省略する。 祖先を順に取得する通信を増やさず、直近の親への移動を繰り返せば上位へ辿れるためである。

未登録・読み込み・失敗

共通レイアウトのルートは breadcrumbRoute に列挙する。 未登録のページとエラーページでは配列を空にし、パンくずの nav を描かない。 直前のページの段を引き継ぐ状態を持たないため、登録し忘れても別のタスク名を表示しない。 プロフィールなど固定の画面名はルートに対応する名前を使い、プロジェクトとタスクの名前は実データから得る。

名前の取得中は骨組みを表示し、空の状態も含めてヘッダー内の高さを維持する。 タスクまたはプロジェクトの取得失敗では段をすべて落とし、ページ本体のエラー処理には影響させない。 親の取得だけが失敗した場合は親の段だけを落とす。 現在の親 UUID と一致しない古い relations 応答は使わない。

長い名前は省略表示し、title 属性で全文を確認できる。 狭い画面でも全段を一列に保ち、パンくずのリスト内を横スクロールさせてページ全体の横幅を広げない。

toBreadcrumbList(segments, origin) は配列を変更しない純関数である。 origin は呼び出し側が明示し、末尾以外の URL を絶対 URL に変換する。 position は 1 から連番にし、末尾の item は省く。 画面に表示する配列と同じ name を使う。

公開プロジェクトのページがないため、この関数はテスト以外から呼び出さず、HTML に構造化データを埋め込まない。 将来公開ページを用意する際に、そのページの公開可否と origin を決めてから利用する。 HTML への埋め込みを行う場合の script 用エスケープは、このオブジェクトへの写像とは別に実装する必要がある。