---
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 testsfrontend/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 `
Modify `frontend/src/components/layout/__tests__/AppSidebar.empty.test.js`. Replace each `it.todo(...)` from Task 1's stub set with the real tests above. Use `import { mount } from '@vue/test-utils'`, `import { setActivePinia, createPinia } from 'pinia'`, and stub `router-link` + `EmptyState` + `AppIcon` + `TreeItem` + `FolderTreeItem` + `CloudProviderTreeItem` via `global.stubs`.
Tests fail initially because AppSidebar still has the old structure.
cd frontend && npm run test -- --run AppSidebar.empty
Expected: 9 tests fail (RED).
- File contains exactly 9 `it(...)` tests across 3 describe blocks (UX-03, UX-01, UX-14)
- No `.todo` entries remain
- Tests stub child components via `global.stubs`
- All 9 tests are RED
9 RED tests describe the AppSidebar contract.Task 2: Edit AppSidebar.vue — remove UX-14 elements, add skeleton + EmptyState wiringfrontend/src/components/layout/AppSidebar.vue
- frontend/src/components/layout/AppSidebar.vue (current state)
- frontend/src/components/layout/__tests__/AppSidebar.empty.test.js (failing tests)
- frontend/src/components/ui/EmptyState.vue (interface)
- .planning/phases/10-ux-interaction/10-PATTERNS.md §"AppSidebar.vue"
- .planning/phases/10-ux-interaction/10-RESEARCH.md §"Component Inventory §3" (sidebar micro EmptyState specs)
1. UX-14 removals (script and template):
- Remove `` 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:
```
Settings
```
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 `
` 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.