--- phase: 10-ux-interaction plan: 07 type: execute wave: 1 depends_on: [10-02, 10-03, 10-05] files_modified: - frontend/src/components/layout/AppSidebar.vue - frontend/src/components/layout/__tests__/AppSidebar.empty.test.js autonomous: true requirements: [UX-03, UX-01, UX-14] must_haves: truths: - "AppSidebar renders sidebar-indent skeleton placeholders for folders, topics, and cloud sections while loading" - "AppSidebar renders EmptyState size='sm' for each empty section (folders, topics, cloud)" - "AppSidebar no longer contains a New button for creating root folders (UX-14)" - "AppSidebar no longer contains startNewFolder/cancelNewFolder/submitNewFolder methods or the related state (showNewFolderInput, newFolderName, newFolderError)" - "StorageBrowser's own startNewFolder (file manager) is UNTOUCHED" artifacts: - path: "frontend/src/components/layout/AppSidebar.vue" provides: "Updated sidebar with skeleton, EmptyState, no inline New button" key_links: - from: "AppSidebar.vue" to: "EmptyState.vue" via: "" pattern: " Wire UX-03 (sidebar skeletons), UX-01 (sidebar EmptyState micro states), and UX-14 (remove sidebar "New" folder button + related state/methods) in `frontend/src/components/layout/AppSidebar.vue`. Per the planning_guidance, UX-14 removal targets ONLY AppSidebar's own folder-creation flow. The file manager's own inline new-folder UI (`StorageBrowser.startNewFolder`) is UNTOUCHED — it remains the canonical way to create folders. Output: AppSidebar.vue with skeleton placeholders matching TreeItem indent (pl-7), three EmptyState size='sm' micro states (folders/topics/cloud), and the "New" button + helper methods + state removed. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @CLAUDE.md @.planning/phases/10-ux-interaction/10-CONTEXT.md @.planning/phases/10-ux-interaction/10-RESEARCH.md @.planning/phases/10-ux-interaction/10-PATTERNS.md @frontend/src/components/layout/AppSidebar.vue @frontend/src/components/ui/EmptyState.vue @frontend/src/components/ui/TreeItem.vue @frontend/src/components/storage/StorageBrowser.vue **AppSidebar.vue uses Options API** — current file, see PATTERNS.md §"AppSidebar.vue". **Sidebar skeleton pattern (PATTERNS.md §3 Sidebar skeleton):** ```html
``` **Three sections requiring skeleton + EmptyState (RESEARCH.md §Component Inventory §3):** | Section | Loading condition | Empty condition | EmptyState icon | EmptyState headline | EmptyState CTA | |---------|-------------------|-----------------|-----------------|---------------------|----------------| | Folders | `loadingRoots` | `foldersStore.rootFolders.length === 0` | folder | "Create a folder in the file manager" | (none) | | Topics | `topicsStore.loading` | `topicsStore.topics.length === 0` | tag | "No topics yet" | (none) | | Cloud | `loadingCloudConnections` | `activeCloudConnections.length === 0` | cloud | "Connect in Settings" | router-link to /settings | All EmptyStates use `size="sm"`. **UX-14 removal targets in AppSidebar.vue:** - Template: the `` element near the folder section header (current lines 75-82) - Template: the inline new-folder `
` block (current lines 87-98) - Script: methods `startNewFolder()`, `cancelNewFolder()`, `submitNewFolder()` (current lines 289-312) - Script: state `showNewFolderInput`, `newFolderName`, `newFolderError` - Update the empty-folder text block (current lines 102-103) to remove the `&& !showNewFolderInput` condition since that variable no longer exists. **StorageBrowser invariant:** `frontend/src/components/storage/StorageBrowser.vue` still has its own `startNewFolder` function, `showNewFolderInput` state, and the inline new-folder input row — DO NOT touch any of these. Task 1: Promote AppSidebar.empty.test.js stubs to real tests frontend/src/components/layout/__tests__/AppSidebar.empty.test.js - frontend/src/components/layout/__tests__/AppSidebar.empty.test.js (Wave 0 stub) - frontend/src/components/layout/AppSidebar.vue (current state) - frontend/src/stores/folders.js, frontend/src/stores/topics.js, frontend/src/stores/cloudConnections.js (store shapes for mocking) Replace `.todo` entries with real assertions (skeleton, EmptyState micro, UX-14 absence): - UX-03 group (3 tests): 1. `renders folder skeleton rows when loadingRoots is true` — mount AppSidebar with foldersStore.loadingRoots=true (use a setup or component data override), assert `wrapper.findAll('.animate-pulse').length >= 3` within the folders section 2. `renders topics skeleton rows when topicsStore.loading is true` — similar assertion for topics 3. `renders cloud skeleton rows when loadingCloudConnections is true` — similar assertion for cloud - UX-01 sidebar micro (3 tests): 4. `renders in folders section when empty` — mount with all loading=false and empty store arrays, stub EmptyState, assert presence in DOM via component lookup 5. `renders in topics section when empty` — similar 6. `renders in cloud section when empty with #cta router-link` — similar - UX-14 group (3 tests): 7. `template does NOT include a "New" button in the folder section header` — assert no `` near folder section header - Remove the inline new-folder `
` block - Remove the data properties `showNewFolderInput`, `newFolderName`, `newFolderError` - Remove the methods `startNewFolder`, `cancelNewFolder`, `submitNewFolder` - Remove any `nextTick(() => this.$refs.newFolderInputRef?.focus())` or related ref code in mounted/methods 2. Skeleton wiring (UX-03): - Replace each `
Loading…
` placeholder with a `
` skeleton block containing 3 `
` rows (icon + text block, animate-pulse), per the PATTERNS template. - Three locations: folders section, cloud section, topics section. 3. EmptyState wiring (UX-01 sidebar micro): - Folders empty: replace `
No folders yet
` with `` - Topics empty: replace existing text with `` - Cloud empty: replace with: ``` ``` 4. Register EmptyState as a component import: `import EmptyState from '../ui/EmptyState.vue'` + add to `components: { ... }` in the Options API export. Edit `frontend/src/components/layout/AppSidebar.vue`: **Step 1 — Imports:** Add `import EmptyState from '../ui/EmptyState.vue'` near the existing imports. Add `EmptyState` to the `components: { ... }` registration object in the Options API `export default`. **Step 2 — Remove UX-14 elements:** - Delete the entire `` element (current ~lines 75-82) - Delete the entire `
...
` inline new-folder block (current ~lines 87-98) - In the `data()` return, remove the three properties: `showNewFolderInput: false`, `newFolderName: ''`, `newFolderError: ''` - In the `methods: { ... }` object, remove `startNewFolder`, `cancelNewFolder`, `submitNewFolder` - Remove the corresponding template `ref="newFolderInputRef"` if present **Step 3 — Folder section update:** - Replace the `
Loading…
` element with: ```
``` - Replace the `
No folders yet
` with: ``` ``` (Drop the `&& !showNewFolderInput` since the variable no longer exists.) **Step 4 — Cloud section update:** - Replace `
Loading…
` with the same 3-row skeleton (with `key="sk-c-${n}"`). - Replace `
No cloud storage connected
` with: ``` ``` **Step 5 — Topics section update:** - Replace `
Loading…
` with a 3-row skeleton (with `key="sk-t-${n}"`), using `class="px-3 py-1 space-y-1"` for the outer wrapper to match the existing topics indent. - Replace `
No topics yet
` with: ``` ``` No comments. Preserve all other functionality (Topics, Shared, Admin, Settings, sign-out, etc.) untouched.
cd frontend && npm run test -- --run AppSidebar.empty Expected: all 9 tests PASS. - `grep -E "import EmptyState" frontend/src/components/layout/AppSidebar.vue` returns 1 - `grep -E "\\s*New\\s*'` returns 0 (no "New" button) - StorageBrowser.vue invariant: `grep -E "function startNewFolder" frontend/src/components/storage/StorageBrowser.vue` still returns 1 (untouched) - `cd frontend && npm run test -- --run AppSidebar.empty` exits 0 - Full sidebar tests pass: `cd frontend && npm run test -- --run AppSidebar` exits 0 AppSidebar updated; UX-03 + UX-01 (micro) + UX-14 all GREEN; StorageBrowser's own startNewFolder preserved. - `cd frontend && npm run test -- --run AppSidebar.empty` exits 0 - StorageBrowser invariant intact: `grep -E "function startNewFolder" frontend/src/components/storage/StorageBrowser.vue` returns 1 - `grep -E "Loading…" frontend/src/components/layout/AppSidebar.vue` returns 0 (loading text replaced by skeletons) - AppSidebar EmptyState count: `grep -c " The sidebar shows shimmering skeleton rows while loading folders/topics/cloud connections. When loading completes and any section has no items, a compact icon + label appears (with a Settings link for cloud). The inline "New folder" button is gone — folder creation is accessible only from the file manager toolbar, as required by UX-14. Create `.planning/phases/10-ux-interaction/10-07-SUMMARY.md` when done.