Files
kite/.planning/milestones/v0.2-phases/10-ux-interaction/10-03-PLAN.md
T
curo1305andClaude Sonnet 4.6 123ae5b29b chore: archive v0.2 phase directories to milestones/v0.2-phases/
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>
2026-06-17 14:34:52 +02:00

11 KiB
Raw Blame History

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 03 execute 0
frontend/src/components/ui/BreadcrumbBar.vue
frontend/src/components/ui/__tests__/BreadcrumbBar.test.js
true
UX-12
truths artifacts key_links
BreadcrumbBar renders the rootLabel as the first clickable segment when showRoot is true
BreadcrumbBar does NOT render the root segment when showRoot is false (admin/settings views)
The last segment is always rendered as plain non-clickable text
Segments without an id render as plain text (admin static segments)
Clicking an intermediate segment emits navigate(segment.id); clicking root emits navigate(null)
>4 segments collapse to first + ellipsis + last two
path provides
frontend/src/components/ui/BreadcrumbBar.vue Shared breadcrumb component used by file manager, cloud, admin, settings views
path provides
frontend/src/components/ui/__tests__/BreadcrumbBar.test.js BreadcrumbBar unit tests
from to via pattern
BreadcrumbBar.vue AppIcon.vue import for chevronRight separator <AppIcon name="chevronRight"
Create `frontend/src/components/ui/BreadcrumbBar.vue` — a shared breadcrumb component that generalizes `FolderBreadcrumb.vue` to also serve admin, settings, and topics views. The existing `FolderBreadcrumb.vue` will be deleted in Wave 1 (plan 10-06) after BreadcrumbBar is wired everywhere.

Purpose: Per D-11/D-12/D-13, every view computes its own segments array. Admin views (e.g. Admin Users) and settings (Settings Account) need static segments without a "Home" root. File manager and cloud views use folder store breadcrumb data with a "Home" or "Cloud" root.

Output: BreadcrumbBar.vue (Options API, props segments/rootLabel/showRoot, emits navigate) + Vitest unit tests adapted from the existing FolderBreadcrumb tests.

<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/folders/FolderBreadcrumb.vue @frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js Per D-11, D-12, D-13 (CONTEXT.md): - Props: - `segments` (Array, default []) — array of `{ id?, label }` objects - Items without `id` render as plain non-clickable text (admin static segments) - Last item is ALWAYS plain non-clickable text regardless of `id` - `rootLabel` (String, default 'Home') — text for the root button when showRoot=true - `showRoot` (Boolean, default true) — when false, omit the root button entirely - Emits: `navigate` with `segment.id` (intermediate click) or `null` (root click) - Last segment: plain ``, no click handler - >4 segments: collapse pattern `[first, {id:'ellipsis', label:'…'}, ...last_two]`

Reference implementation (FolderBreadcrumb.vue):

  • Uses <script setup> (we will use Options API per CLAUDE.md for THIS new component — exception in PATTERNS.md says BreadcrumbBar may use script setup since it replaces a setup component; pick Options API anyway for consistency with EmptyState/AppIcon)
  • Renders <nav aria-label> > <ol> > <li> segments

Segment shape change:

  • FolderBreadcrumb uses { id, name } — BreadcrumbBar uses { id?, label }
  • Wave 1 plans will map {id, name}{id, label: name} at the call sites
Task 1: Create BreadcrumbBar.test.js with failing tests frontend/src/components/ui/__tests__/BreadcrumbBar.test.js - frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js (reference test patterns) - frontend/src/components/folders/FolderBreadcrumb.vue (current behavior reference) - .planning/phases/10-ux-interaction/10-PATTERNS.md §"BreadcrumbBar.vue" - Test 1: `renders rootLabel button when showRoot=true` — mount with rootLabel='Home', segments=[], assert wrapper.find('button').text() === 'Home' - Test 2: `does NOT render root button when showRoot=false` — mount with showRoot=false, segments=[{label: 'Users'}], assert wrapper.findAll('button').length === 0 - Test 3: `clicking root button emits navigate(null)` — mount default with empty segments, click first button, assert emitted.navigate[0] === [null] - Test 4: `last segment renders as a non-clickable ` — mount with segments=[{id:'a', label:'A'}, {id:'b', label:'B'}], assert text contains 'B' AND wrapper.findAll('button').filter(b => b.text() === 'B').length === 0 - Test 5: `clicking intermediate segment emits navigate(segment.id)` — mount with segments=[{id:'r1', label:'Root'}, {id:'f1', label:'Test'}], click the 'Root' button, assert emitted.navigate[0] === ['r1'] - Test 6: `segments without id render as plain text even when intermediate` — mount with segments=[{label:'Admin'}, {label:'Users'}], showRoot=false, assert NO buttons exist (both render as spans) - Test 7: `>4 segments collapse to first + ellipsis + last two` — mount with 5 segments, assert text contains the first segment label, '…', and the last 2 labels but NOT segments 2-3 - Test 8: `rootLabel defaults to "Home"` — mount with no rootLabel prop, assert first button text === 'Home' - Test 9: `custom rootLabel "Cloud" renders correctly` — mount with rootLabel='Cloud', assert first button text === 'Cloud' - Test 10: `renders chevronRight separator between segments` — mount with segments=[{id:'a', label:'A'}, {id:'b', label:'B'}] and stubs: { AppIcon: true }, assert AppIcon stubs are present (count >= 1) Create `frontend/src/components/ui/__tests__/BreadcrumbBar.test.js`. Adapt the test style from `frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js`. Stub AppIcon via `global: { stubs: { AppIcon: true } }`. Use the segment shape `{ id, label }` (NOT `{ id, name }`). Write all 10 tests above. Tests fail until Task 2. cd frontend && npm run test -- --run BreadcrumbBar Expected: 10 tests collected; all fail (RED). - File `frontend/src/components/ui/__tests__/BreadcrumbBar.test.js` exists with 10 `it(...)` blocks - Tests use segment shape `{ id, label }` exclusively - Running `cd frontend && npm run test -- --run BreadcrumbBar` shows 10 failing tests 10 failing tests in place describing the BreadcrumbBar contract. Task 2: Implement BreadcrumbBar.vue frontend/src/components/ui/BreadcrumbBar.vue - frontend/src/components/ui/__tests__/BreadcrumbBar.test.js (failing tests) - frontend/src/components/folders/FolderBreadcrumb.vue (reference template — lines 1-44) - .planning/phases/10-ux-interaction/10-PATTERNS.md §"BreadcrumbBar.vue" - Options API component `BreadcrumbBar`, registers `AppIcon` from `./AppIcon.vue` - Props: `segments` (Array, default []), `rootLabel` (String, default 'Home'), `showRoot` (Boolean, default true) - Emits: `['navigate']` - Computed `visibleSegments`: if `segments.length > 4` returns `[segments[0], { id: 'ellipsis', label: '…' }, ...segments.slice(-2)]`; else returns `segments` - Template renders `
    ` - When `showRoot`: render the root `
  1. {{ rootLabel }}
  2. ` - For each segment in visibleSegments with index: - Separator `
  3. ` shown only when there is something to the left (showRoot OR idx > 0) - If `segment.id === 'ellipsis'`: `
  4. ` - If `idx === visibleSegments.length - 1`: `
  5. {{ segment.label }}
  6. ` - Else if `segment.id`: `
  7. {{ segment.label }}
  8. ` - Else: `
  9. {{ segment.label }}
  10. ` (no id, no click) Create `frontend/src/components/ui/BreadcrumbBar.vue` using Options API. Import AppIcon from `./AppIcon.vue`. Implement exactly the template described in the behavior block. Match the FolderBreadcrumb visual style (text-indigo-600, hover:underline for clickable; text-gray-900 font-medium for the last segment; text-gray-400 for separator). Use `` for separators (NO inline svg — this is the new icon centralization paradigm). Skip the separator before the first segment when `!showRoot`. No comments inside the file. cd frontend && npm run test -- --run BreadcrumbBar Expected: all 10 tests PASS. - File `frontend/src/components/ui/BreadcrumbBar.vue` exists - File imports AppIcon from `./AppIcon.vue` - File contains `name: 'BreadcrumbBar'` - Template contains `` - All 10 tests pass - File uses Options API BreadcrumbBar.vue implemented; 10 tests green. - `cd frontend && npm run test -- --run BreadcrumbBar` exits 0 with 10 passing tests - `grep -E "name:\\s*'BreadcrumbBar'" frontend/src/components/ui/BreadcrumbBar.vue` returns 1 match - `grep -E "rootLabel" frontend/src/components/ui/BreadcrumbBar.vue` returns ≥ 2 matches (prop + template) - `grep -E "showRoot" frontend/src/components/ui/BreadcrumbBar.vue` returns ≥ 2 matches - `grep -E "

    <success_criteria> BreadcrumbBar.vue is ready to replace FolderBreadcrumb.vue everywhere. Wave 1 plan 10-06 will swap the import in StorageBrowser.vue, update FileManagerView/CloudFolderView to map breadcrumb to {id, label}, wire admin/settings views to pass static segments, and delete FolderBreadcrumb.vue. </success_criteria>

    Create `.planning/phases/10-ux-interaction/10-03-SUMMARY.md` when done.