Moves phases 08–11 execution artifacts from .planning/phases/ to .planning/milestones/v0.2-phases/ to keep .planning/phases/ clean for the next milestone. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
21 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 10-ux-interaction | 12 | execute | 5 |
|
|
true |
|
|
Per RESEARCH.md §Component Inventory §1, the audit found ~66 <svg> 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
AppIconfrom the correct relative path - Every inline
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="..." /></svg>block (or equivalent) is replaced with<AppIcon name="<assigned-name>" class="<original-classes>" /> - 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
<AppIcon name="dots" />(stroke variant added in 10-01)
<execution_context> @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md </execution_context>
@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 <svg> block by its d attribute, look up the icon name in the AppIcon ICON_PATHS map, then replace.
Example transformation:
<!-- BEFORE -->
<svg class="w-4 h-4 mr-2 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7..." />
</svg>
<!-- AFTER -->
<AppIcon name="tag" class="w-4 h-4 mr-2 shrink-0" />
Special cases:
- Settings dual-path (cog + cogDot) in AppSidebar -> single
<AppIcon name="cog" class="..." />(AppIcon handles the array) - FolderRow dots (fill-based) ->
<AppIcon name="dots" class="w-4 h-4" />(stroke replacement; ICON_PATHS already includes the stroke version per 10-01) - UploadProgress fill-based check/error ->
<AppIcon name="checkCircle" class="..." />/<AppIcon name="exclamationCircle" class="..." /> - 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
<circle>) -> 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 "<svg" <file> at execution time.
Identification process: For each file:
- Read the file
- For each inline
<svg>block, read thedattribute - Look up the matching name in ICON_PATHS (from 10-01)
- Replace the whole
<svg>...</svg>block with<AppIcon name="<name>" class="<original class attribute value>" /> - 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 <script setup> files, the import is enough.
Then, for each inline `<svg>` block, replace as described in <interfaces>:
**StorageBrowser.vue** (approx 6-7 SVGs):
- "New folder" button SVG (d=`M12 4v16m8-8H4`) -> `<AppIcon name="plus" class="w-4 h-4" />`
- Folder row icon (d starting `M3 7a2 2 0 012-2h4l2 2h8...`) -> `<AppIcon name="folder" class="w-4 h-4 text-amber-500" />`
- Inline new-folder row folder icon -> same as above
- File row pencil (rename) -> `<AppIcon name="pencil" class="..." />`
- File row trash (delete) -> `<AppIcon name="trash" class="..." />`
- File row share -> `<AppIcon name="share" class="..." />`
- File row document icon -> `<AppIcon name="document" class="..." />`
- File row folder-move (folderMove) -> `<AppIcon name="folderMove" class="..." />`
**AppSidebar.vue** (approx 10 SVGs):
- chevronRight x2 -> `<AppIcon name="chevronRight" class="..." />` each
- tag (All Topics) -> `<AppIcon name="tag" class="..." />`
- inbox (Shared with me) -> `<AppIcon name="inbox" class="..." />`
- cloud (Cloud section) -> `<AppIcon name="cloud" class="..." />`
- shield (Admin) -> `<AppIcon name="shield" class="..." />`
- cog dual-path (Settings) -> `<AppIcon name="cog" class="..." />` (single tag - AppIcon handles the array)
- logout (Sign out) -> `<AppIcon name="logout" class="..." />`
**AdminSidebar.vue** (approx 6 SVGs): home, users, chartBar, lightBulb, clipboardList, logout. Replace each with the matching AppIcon name preserving the original class attribute.
**TreeItem.vue** (1 SVG): chevronRight -> `<AppIcon name="chevronRight" class="..." />`.
Preserve all existing classes verbatim. Do not change SVG container element types (e.g., if the SVG was inside a `<button>`, the AppIcon stays inside the `<button>`).
Specific notes:
- **FolderRow.vue**: the three-dot menu currently uses `fill="currentColor"` - replace with `<AppIcon name="dots" class="w-4 h-4" />` (stroke variant added in 10-01).
- **FolderDeleteModal.vue**: warning icon -> `<AppIcon name="warning" class="..." />`.
- **DocumentCard.vue**: document + folderMove + trash -> each with matching AppIcon name.
- **DocumentPreviewModal.vue**: close `x` button SVG -> `<AppIcon name="x" class="..." />`. KEEP the loading spinner SVG (it uses `<circle>` and is not in the icon map).
- **SearchBar.vue**: if SearchBar has a search icon inline, replace with `<AppIcon name="search" />`. 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 -> `<AppIcon name="x" class="..." />`.
- **DropZone.vue**: upload icon -> `<AppIcon name="upload" class="..." />`.
- **UploadProgress.vue**: fill-based check + error icons -> `<AppIcon name="checkCircle" />` / `<AppIcon name="exclamationCircle" />`. 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.
For all views: register `AppIcon` in `components: { ... }` if Options API; or only add the import if `<script setup>`.
<success_criteria>
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 <AppIcon name="..." /> at consumer sites - no more copy-paste of <svg ...> blocks. The grep gate guarantees no future drift back to inline SVGs without violating CODE-05.
</success_criteria>