--- phase: 10-ux-interaction plan: "03" subsystem: frontend/ui tags: [breadcrumb, navigation, vue, tdd, options-api] dependency_graph: requires: [] provides: [BreadcrumbBar.vue, AppIcon.vue] affects: [StorageBrowser.vue, FileManagerView.vue, CloudFolderView.vue, admin views, settings views] tech_stack: added: [] patterns: [options-api, computed-visibleSegments, AppIcon-separator, tdd-red-green] key_files: created: - frontend/src/components/ui/BreadcrumbBar.vue - frontend/src/components/ui/AppIcon.vue - frontend/src/components/ui/__tests__/BreadcrumbBar.test.js modified: [] decisions: - "Options API chosen for BreadcrumbBar per CLAUDE.md convention (despite FolderBreadcrumb using script setup)" - "AppIcon.vue created in worktree as Rule-3 dependency fix (plan 10-01 creates it in another wave-0 agent)" - "BreadcrumbBar separator uses AppIcon not inline SVG — icon centralization paradigm enforced" metrics: duration: "~5 minutes" completed: "2026-06-15T18:13:50Z" tasks_completed: 2 tasks_total: 2 files_created: 3 files_modified: 0 --- # Phase 10 Plan 03: BreadcrumbBar Component Summary **One-liner:** Shared breadcrumb component with showRoot/rootLabel props, ellipsis collapse for >4 segments, and static no-id segment support for admin/settings views. ## Tasks Completed | Task | Name | Commit | Files | |------|------|--------|-------| | 1 | Create BreadcrumbBar.test.js (RED) | b6ea858 | frontend/src/components/ui/__tests__/BreadcrumbBar.test.js | | 2 | Implement BreadcrumbBar.vue (GREEN) | 7e584e0 | frontend/src/components/ui/BreadcrumbBar.vue, frontend/src/components/ui/AppIcon.vue | ## What Was Built `BreadcrumbBar.vue` is a generalized breadcrumb component that replaces `FolderBreadcrumb.vue` across all views. Key capabilities over the original: - **`showRoot` prop** (Boolean, default true): When false, omits the root button entirely — needed for admin/settings views (`Admin > Users`, `Settings > Account`) that have no "Home" concept. - **`rootLabel` prop** (String, default 'Home'): Configurable root text — file manager uses 'Home', cloud view uses 'Cloud'. - **Static segments** (no `id`): Segments without an `id` render as non-clickable `` elements. Admin views pass static breadcrumb labels that should not navigate anywhere. - **`{ id?, label }` shape**: Changed from FolderBreadcrumb's `{ id, name }` to `{ id?, label }`. Wave 1 (plan 10-06) maps existing `{ id, name }` to `{ id, label: name }` at call sites. - **AppIcon separator**: Uses `` instead of inline SVG — enforces the new icon centralization paradigm from plan 10-01. - **Ellipsis collapse**: `>4 segments` collapses to `[first, ellipsis, ...last_two]` — carried from FolderBreadcrumb. ## Test Coverage 10 Vitest unit tests, all green: 1. Renders rootLabel button when showRoot=true 2. No button rendered when showRoot=false 3. Root click emits navigate(null) 4. Last segment is non-clickable span 5. Intermediate segment click emits navigate(segment.id) 6. No-id segments render as plain text (no buttons) 7. >4 segments collapse to first + ellipsis + last two 8. rootLabel defaults to 'Home' 9. Custom rootLabel 'Cloud' renders correctly 10. chevronRight AppIcon separator present ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] AppIcon.vue missing in worktree** - **Found during:** Task 2 (implementing BreadcrumbBar.vue which imports AppIcon) - **Issue:** `frontend/src/components/ui/AppIcon.vue` does not exist in this worktree. Plan 10-01 creates AppIcon in a parallel wave-0 agent. Without AppIcon, the BreadcrumbBar import would fail at test time. - **Fix:** Created `AppIcon.vue` in the worktree using the full implementation from PATTERNS.md. Identical to what plan 10-01 will produce. When the wave merges, git will show no conflict (same content). - **Files modified:** `frontend/src/components/ui/AppIcon.vue` (created) - **Commit:** 7e584e0 ## Known Stubs None. BreadcrumbBar is complete and self-contained. It emits `navigate` events; the caller handles routing. ## Threat Flags None. BreadcrumbBar is a pure presentational component — no network requests, no auth, no user data stored. Segment labels come from trusted store data (folder names, view titles) and are rendered via Vue template interpolation (auto-escaped, no XSS risk). ## Self-Check: PASSED - [x] `frontend/src/components/ui/__tests__/BreadcrumbBar.test.js` exists - [x] `frontend/src/components/ui/BreadcrumbBar.vue` exists - [x] `frontend/src/components/ui/AppIcon.vue` exists - [x] Commit b6ea858 exists (RED phase) - [x] Commit 7e584e0 exists (GREEN phase) - [x] All 10 tests pass (`./node_modules/.bin/vitest run BreadcrumbBar` — 10/10) - [x] `name: 'BreadcrumbBar'` present in BreadcrumbBar.vue - [x] `rootLabel` appears >= 2 times in BreadcrumbBar.vue - [x] `showRoot` appears >= 3 times in BreadcrumbBar.vue - [x] `