> For the complete documentation index, see [llms.txt](https://summerain-1.gitbook.io/summerain/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://summerain-1.gitbook.io/summerain/ja/kaibumi/frontend-architecture/10-pages-ui-ux.md).

# 10 - ページ UI/UX 仕様

> \[!WARNING] **アーカイブ済みの設計記録です。** このページは完成済みの V2 フロントエンドより前に 作成されており、古いバージョン、パス、実装状態を含む場合があります。

> [フロントエンドアーキテクチャ設計（索引）](/summerain/ja/kaibumi/frontend-architecture.md)の一部です。デザイントークンと コンポーネント規則は [design-system/MASTER.md](/summerain/ja/kaibumi/frontend-architecture/master.md) を参照して ください。以下の各レイアウトは `mockup/index.html` で検証済みです。すべてのコンポーネントは shadcn/ui を組み合わせて実装します。

## 公開ページ

### `/` ランディングページ

* **表示対象：** 全員。ログイン済みの訪問者は自動的に `/dashboard` へリダイレクトする。
* **レイアウト：** （1）コーヒー色のグラデーション、`clamp()` の大見出し、2 つの CTA（「今すぐ アップロード」/「無料登録」）を持つヒーロー、（2）4 枚のカードで構成する機能 **Bento**、 （3）3 ステップの利用方法、（4）CTA の帯。
* **コンポーネント：** `Card`（Bento）+ `Button` + `Badge` + `Separator`。
* **モーション：** ヒーロー文言を段階的に表示する `fadeUp`、ドット模様の `breathe`、アンカーへの スムーズスクロール。
* **レスポンシブ：** モバイルでは 1 カラムとし、CTA を全幅にする。

### `/login` と `/register`

* **レイアウト：** 暖色のグラデーション背景の中央に `Card`（`max-w` 440）。フィールドの**ラベルを コントロールの上**に置く（`FieldGroup` + `Field`、プレースホルダーは使わない）。パスワードの 表示切り替え（`InputGroup` + `InputGroupAddon`）。読み込み中状態（`Spinner` + `disabled`） を備えた全幅のプライマリーボタン。
* **CAPTCHA 配置領域：** `provider != none` の場合はフォーム内に埋め込む。 [03](/summerain/ja/kaibumi/frontend-architecture/03-features.md#pluggable-captcha-administrator-selected-default-none)を参照。
* **コンポーネント：** `Card` + `Field` + `Input` + `Button` + `Alert`（エラー）+ カスタム ドロップダウン（ネイティブの選択欄は使わない）。
* **エラー処理：** `2001` 認証情報エラー -> フィールド下の赤字、`2008/429` レート制限 -> `Alert` + カウントダウン、`4030` アカウント無効 -> `Alert`、`2009/1004` CAPTCHA エラー。 すべての文言は i18n を使用する。
* **処理の流れ：** ログイン成功時は `queryClient.clear()` を呼び出して `/dashboard` へ移動する。 登録成功時は自動ログインせず、Toast とともに `/login` へ移動する。

## 保護ページ（`AuthGuard`）

### `/dashboard` ダッシュボード（ロール別）

* **レイアウト：** 上部に Bento 形式の統計カード、その下に「最近の画像」グリッドとサイドバー。 サイドバーにはストレージ使用量の進捗と管理者向けシステム概要カードを置く。
* **データ：** 統計／割り当て（`storage_percent` を含む）は `useProfile`、最近の画像は `useImages`。管理者向けの `useAdminStats` も遅延読み込みする。`storage_used` は 常に `useProfile` を正とする。
* **コンポーネント：** 完全な `Card` 構成 + `Progress` + `Avatar` + `Chart`（管理者領域）+ `Empty`（画像なし）。
* **ロール別表示：** 全員共通の領域に加え、`role==='admin'` の場合だけシステム概要カードと 「管理画面を開く」ボタンを表示する。一般ユーザーが管理者向けコードをダウンロードしない よう `React.lazy` を使用する。
* **空状態：** 画像なし -> `Empty` + 「最初の画像をアップロード」。

### `/images` マイ画像

* **レイアウト：** 検索、公開範囲フィルター、グリッド／リスト切り替えのツールバー、画像の グリッド／リスト、無限スクロール。
* **コンポーネント：** `Input`（検索）+ カスタムドロップダウン / `ToggleGroup`（フィルターと表示）+ グリッド用 `Card` + `Skeleton` + `Empty` + `DropdownMenu`（行操作）+ `AlertDialog`（削除確認）。
* **操作：** ホバー時にカードを持ち上げ、ファイル名のオーバーレイと表示／削除操作を 表示する。書き込み操作には CSRF を付ける。
* **ページネーション：** `useInfiniteQuery`。`has_more` を終了条件とし、下端の監視要素と `Skeleton` を使う。エラー時は再試行する。
* **副作用：** アップロード／削除／公開範囲変更後に `['images']` を無効化し、 `refreshUser()` を呼び出す。

### `/images/:id` 画像詳細（所有者のみ）

* **レイアウト：** 2 カラム。左にクリックでライトボックスを開く大画像、右に情報パネル。
* **コンポーネント：** `Card`（直接リンク、メタデータ、非公開トークン）+ `Table` / 定義リスト （メタデータ）+ `InputGroup`（直接リンクとコピー用 `InputGroupAddon`）+ `Switch` / カスタムドロップダウン（公開範囲）+ 非公開トークンのコントロール：`Badge`（状態）+ カスタムドロップダウン （TTL）+ `Button`（発行／再発行／失効）+ `Alert`（警告）。
* **ライトボックス：** 大画像のクリックで [MASTER セクション 10](/summerain/ja/kaibumi/frontend-architecture/master.md)の全画面ライトボックスを開く。
* **非公開トークンパネル：** 現在のトークン（マスク表示 + コピー）、共有 URL `/i/<link>?token=`、TTL 選択欄（既定 1h、範囲 10min-72h）、明示的な 発行／再発行／失効操作。自動操作は行わない。非公開へ切り替えると `warning/tokens_revoked` Toast を表示する。
* **レスポンシブ：** モバイルでは画像を先頭にした 1 カラム。

### `/upload` アップロード

* **レイアウト：** クリック／ドラッグ入力とホバー時の跳ねる動きを持つ大きな破線のドロップゾーン、 公開範囲とタグの選択肢、キュー。
* **コンポーネント：** ドロップゾーン（トークンスタイル）+ `ToggleGroup` / カスタムドロップダウン （公開範囲）+ `Field` + `Card` + `Progress` + `Badge`（状態）のキュー項目。
* **検証：** ファイルごとのサイズ／形式／件数、`4012` 容量超過 `Alert`、 `4029/429` レート制限、成功時の Toast + `refreshUser`。
* **状態：** 各項目は `uploading`（`Spinner` + きらめく進捗表示）、`complete` （成功を示す `Badge`）、`failed`（再試行）を取る。

### `/profile` プロフィール

* **レイアウト：** アカウント情報カード、割り当て使用量、パスワード変更カード。
* **コンポーネント：** `Card` + `Badge`（ロール／状態）+ `FieldGroup` / `Field` （パスワード変更）+ `Separator`。
* **処理の流れ：** パスワード変更成功後、バックエンドが全セッションを削除する。 `queryClient.clear()`、auth-store の消去、`/login` への遷移、Toast 表示を行う。
* **対象外：** アバターまたはプロフィール編集用エンドポイントはない。

## 管理者ページ（`AdminGuard` + バックエンドの `RequireAdmin` による 403 フォールバック）

### `/admin` 管理概要

* **コンポーネント：** `Card` の統計一覧 + `Chart`（棒グラフ、遅延読み込み、 動きを抑える設定を尊重）+ `Empty`。
* **自動復旧：** `4030/4032` の場合は `refreshUser()` を呼び出し、`/dashboard` に戻す。

### `/admin/users` ユーザー管理

* **レイアウト：** 検索 + デスクトップの表 / モバイルのカード。
* **コンポーネント：** `Table`（デスクトップ、`ScrollArea` / オーバーフロー）+ `Badge`（ロール／状態、 色と文字）+ `Avatar` + `Pagination` + `DropdownMenu`（停止／復元）+ `AlertDialog`（確認）+ `Input`（検索）。
* **操作：** `suspended` に設定すると、バックエンドはそのユーザーのセッションを削除し、 通知を送る。CSRF を付ける。**ユーザーは削除できない。**
* **レスポンシブ：** 幅 820 以下では表を 1 カラムのカードに置き換える。先頭セルを 見出しとし、`td::before` で `data-label` を表示し、カスタムスクロールバーを使用する。

### `/admin/configs` システム設定

* **レイアウト：** CAPTCHA、非公開トークン、その他設定のセクションカード形式のフォーム + 固定表示の保存バー。
* **コンポーネント：** `Card` + `Field` + カスタムドロップダウン（CAPTCHA プロバイダー）+ `Input` （キー）+ `Slider` / `Input`（TTL）+ `Button`（保存）+ `Sonner`（成功）。
* **内容：** CAPTCHA `provider`（`none/recaptcha/turnstile/geetest_v4`）+ キー、 600000-259200000 ms の範囲にある非公開トークンの既定 TTL。プロバイダーの変更時には、 対応する外部リソースが有効になることを警告する。

## グローバルコンポーネント（独立ページではない）

* **ナビゲーションバー：** 固定表示 + 半透明のぼかし。左にブランド、ロール対応リンク、明示的な ☀/🌙 の `ThemeToggle`（VT + マスク）、ボタン内に未読ドットを固定した `NotificationBell`、 `Avatar` + `AvatarFallback` + ロール `Badge` + ログアウトを含むユーザーメニュー。
  * **レスポンシブ：** 幅 820 以下ではタブバーを隠し、ハンバーガーメニュー + 横から現れる `Sheet` を 使用する。完全なナビゲーション、背景幕、Esc で閉じる機能、選択時に閉じる機能を備え、ブランドは左、 操作は右に置く。
* **NotificationBell ドロップダウン：** `DropdownMenu` の一覧 + 未読 `Badge` + CSRF 付きの すべて既読／すべて消去。通知なしは `Empty`。
* **404：** `Empty` + ホームへ戻る `Button`。
* **Toaster：** 成功、エラー、レート制限、アカウント無効のメッセージに `sonner` を 使用し、3-5s 後に自動消去。`aria-live=polite`。
* **カスタムドロップダウン：** ネイティブの `<select>` を置き換え、独自の矢印、選択済みチェックマーク、 開閉アニメーション、外側クリックの処理を提供する。
* **カスタムスクロールバー：** ネイティブの灰色バーの代わりに細いテーマ色のバーを使用する。

***

## 遷移先とロール差分

3 種類のロールはすべて `/dashboard` に遷移します。差分は `/dashboard` で管理者領域を 描画するか、`/admin/*` を許可するかだけです。すべての未認可アクセスはバックエンドの 403 が最終的に保護します。[02](/summerain/ja/kaibumi/frontend-architecture/02-architecture.md) と [09](/summerain/ja/kaibumi/frontend-architecture/09-decisions-and-scope.md)を参照してください。

<- [09 判断と対象範囲](/summerain/ja/kaibumi/frontend-architecture/09-decisions-and-scope.md) - [索引](/summerain/ja/kaibumi/frontend-architecture.md) - デザインシステム：[MASTER](/summerain/ja/kaibumi/frontend-architecture/master.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://summerain-1.gitbook.io/summerain/ja/kaibumi/frontend-architecture/10-pages-ui-ux.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
