Yuki Takei il y a 8 mois
Parent
commit
a6c35cdd28

+ 40 - 0
apps/app/docs/plan/README.md

@@ -0,0 +1,40 @@
+# React State Management Documentation
+
+# React State Management Documentation
+
+## Current Documentation
+
+### [`jotai-migration.md`](jotai-migration.md)
+Jotai移行のガイドドキュメント(実装方針・パターン)
+
+- 移行方針と背景
+- 実装パターンとガイドライン
+- 判断基準とベストプラクティス
+- 移行の成果と技術スタック
+
+### [`jotai-migration-progress.md`](jotai-migration-progress.md)
+実装進捗と次のステップ(随時更新)
+
+- 完了済み実装の一覧
+- 次の実装ステップと優先順位
+- 進捗サマリーと更新履歴
+
+---
+
+## ドキュメント構造について
+
+### 設計方針
+**役割分離**: 安定的なガイドと頻繁に更新される進捗を分離
+
+- **`jotai-migration.md`**: 実装方針とパターン(安定的)
+- **`jotai-migration-progress.md`**: 進捗と次のステップ(頻繁更新)
+
+### メリット
+- **メンテナンス性向上**: 更新頻度に応じた適切な構造
+- **情報の明確化**: 各ドキュメントの責務が明確
+- **開発効率向上**: 必要な情報に素早くアクセス可能
+
+### 推奨される利用方法
+1. **新規参入者**: `jotai-migration.md` で実装方針とパターンを理解
+2. **開発者**: `jotai-migration-progress.md` で次のタスクを確認
+3. **レビュー**: `jotai-migration.md` の実装パターンで一貫性を保証

+ 90 - 0
apps/app/docs/plan/jotai-migration-progress.md

@@ -0,0 +1,90 @@
+# Jotai 移行進捗
+
+## 実装状況
+
+### ✅ 移行完了済み
+
+#### サイドバー・デバイス・エディター状態(完了)
+- ✅ `useDrawerOpened`: サイドバーのドロワー表示状態
+- ✅ `usePreferCollapsedMode`: サイドバーの折りたたみモード(永続化対応)
+- ✅ `useSidebarMode`: サイドバーの表示モード管理
+- ✅ `useCurrentSidebarContents`: サイドバーのコンテンツタイプ(永続化対応)
+- ✅ `useCollapsedContentsOpened`: 折りたたまれたコンテンツの開閉状態
+- ✅ `useCurrentProductNavWidth`: プロダクトナビゲーションの幅(永続化対応)
+- ✅ `useDeviceLargerThanXl`: デバイスサイズ判定
+- ✅ `useEditorMode`: エディターモード管理(部分的)
+
+#### SSRハイドレーション対応(完了)
+- ✅ `useHydrateSidebarAtoms`: 統一的なJotai atomsの初期化
+
+**実装済みファイル:**
+- `states/ui/sidebar.ts`: サイドバー状態の完全実装
+- `states/ui/device.ts`: デバイス状態
+- `states/ui/editor.ts`: エディター状態(部分)
+- `states/hydrate/sidebar.ts`: SSRハイドレーション
+
+## 🚧 次の実装ステップ(優先度順)
+
+### **優先度 1: ページ関連 UI 状態**
+
+#### 1. `usePageControlsX` の移行 ← **次の優先タスク**
+- **ファイル**: `/workspace/growi/apps/app/src/stores/ui.tsx:171`
+- **実装先**: `states/ui/page.ts`
+- **使用箇所**: 
+  - `PagePathNavSticky.tsx`
+  - `PageControls.tsx`
+  - `PageHeader.tsx`
+- **特徴**: 一時的な状態(永続化不要)
+- **実装方針**: シンプルな number atom として実装
+
+#### 2. `useSelectedGrant` の移行
+- **ファイル**: `/workspace/growi/apps/app/src/stores/ui.tsx:192`
+- **実装先**: `states/ui/editor.ts`
+- **使用箇所**: 
+  - `SavePageControls.tsx`
+  - `GrantSelector.tsx`
+  - `PageEditor.tsx`
+- **特徴**: エディター内の一時的な状態
+
+### **優先度 2: モーダル状態の一括移行**
+
+#### 3. 全モーダル状態の移行
+- **新規ファイル**: `states/ui/modal.ts`
+- **対象モーダル(全9種類)**:
+  - `usePageCreateModal`, `useGrantedGroupsInheritanceSelectModal`
+  - `useDeleteModal`, `useEmptyTrashModal`, `useDuplicateModal`
+  - `useRenameModal`, `usePutBackPageModal`, `usePresentationModal`
+  - `usePrivateLegacyPagesMigrationModal`
+- **実装方針**: 統一的なパターンでモーダル状態を管理
+- **特徴**: すべて一時的な状態で永続化不要
+
+### **優先度 3: データ関連状態の判定**
+
+以下はSWR継続使用を検討:
+- **Alert系**: `usePageStatusAlert`
+- **YJS関連**: `useCurrentPageYjsData`
+- **リモートページ関連**: revision関連の各種hooks
+- **編集クライアント**: `useEditingClients`
+
+### **最終フェーズ: クリーンアップ**
+
+#### 4. 不要ファイルの削除とリファクタリング
+- `stores/ui.tsx` の完全削除
+- `stores/modal.tsx` の完全削除
+- 残存する SWR ベースの状態の最終判定
+- ドキュメントの更新
+
+## 📊 進捗サマリー
+
+- **完了**: 8つの主要UI状態 + SSRハイドレーション
+- **次のタスク**: `usePageControlsX` の移行
+- **残り**: ページ関連2つ + モーダル9つ + クリーンアップ
+- **推定残工数**: 2-3週間(優先度3は判定のみ)
+
+---
+
+## 🔄 更新履歴
+
+- **2025-07-30**: ドキュメント統合、進捗の実装状況反映
+- **2025-07-XX**: サイドバー関連の移行完了
+- **2025-07-XX**: SSRハイドレーション対応完了

+ 0 - 253
apps/app/docs/plan/jotai-migration-todo.md

@@ -1,253 +0,0 @@
-# Jotai 移行 TODO リスト
-
-## 現在の進捗状況
-
-### ✅ 移行完了済み
-
-1. **サイドバー関連(完了済み)**
-   - `useDrawerOpened`: サイドバーのドロワー表示状態
-   - `usePreferCollapsedMode`: サイドバーの折りたたみモード設定(永続化含む)
-   - `useSidebarMode`: サイドバーの表示モード管理(`DRAWER`, `COLLAPSED`, `DOCK`)
-
-2. **デバイス状態(完了済み)**
-   - `useDeviceLargerThanXl`: デバイスサイズ判定
-
-3. **エディター状態(部分的)**
-   - `useEditorMode`: エディターモード管理(TODO コメント有り)
-
-## 🚧 次に移行すべき状態(優先度順)
-
-### ✅ SSR対応の改善(完了)
-
-**実施内容:**
-- ~~`usePreferCollapsedModeInitializer` を削除し、`useHydrateAtoms` ベースの `UIStateHydrator` コンポーネントに移行~~
-- ✅ `usePreferCollapsedModeInitializer` を削除し、`useHydrateAtoms` ベースの `useHydrateSidebarAtoms` フックに移行
-- HoC パターンからカスタムフックパターンに変更し、よりシンプルで自然な実装に
-- 各ページで `useHydrateSidebarAtoms` を使用してJotai atomsの初期化を統一的に実行
-- SSR/CSRハイドレーション不整合の問題を解決
-
-**変更ファイル:**
-- ~~`states/ui/UIStateHydrator.tsx`: 新規作成~~ → `states/hydrate/sidebar.ts`: 新規作成(改良)
-- `states/ui/sidebar.ts`: initializer フック削除、base atom のエクスポート追加
-- `pages/utils/commons.ts`: `useInitSidebarConfig` 関数を簡素化
-- `pages/[[...path]].page.tsx`: `useHydrateSidebarAtoms` フック使用
-- `pages/_private-legacy-pages.page.tsx`: `useHydrateSidebarAtoms` フック使用
-
-**メリット:**
-- ✅ Jotai公式のSSR対応パターンに準拠
-- ✅ 複数atomsの統一的な初期化
-- ✅ ハイドレーション不整合の解決
-- ✅ 将来の状態追加時の拡張性向上
-- ✅ HoCよりもシンプルなフックパターン
-- ✅ JSX階層がフラット
-- ✅ より自然な React Hook の使用感
-
-### ✅ 優先度 1: UI 状態(クライアントサイド完結)- 完了
-
-#### ✅ 1.1 サイドバー関連の完全移行(完了)
-- ✅ `useCurrentSidebarContents`: サイドバーのコンテンツタイプ
-  - **実装**: `currentSidebarContentsAtom` + `currentSidebarContentsAtomExt`
-  - **永続化**: `scheduleToPut({ currentSidebarContents: data })`
-  - **SSRハイドレーション**: 追加済み
-
-- ✅ `useCollapsedContentsOpened`: 折りたたまれたコンテンツの開閉状態
-  - **実装**: `isCollapsedContentsOpenedAtom`
-  - **特徴**: 一時的な状態(永続化不要)
-
-- ✅ `useCurrentProductNavWidth`: プロダクトナビゲーションの幅
-  - **実装**: `currentProductNavWidthAtom` + `currentProductNavWidthAtomExt`
-  - **永続化**: `scheduleToPut({ currentProductNavWidth: data })`
-  - **SSRハイドレーション**: 追加済み
-
-**実施内容:**
-- ✅ 新しい atoms を `states/ui/sidebar.ts` に実装
-- ✅ `preferCollapsedModeAtomExt` パターンに従って永続化対応
-- ✅ SSRハイドレーションに全ての atoms を追加
-- ✅ `useInitSidebarConfig` 関数を完全削除
-- ✅ 使用箇所の更新(imports削除)
-
-**次のステップ**: 既存SWR版の使用箇所をJotai版に置き換え
-
-#### 1.2 ページ関連の UI 状態
-- [ ] `usePageControlsX`: ページコントロールのX座標
-  - **ファイル**: `/workspace/growi/apps/app/src/stores/ui.tsx:171`
-  - **使用箇所**: 
-    - `PagePathNavSticky.tsx`
-    - `PageControls.tsx`
-    - `PageHeader.tsx`
-  - **特徴**: 一時的な状態(永続化不要)
-
-- [ ] `useSelectedGrant`: 選択された権限設定
-  - **ファイル**: `/workspace/growi/apps/app/src/stores/ui.tsx:192`
-  - **使用箇所**: 
-    - `SavePageControls.tsx`
-    - `GrantSelector.tsx`
-    - `PageEditor.tsx`
-  - **特徴**: エディター内の一時的な状態
-
-### 優先度 2: モーダル状態
-
-#### 2.1 各種モーダルの開閉状態
-すべて `/workspace/growi/apps/app/src/stores/modal.tsx` に実装されている:
-
-- [ ] `usePageCreateModal`: ページ作成モーダル
-- [ ] `useGrantedGroupsInheritanceSelectModal`: グループ継承選択モーダル
-- [ ] `useDeleteModal`: 削除モーダル
-- [ ] `useEmptyTrashModal`: ゴミ箱空モーダル
-- [ ] `useDuplicateModal`: 複製モーダル
-- [ ] `useRenameModal`: リネームモーダル
-- [ ] `usePutBackPageModal`: ページ復元モーダル
-- [ ] `usePresentationModal`: プレゼンテーションモーダル
-- [ ] `usePrivateLegacyPagesMigrationModal`: プライベートページ移行モーダル
-
-**特徴**: すべて一時的な状態で永続化不要
-
-### 優先度 3: データ関連状態(SWR 継続使用を検討)
-
-以下は SWR での管理を継続すべきか検討が必要:
-
-- [ ] **Alert 系** (`/workspace/growi/apps/app/src/stores/alert.tsx`)
-  - `usePageStatusAlert`: ページステータスアラート
-
-- [ ] **YJS 関連** (`/workspace/growi/apps/app/src/stores/yjs.ts`)
-  - `useCurrentPageYjsData`: YJS データ
-
-- [ ] **リモートページ関連** (`/workspace/growi/apps/app/src/stores/remote-latest-page.ts`)
-  - `useRemoteRevisionId`
-  - `useRemoteRevisionBody`
-  - `useRemoteRevisionLastUpdateUser`
-  - `useRemoteRevisionLastUpdatedAt`
-
-- [ ] **編集クライアント** (`/workspace/growi/apps/app/src/stores/use-editing-clients.ts`)
-  - `useEditingClients`
-
-## 🎯 次の実装ステップ
-
-### ステップ 1: 優先度1の UI 状態を移行
-
-1. **`useCurrentSidebarContents` の移行**
-   - 新しい atom を `states/ui/sidebar.ts` に追加
-   - 永続化機能を実装(`usePreferCollapsedMode` のパターンを参考)
-   - 使用箇所を順次更新
-
-2. **`useCollapsedContentsOpened` の移行**
-   - シンプルな boolean atom として実装
-   - 使用箇所を順次更新
-
-3. **`useCurrentProductNavWidth` の移行**
-   - 永続化機能付きの atom として実装
-   - 使用箇所を順次更新
-
-4. **`usePageControlsX` の移行**
-   - シンプルな number atom として実装
-   - 使用箇所を順次更新
-
-5. **`useSelectedGrant` の移行**
-   - エディター関連の atom として `states/ui/editor.ts` に追加
-   - 使用箇所を順次更新
-
-### ステップ 2: モーダル状態の移行
-
-1. **新しいファイル作成**: `states/ui/modal.ts`
-2. **各モーダルの atom を実装**
-   - 統一的なパターンでモーダル状態を管理
-   - 開閉とデータ保持の機能を提供
-3. **既存の `stores/modal.tsx` から順次移行**
-
-### ステップ 3: 移行完了後のクリーンアップ
-
-1. **不要になったファイルの削除**
-   - `stores/ui.tsx` の移行済み部分を削除
-   - `stores/modal.tsx` の移行済み部分を削除
-
-2. **統一的なパターンの確立**
-   - 命名規則の統一
-   - ディレクトリ構造の整理
-   - ドキュメントの更新
-
-### 📋 移行時の注意点
-
-### SSR対応パターン(ハイドレーション専用モジュール方式)
-```typescript
-// states/hydrate/sidebar.ts - サイドバー状態のSSRハイドレーション
-export const useHydrateSidebarAtoms = (sidebarConfig: ISidebarConfig, userUISettings?: IUserUISettings): void => {
-  useHydrateAtoms([
-    [preferCollapsedModeAtom, userUISettings?.preferCollapsedModeByUser ?? sidebarConfig.isSidebarCollapsedMode],
-    // 他のサイドバー関連 atom も同様に追加
-  ]);
-};
-
-// 各ページでの使用(シンプル!)
-const MyPage = (props) => {
-  useHydrateSidebarAtoms(props.sidebarConfig, props.userUISettings);
-  // 他のロジック...
-  return <div>...</div>;
-};
-
-// 将来の拡張例
-// states/hydrate/modal.ts
-// states/hydrate/editor.ts
-```
-
-**ディレクトリ構造:**
-```
-states/
-├── ui/
-│   ├── sidebar.ts      # サイドバー状態の定義・操作
-│   ├── modal.ts        # モーダル状態の定義・操作
-│   └── editor.ts       # エディター状態の定義・操作
-└── hydrate/
-    ├── sidebar.ts      # サイドバー状態のSSRハイドレーション
-    ├── modal.ts        # モーダル状態のSSRハイドレーション (将来)
-    └── editor.ts       # エディター状態のSSRハイドレーション (将来)
-```
-
-### 永続化パターン
-```typescript
-// 永続化が必要な状態の実装パターン
-const someSettingAtom = atom(defaultValue);
-const someSettingAtomExt = atom(
-  get => get(someSettingAtom),
-  (get, set, update: ValueType) => {
-    set(someSettingAtom, update);
-    scheduleToPut({ settingKey: update });
-  },
-);
-```
-
-### 初期化パターン
-```typescript
-// サーバーサイドデータでの初期化パターン
-const initializedAtom = atom(false);
-export const useSomeSettingInitializer = (initialData: ValueType): void => {
-  const [isInitialized, setIsInitialized] = useAtom(initializedAtom);
-  const [, setSomeSetting] = useSomeSetting();
-
-  useEffect(() => {
-    if (!isInitialized) {
-      setSomeSetting(initialData);
-      setIsInitialized(true);
-    }
-  }, [isInitialized, setSomeSetting, setIsInitialized, initialData]);
-};
-```
-
-### テスト戦略
-- 各 atom の単体テスト
-- 永続化機能のテスト
-- コンポーネント結合テスト
-- E2E テストでの動作確認
-
-## 🔍 判断基準
-
-### Jotai に移行すべき状態
-- ✅ クライアントサイド完結の UI 状態
-- ✅ 同期的な状態更新
-- ✅ シンプルなデータ構造
-- ✅ コンポーネント間での状態共有が必要
-
-### SWR を継続使用すべき状態
-- ❌ サーバーからのデータフェッチが必要
-- ❌ 非同期的な状態更新
-- ❌ キャッシュ機能が重要
-- ❌ リアルタイム更新が必要

+ 109 - 0
apps/app/docs/plan/jotai-migration.md

@@ -0,0 +1,109 @@
+# Jotai 移行ガイド
+
+> **📊 最新の進捗状況**: [`jotai-migration-progress.md`](jotai-migration-progress.md) を参照
+
+## 1. 背景と移行方針
+
+### 課題
+- `useSWRStatic` や `useContextSWR` による複雑な状態管理
+- パフォーマンスの問題と潜在的なバグ
+- 責務の不明確性
+
+### 解決方針
+**役割分担の明確化:**
+- **SWR**: データフェッチング、サーバーキャッシュ管理に特化
+- **Jotai**: クライアントサイドUI状態、同期的な状態管理に特化
+
+## 2. 実装ガイド
+
+### ディレクトリ構造
+
+```
+states/
+├── ui/
+│   ├── sidebar.ts      # サイドバー状態 ✅
+│   ├── device.ts       # デバイス状態 ✅
+│   ├── editor.ts       # エディター状態 ✅(部分)
+│   ├── page.ts         # ページ関連状態(次の対象)
+│   └── modal.ts        # モーダル状態(未作成)
+└── hydrate/
+    └── sidebar.ts      # SSRハイドレーション ✅
+```
+
+### 実装パターン
+
+#### 永続化対応パターン
+```typescript
+// 永続化が必要な状態
+const someSettingAtom = atom(defaultValue);
+const someSettingAtomExt = atom(
+  get => get(someSettingAtom),
+  (get, set, update: ValueType) => {
+    set(someSettingAtom, update);
+    scheduleToPut({ settingKey: update });
+  },
+);
+
+export const useSomeSetting = () => useAtom(someSettingAtomExt);
+```
+
+#### 一時的な状態パターン
+```typescript
+// 永続化不要な一時的な状態
+const temporaryStateAtom = atom(defaultValue);
+
+export const useTemporaryState = () => useAtom(temporaryStateAtom);
+```
+
+#### SSRハイドレーションパターン
+```typescript
+// states/hydrate/feature.ts
+export const useHydrateFeatureAtoms = (initialData: InitialData) => {
+  useHydrateAtoms([
+    [featureAtom, initialData.feature],
+    // 他のatoms...
+  ]);
+};
+```
+
+### 命名規則
+- **Atom**: `{feature}Atom`
+- **Hook**: `use{Feature}`
+- **永続化対応**: `{feature}AtomExt`
+
+## 3. 判断基準
+
+### Jotai移行対象
+- ✅ クライアントサイド完結のUI状態
+- ✅ 同期的な状態更新
+- ✅ シンプルなデータ構造
+- ✅ コンポーネント間での状態共有が必要
+
+### SWR継続使用対象
+- ❌ サーバーからのデータフェッチが必要
+- ❌ 非同期的な状態更新
+- ❌ キャッシュ機能が重要
+- ❌ リアルタイム更新が必要
+
+## 4. 移行の成果
+
+### 技術的改善
+- **コードの簡潔化**: 複雑なSWRベースのカスタムフックがシンプルなatomsに
+- **責務の分離**: データフェッチングとクライアント状態管理の明確な分離
+- **TypeScript親和性**: 優れた型推論とタイプセーフティ
+- **パフォーマンス改善**: 必要な箇所のみの再レンダリング
+- **保守性向上**: 状態の依存関係が明確化
+
+### 開発体験の向上
+- **直感的なAPI**: React の `useState` に近い使用感
+- **デバッグの容易さ**: 状態の変更が追跡しやすい
+- **テストの簡素化**: モックやテストデータの管理が簡単
+
+---
+
+## 5. 技術スタック
+
+- **Jotai**: v2.x(アトミックな状態管理)
+- **SSR対応**: `useHydrateAtoms`(公式パターン)
+- **永続化**: 既存の`scheduleToPut`機構と連携
+- **TypeScript**: 型推論とタイプセーフティ

+ 0 - 165
apps/app/docs/plan/react-state-management-plan.md

@@ -1,165 +0,0 @@
-# React グローバルステート管理改善計画
-
-## 1. 背景と目的
-
-現在のプロジェクトでは、グローバルな状態管理に SWR が中心的に利用されています。特に `useSWRStatic` や `useContextSWR` といったカスタムフックを用いて、クライアントサイドの状態管理も行われています。
-
-しかし、以下の課題が認識されています。
-
-*   **パフォーマンスへの懸念:** アプリケーションの特定の箇所でパフォーマンスの問題が発生している可能性があります。SWR の再検証戦略やカスタムフックの実装が影響している可能性が考えられます。
-*   **潜在的なバグ:** 特に `useSWRStatic` 周りで、意図しない挙動やデータの不整合が発生している可能性が指摘されています。カスタムフックの複雑さやキャッシュの扱い方が原因である可能性があります。
-
-これらの課題を解決し、より堅牢でメンテナンスしやすく、パフォーマンスの良い状態管理を実現することを目的とします。
-
-## 2. 基本方針: 役割分担の見直し
-
-SWR と、クライアントサイド状態管理に特化した軽量ライブラリ(Jotai)を併用する方針を採用します。
-
-*   **SWR:** データフェッチング、サーバーキャッシュ管理、非同期状態管理に特化して利用を継続します。リモートから取得するデータ(ページ情報、ユーザー情報など)の管理に適しています。
-*   **Jotai:** クライアントサイドで完結するUI状態や、同期的な状態管理を担当します。(例: モーダルの開閉、テーマ設定、フォーム入力値など)
-
-```mermaid
-graph TD
-    subgraph "提案: 役割分担"
-        A[React Component] --> B{useSWR};
-        B --> C[SWR Cache (サーバーキャッシュ)];
-        C -- データフェッチ --> D[API Server];
-
-        A --> E{useAtom (Jotai)};
-        E --> F[Jotai Atoms (クライアント状態)];
-    end
-```
-
-この方針により、以下のメリットが期待されます。
-
-*   **責務の分離:** 各ライブラリの得意分野を活かし、コードの見通しが良くなります。
-*   **コードの簡潔化:** 複雑なカスタムフック (`useSWRStatic`, `useContextSWR`) が不要になる可能性があります。
-*   **パフォーマンス改善:** 不要な再レンダリングを抑制しやすくなります。
-*   **予測可能性の向上:** 状態の更新フローが明確になります。
-
-## 3. 具体的な計画ステップ
-
-以下のステップで段階的に改善を進めます。
-
-### ステップ1: Jotai 導入 PoC (Proof of Concept) の実施
-
-クライアントサイド状態管理ライブラリとして Jotai を導入し、その使用感やプロジェクトへの適合性を確認するため、小規模な PoC を実施します。
-
-*   **対象:** `useSWRStatic` や `useContextSWR` で管理されているクライアント状態の中から、比較的シンプルで影響範囲の小さいものをいくつか選定します。(例: `isDrawerOpened`, `sidebarContents`, `preferCollapsedMode` など)
-*   **実施内容:** 選定した状態を Jotai で実装します。
-*   **確認観点:**
-    *   実装の容易さ、コードの可読性
-    *   TypeScript との親和性
-    *   パフォーマンス(React DevTools で再レンダリングを確認)
-    *   テストのしやすさ
-    *   バンドルサイズへの影響
-
-### ステップ2: 段階的な移行
-
-PoC の結果を踏まえ、Jotai を本格的に導入し、既存の状態管理を段階的に移行します。
-
-1.  **Jotai 導入:** Jotai をプロジェクトの依存関係に追加し、基本的な設定を行います。(PoC で実施済みであれば確認のみ)
-2.  **小規模な状態から移行:** まずは PoC で試した状態や、新規に追加されるクライアント状態から新しいライブラリでの管理を開始します。
-3.  **既存コードの置き換え:** `useSWRStatic` / `useContextSWR` を利用している箇所を特定し、クライアント状態管理の部分を新しいライブラリに置き換えていきます。
-    *   SWR はデータフェッチングが必要な箇所では引き続き利用します。
-    *   カスタムフック (`useSWRStatic`, `useContextSWR`) の利用箇所を徐々に減らしていきます。
-4.  **テストの更新:** 状態管理の変更に伴い、関連するユニットテストや E2E テストを更新し、デグレードが発生しないことを確認します。
-
-## 4. 期待される効果
-
-*   状態管理コードの責務が明確になり、可読性とメンテナンス性が向上する。
-*   パフォーマンスが改善され、ユーザー体験が向上する。
-*   `useSWRStatic` などに起因する可能性のあったバグが解消される。
-*   モダンな状態管理ライブラリの知見がチームに蓄積される。
-
-## 5. 移行の進捗状況
-
-### 5.1 完了した移行
-
-以下の状態を Jotai に移行完了しました:
-
-1.  **PoC フェーズ:**
-    *   `useDrawerOpened`: サイドバーのドロワー表示状態
-    *   `usePreferCollapsedMode`: サイドバーの折りたたみモード設定(永続化含む)
-
-2.  **追加移行完了:**
-    *   `useSidebarMode`: サイドバーの表示モード管理(`DRAWER`, `COLLAPSED`, `DOCK`)
-        *   `editorMode` と `isDeviceLargerThanXl` の状態との連携
-        *   関連コンポーネントの更新(`PagePathNavSticky`, `Sidebar`, `SidebarContents`, `PrimaryItems`)
-
-### 5.2 移行パターンの確立
-
-移行を通じて、以下のパターンが確立されました:
-
-*   **ディレクトリ構造:** Jotai の実装は `states/` ディレクトリに配置
-*   **依存関係の管理:** 複数の状態を組み合わせる場合(例: `useSidebarMode`)の実装パターン
-*   **永続化の方法:** ユーザー設定の永続化が必要な状態の実装パターン
-
-## 6. 今後の方針
-
-### 6.1 実施した PoC の概要
-
-以下の状態を Jotai を使用して実装し、検証を行いました:
-
-1.  **`useDrawerOpened`:** サイドバーのドロワー表示状態
-2.  **`usePreferCollapsedMode`:** サイドバーの折りたたみモード設定(ユーザー設定の永続化を含む)
-3.  **`useSidebarMode`:** サイドバーの表示モード管理(複数の状態を組み合わせた派生状態)
-4.  **`useDeviceLargerThanXl`:** デバイスサイズ判定
-
-### 6.2 実装内容
-
-*   新しい `states/` ディレクトリ構造を作成し、責務別に分割:
-    *   `states/ui/sidebar.ts`: サイドバー関連の状態定義・操作
-    *   `states/ui/device.ts`: デバイス状態
-    *   `states/ui/editor.ts`: エディター関連の状態
-    *   `states/ui/helper.ts`: 型定義ヘルパー
-    *   `states/hydrate/sidebar.ts`: サイドバー状態のSSRハイドレーション専用
-*   既存の SWR ベースの実装を削除
-*   関連するコンポーネントを新しいカスタムフックを使用するように修正:
-    *   `DrawerToggler`
-    *   `GrowiNavbarBottom`
-    *   `EditorNavbarBottom`
-    *   `Sidebar`
-    *   `ToggleCollapseButton`
-    *   `PagePathNavSticky`
-    *   `SidebarContents`
-    *   `PrimaryItems`
-*   `pages/utils/commons.ts` の初期化処理を更新
-
-### 6.3 PoC の成果
-
-*   **コードの簡潔化:** SWR の仕組みを使った複雑なカスタムフックが、シンプルな Jotai の atoms とフックに置き換わりました。
-*   **責務の分離:** データフェッチングとクライアント状態管理の役割が明確に分かれました。
-*   **実装の直感性:** Jotai の API は React の `useState` に近く、理解しやすい実装となりました。
-*   **TypeScript との親和性:** Jotai は優れた型推論をサポートしており、型安全な実装が実現できました。
-*   **パフォーマンス改善:** 必要な箇所のみの再レンダリングが実現され、パフォーマンスが改善されました。
-*   **保守性の向上:** 状態の依存関係が明確になり、デバッグが容易になりました。
-
-### 6.4 次の実装フェーズ
-
-PoC の成功を受けて、以下の段階的な移行を実施します:
-
-#### フェーズ 1: UI 状態の移行(実施中)
-*   `useCurrentSidebarContents`: サイドバーのコンテンツタイプ(永続化必要)
-*   `useCollapsedContentsOpened`: 折りたたまれたコンテンツの開閉状態
-*   `useCurrentProductNavWidth`: プロダクトナビゲーションの幅(永続化必要)
-*   `usePageControlsX`: ページコントロールのX座標
-*   `useSelectedGrant`: 選択された権限設定
-
-#### フェーズ 2: モーダル状態の移行
-*   各種モーダルの開閉状態(`stores/modal.tsx` の内容)
-*   統一的なモーダル管理パターンの確立
-
-#### フェーズ 3: その他のクライアント状態
-*   データフェッチングが不要な状態の特定と移行
-*   SWR を継続使用すべき状態の明確化
-
-### 6.5 技術的指針
-
-*   **ディレクトリ構造**: `states/ui/` 配下に機能別でファイルを分割
-*   **命名規則**: `{feature}Atom` および `use{Feature}` パターンを継続
-*   **永続化**: ユーザー設定が必要な状態は `scheduleToPut` を使用した永続化を実装
-*   **初期化**: サーバーサイドデータが必要な状態は専用の initializer フックを提供
-*   **型安全性**: TypeScript の型推論を活用し、`UseAtom` ヘルパー型を使用
-
-詳細な移行計画とTODOリストは `jotai-migration-todo.md` を参照してください。