--- phase: 10-ux-interaction plan: 12 type: execute wave: 5 depends_on: [10-01, 10-06, 10-07, 10-08, 10-09, 10-10, 10-11] files_modified: - frontend/src/components/storage/StorageBrowser.vue - frontend/src/components/layout/AppSidebar.vue - frontend/src/components/admin/AdminSidebar.vue - frontend/src/components/folders/FolderRow.vue - frontend/src/components/folders/FolderTreeItem.vue - frontend/src/components/folders/FolderDeleteModal.vue - frontend/src/components/documents/DocumentCard.vue - frontend/src/components/documents/DocumentPreviewModal.vue - frontend/src/components/documents/SearchBar.vue - frontend/src/components/sharing/ShareModal.vue - frontend/src/components/upload/DropZone.vue - frontend/src/components/upload/UploadProgress.vue - frontend/src/components/ui/TreeItem.vue - frontend/src/components/ui/SearchableModelSelect.vue - frontend/src/components/settings/SettingsCloudTab.vue - frontend/src/components/cloud/CloudFolderTreeItem.vue - frontend/src/components/cloud/CloudProviderTreeItem.vue - frontend/src/views/AccountView.vue - frontend/src/views/CloudStorageView.vue - frontend/src/views/SettingsView.vue - frontend/src/views/admin/AdminUsersView.vue - frontend/src/views/admin/AdminAuditView.vue - frontend/src/views/admin/AdminQuotasView.vue - frontend/src/views/admin/AdminAiView.vue - frontend/src/views/admin/AdminOverviewView.vue autonomous: true requirements: [CODE-05] must_haves: truths: - "All inline blocks (~66 instances across ~29 files) are replaced with calls" - "Each affected file imports AppIcon from the correct relative path" - "Visual rendering is unchanged - same classes carry through to the via $attrs.class" - "The full test suite continues to pass post-migration (no regression)" - "No inline `` blocks remain (except in AppIcon.vue itself, AppSpinner.vue spinner, and UploadProgress.vue fill-based icons if they cannot be swapped)" artifacts: - path: "frontend/src/**/*.vue" provides: "Updated to use AppIcon" key_links: - from: "Each modified .vue file" to: "AppIcon.vue" via: "import AppIcon from /components/ui/AppIcon.vue" pattern: "import AppIcon" --- Complete CODE-05 by replacing every inline `` block in the frontend with an `` call. This is the final wave of Phase 10 because every previous wave can freely modify its files without worrying about icon migration churn, and any new SVGs introduced earlier in the phase are caught here. Per RESEARCH.md §Component Inventory §1, the audit found ~66 `` blocks across ~29 files mapping to ~30 named icons. The full Name -> d-attribute map lives in `AppIcon.vue` (from 10-01). Output: - Every affected file imports `AppIcon` from the correct relative path - Every inline `` block (or equivalent) is replaced with `` - AppSpinner.vue retains its inline spinner SVG (it is not an icon) - UploadProgress.vue fill-based icons are swapped for stroke equivalents (checkCircle / exclamationCircle from AppIcon) - FolderRow.vue's previously fill-based three-dot icon is replaced with `` (stroke variant added in 10-01) @$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/ui/AppIcon.vue **Migration mapping (from RESEARCH.md §Component Inventory §1):** For each file, identify each inline `` block by its `d` attribute, look up the icon name in the AppIcon ICON_PATHS map, then replace. Example transformation: ```html ``` **Special cases:** - Settings dual-path (cog + cogDot) in AppSidebar -> single `` (AppIcon handles the array) - FolderRow dots (fill-based) -> `` (stroke replacement; ICON_PATHS already includes the stroke version per 10-01) - UploadProgress fill-based check/error -> `` / `` - BreadcrumbBar internal chevronRight (added in 10-03) is already AppIcon - no change needed - AppSpinner internal spinner SVG -> KEEP (it is a special animation, not an icon) - DocumentPreviewModal internal spinner SVG (if it uses ``) -> KEEP **Per-file inline SVG count (from RESEARCH.md):** | File | Approx SVG count | Notes | |------|-----------------|-------| | frontend/src/components/storage/StorageBrowser.vue | ~6 | plus, folder (x2), folderMove, pencil, trash, share, document | | frontend/src/components/layout/AppSidebar.vue | ~10 | tag, inbox, cloud, shield, cog (dual-path), logout, chevronRight (x2) | | frontend/src/components/admin/AdminSidebar.vue | ~6 | home, users, chartBar, lightBulb, clipboardList, logout | | frontend/src/components/folders/FolderRow.vue | ~3 | folder, dots, pencil, trash | | frontend/src/components/folders/FolderTreeItem.vue | ~2 | folder, chevronRight | | frontend/src/components/folders/FolderDeleteModal.vue | 1 | warning | | frontend/src/components/documents/DocumentCard.vue | ~3 | document, folderMove, trash | | frontend/src/components/documents/DocumentPreviewModal.vue | 1 | x (plus spinner kept) | | frontend/src/components/sharing/ShareModal.vue | 1 | x | | frontend/src/components/upload/DropZone.vue | 1 | upload | | frontend/src/components/upload/UploadProgress.vue | ~2 | checkCircle, exclamationCircle (fill-swap) | | frontend/src/components/ui/TreeItem.vue | 1 | chevronRight | | frontend/src/components/ui/SearchableModelSelect.vue | ~2 | chevronDown, pencilEdit | | frontend/src/components/settings/SettingsCloudTab.vue | 1 | warning | | frontend/src/components/cloud/CloudFolderTreeItem.vue | ~2 | folder, fileDoc | | frontend/src/components/cloud/CloudProviderTreeItem.vue | 1 | cloud | | frontend/src/views/AccountView.vue | 1 | checkMark | | frontend/src/views/CloudStorageView.vue | 1 | cloud (now handled in 10-08 via EmptyState; verify no other inline svg) | | frontend/src/views/SettingsView.vue | ~3 | checkCircle, exclamationCircle, x (x2) | | frontend/src/views/admin/AdminUsersView.vue | ~3 | copy, check, refresh | | frontend/src/views/admin/AdminAuditView.vue | possibly 0-1 after 10-08 changes | | frontend/src/views/admin/AdminQuotasView.vue | 0-1 | | frontend/src/views/admin/AdminAiView.vue | 0-1 | | frontend/src/views/admin/AdminOverviewView.vue | 0-1 | The numbers are approximate; the actual count comes from `grep -c "` at execution time. **Identification process:** For each file: 1. Read the file 2. For each inline `` block, read the `d` attribute 3. Look up the matching name in ICON_PATHS (from 10-01) 4. Replace the whole `...` block with `` 5. Ensure the file imports AppIcon If an inline SVG's `d` attribute does NOT match any known icon, halt and report it - DO NOT invent a name. Either: (a) Add the missing name+d to ICON_PATHS in AppIcon.vue (and update the AppIcon test if necessary), OR (b) Leave that one inline SVG untouched and note it as an exception in the SUMMARY. **Import path patterns:** - Files under `frontend/src/components/storage/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/layout/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/folders/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/documents/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/cloud/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/sharing/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/upload/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/settings/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/admin/` -> `import AppIcon from '../ui/AppIcon.vue'` - Files under `frontend/src/components/ui/` -> `import AppIcon from './AppIcon.vue'` - Files under `frontend/src/views/` -> `import AppIcon from '../components/ui/AppIcon.vue'` - Files under `frontend/src/views/admin/` -> `import AppIcon from '../../components/ui/AppIcon.vue'` For Options API files, also register: `components: { AppIcon, ... }`. For ` Task 1: Migrate sidebar + top-level layout files (StorageBrowser, AppSidebar, AdminSidebar, TreeItem) frontend/src/components/storage/StorageBrowser.vue, frontend/src/components/layout/AppSidebar.vue, frontend/src/components/admin/AdminSidebar.vue, frontend/src/components/ui/TreeItem.vue - All four files (current state) - frontend/src/components/ui/AppIcon.vue (to know the available names and their d-values) - .planning/phases/10-ux-interaction/10-RESEARCH.md §"Component Inventory §1: SVG Audit" (file-to-icon map) For each file: add the AppIcon import (correct relative path). For Options API files (AppSidebar uses Options API, AdminSidebar likely the same, TreeItem may be either), register `AppIcon` in the `components: { ... }` map. For ` cd frontend && npm run test -- --run; cd frontend && npm run build Expected: full test suite passes; build succeeds. - StorageBrowser.vue: `grep -c "` calls - Full test suite passes - npm run build exits 0 4 sidebar/storage files fully migrated; no inline SVGs remain in any of them. Task 2: Migrate folder + document + upload + sharing components frontend/src/components/folders/FolderRow.vue, frontend/src/components/folders/FolderTreeItem.vue, frontend/src/components/folders/FolderDeleteModal.vue, frontend/src/components/documents/DocumentCard.vue, frontend/src/components/documents/DocumentPreviewModal.vue, frontend/src/components/documents/SearchBar.vue, frontend/src/components/sharing/ShareModal.vue, frontend/src/components/upload/DropZone.vue, frontend/src/components/upload/UploadProgress.vue - All nine files (current state) - frontend/src/components/ui/AppIcon.vue - .planning/phases/10-ux-interaction/10-RESEARCH.md §"Component Inventory §1" (file/icon map) For each file, repeat the migration pattern: add `import AppIcon`, register in components if Options API, replace each inline `` with ``. Specific notes: - **FolderRow.vue**: the three-dot menu currently uses `fill="currentColor"` - replace with `` (stroke variant added in 10-01). - **FolderDeleteModal.vue**: warning icon -> ``. - **DocumentCard.vue**: document + folderMove + trash -> each with matching AppIcon name. - **DocumentPreviewModal.vue**: close `x` button SVG -> ``. KEEP the loading spinner SVG (it uses `` and is not in the icon map). - **SearchBar.vue**: if SearchBar has a search icon inline, replace with ``. If it does not have any inline SVG, this file is a no-op for migration (still add the import only if needed). - **ShareModal.vue**: `x` close button -> ``. - **DropZone.vue**: upload icon -> ``. - **UploadProgress.vue**: fill-based check + error icons -> `` / ``. Drop the `fill="currentColor"` styling - AppIcon uses stroke; visual difference at w-5 h-5 is minor and acceptable per RESEARCH.md Open Question 1. cd frontend && npm run test -- --run; cd frontend && npm run build Expected: tests pass; build succeeds. - For each file: `grep -c "` returns 0 OR 1 (1 is acceptable only for DocumentPreviewModal.vue with the loading spinner) - Specifically: `grep -c "` returns 0 - Every file contains `import AppIcon` (except SearchBar if no SVGs existed there - confirm by reading) - Full test suite passes - npm run build exits 0 9 folder/document/upload/sharing files migrated. Task 3: Migrate cloud + settings + UI utility files frontend/src/components/cloud/CloudFolderTreeItem.vue, frontend/src/components/cloud/CloudProviderTreeItem.vue, frontend/src/components/settings/SettingsCloudTab.vue, frontend/src/components/ui/SearchableModelSelect.vue - All four files (current state) - frontend/src/components/ui/AppIcon.vue - .planning/phases/10-ux-interaction/10-RESEARCH.md §"Component Inventory §1" Apply the migration: - **CloudFolderTreeItem.vue**: folder + fileDoc -> `` / ``. - **CloudProviderTreeItem.vue**: cloud -> ``. - **SettingsCloudTab.vue**: warning -> ``. - **SearchableModelSelect.vue**: chevronDown + pencilEdit -> `` / ``. cd frontend && npm run test -- --run; cd frontend && npm run build Expected: tests pass; build succeeds. - Each file: `grep -c "` returns 0 - Each file imports AppIcon - Test suite + build pass 4 cloud/settings/UI files migrated. Task 4: Migrate view files (AccountView, CloudStorageView, SettingsView, all admin views) frontend/src/views/AccountView.vue, frontend/src/views/CloudStorageView.vue, frontend/src/views/SettingsView.vue, frontend/src/views/admin/AdminUsersView.vue, frontend/src/views/admin/AdminAuditView.vue, frontend/src/views/admin/AdminQuotasView.vue, frontend/src/views/admin/AdminAiView.vue, frontend/src/views/admin/AdminOverviewView.vue - All eight files (current state, after 10-08 modifications) - frontend/src/components/ui/AppIcon.vue - .planning/phases/10-ux-interaction/10-RESEARCH.md §"Component Inventory §1" Apply the migration: - **AccountView.vue**: checkMark -> ``. - **CloudStorageView.vue**: any remaining inline SVG (after 10-08 EmptyState wiring) -> matching AppIcon. - **SettingsView.vue**: checkCircle + exclamationCircle + x (x2) -> matching AppIcons. - **AdminUsersView.vue**: copy + check + refresh -> matching AppIcons. - **AdminAuditView.vue, AdminQuotasView.vue, AdminAiView.vue, AdminOverviewView.vue**: any remaining inline SVGs -> matching AppIcons. If none, this is a no-op (no import needed unless adding it). For all views: register `AppIcon` in `components: { ... }` if Options API; or only add the import if ` cd frontend && npm run test -- --run; cd frontend && npm run build; grep -rE " Expected: tests pass; build succeeds; grep count returns 0 (all stroke-based outline SVGs migrated). - Each view file: `grep -c "` returns 0 - `grep -rE "`). Both have already been validated NOT to use the stroke + viewBox 0 0 24 24 pattern; if either matches the grep above, halt and confirm with the user before proceeding. - npm run build exits 0 - Full test suite passes All view-level files migrated; CODE-05 verifiable by the single grep across the codebase returning 0. - Codebase-wide check: `grep -rE " The frontend bundle has a single source of truth for icon paths. Visually, the app renders identically to before migration. Adding a new icon requires editing ONE map in AppIcon.vue and using `` at consumer sites - no more copy-paste of `` blocks. The grep gate guarantees no future drift back to inline SVGs without violating CODE-05. Create `.planning/phases/10-ux-interaction/10-12-SUMMARY.md` when done. Include the final `grep -rc "