diff --git a/.planning/phases/11-visual-design-responsive-layout-cleanup/11-03-SUMMARY.md b/.planning/phases/11-visual-design-responsive-layout-cleanup/11-03-SUMMARY.md new file mode 100644 index 0000000..597c9e6 --- /dev/null +++ b/.planning/phases/11-visual-design-responsive-layout-cleanup/11-03-SUMMARY.md @@ -0,0 +1,131 @@ +--- +phase: 11-visual-design-responsive-layout-cleanup +plan: 3 +subsystem: frontend/responsive +tags: [responsive, layout, drawer, touch-targets, RESP-01, RESP-02, RESP-03, RESP-05] +dependency_graph: + requires: [11-02] + provides: [responsive-user-shell, responsive-admin-shell, responsive-storage-rows, touch-targets] + affects: + - frontend/src/App.vue + - frontend/src/layouts/AdminLayout.vue + - frontend/src/components/storage/StorageBrowser.vue +tech_stack: + added: [] + patterns: + - "Hamburger button + slide-in overlay drawer with Teleport backdrop (translate-x-0/-translate-x-full)" + - "Drawer state owned by layout root (App.vue / AdminLayout.vue), not sidebar component (D-04/D-05)" + - "Route-change watcher closes drawer automatically on navigation" + - "Responsive grid-cols variants: mobile base, sm (+modified), md (all 5 columns)" + - "Touch target floor: min-w-[36px] min-h-[36px] on action buttons" +key_files: + created: [] + modified: + - frontend/src/App.vue + - frontend/src/layouts/AdminLayout.vue + - frontend/src/components/storage/StorageBrowser.vue + - frontend/src/__tests__/keyboard.test.js + - frontend/src/components/storage/__tests__/StorageBrowser.skeleton.test.js +decisions: + - "Drawer state in App.vue ref (not Pinia, not AppSidebar) — satisfies D-04/D-05 pitfall constraint" + - "Backdrop teleported to via — consistent with Phase 10 modal/toast pattern" + - "Grid templates use mobile-first responsive variants instead of a fixed 5-column layout — prevents horizontal overflow at 375px" + - "Touch targets applied via min-w/min-h classes at all breakpoints, removed with md:min-w-0 md:min-h-0 at desktop — desktop appearance unchanged" +metrics: + duration_minutes: 9 + tasks_completed: 8 + files_created: 0 + files_modified: 5 + completed_date: "2026-06-16" +--- + +# Phase 11 Plan 3: Responsive Shells & Storage Rows Summary + +Implemented mobile-first responsive shells for both user and admin layouts using hamburger-triggered slide-in overlay drawers, and made StorageBrowser rows fit small viewports without horizontal overflow. + +## What Was Built + +### Tasks 1-3 — App.vue: user layout responsive shell (RESP-01) + +`frontend/src/App.vue` updated: + +- **Drawer state:** `drawerOpen = ref(false)` owned by `App.vue` — satisfies D-04/D-05 constraint (never put in `AppSidebar`). +- **Route-change close:** `watch(() => route.fullPath, ...)` sets `drawerOpen.value = false` on every navigation so link taps auto-close the drawer. +- **Mobile header:** `
` contains the hamburger button (`data-test="hamburger-btn"`) and the DocuVault wordmark. Only shown below `lg`. +- **Backdrop:** `` wraps a semi-transparent overlay `
` that appears when `drawerOpen` is true and calls `drawerOpen = false` on click. Uses `data-test="drawer-backdrop"`. +- **Sidebar wrapper:** `fixed inset-y-0 left-0 z-50` positioning for mobile, `lg:static lg:z-auto lg:translate-x-0` for desktop. Transition: `translate-x-0` (open) / `-translate-x-full` (closed) via `transition-transform duration-200`. Attribute `data-test="app-sidebar-wrapper"`. +- **Main content:** `pt-[53px] lg:pt-0` offset on `
` so mobile content doesn't hide under the fixed header. + +### Task 4 — AdminLayout.vue: admin layout responsive shell (RESP-05) + +`frontend/src/layouts/AdminLayout.vue` mirrors the user layout pattern exactly: + +- `drawerOpen = ref(false)` + `watch(() => route.fullPath, ...)` for auto-close on navigation. +- Mobile header shows "DocuVault" + "Admin" label with `data-test="admin-hamburger-btn"`. +- Teleport backdrop with `data-test="admin-drawer-backdrop"`. +- Sidebar wrapper with `data-test="admin-sidebar-wrapper"` and identical transition classes. +- `useRoute` import added; no `useRouter` needed (AdminLayout itself doesn't navigate). + +### Tasks 5-6 — StorageBrowser.vue: responsive grid and touch targets (RESP-02, RESP-03) + +`frontend/src/components/storage/StorageBrowser.vue` updated: + +**Responsive grid templates** (replaces fixed `grid-cols-[2rem_1fr_6rem_8rem_6rem]` everywhere): + +| Breakpoint | Grid template | Visible columns | +|---|---|---| +| Default (< sm, 375px) | `grid-cols-[2rem_1fr_6rem]` | icon, name, actions | +| sm (640px+) | `sm:grid-cols-[2rem_1fr_8rem_6rem]` | + modified date | +| md (768px+) | `md:grid-cols-[2rem_1fr_6rem_8rem_6rem]` | + size | + +Applied to: list header row, new-folder input row, folder rows, file rows, skeleton rows. + +Added `data-test="list-header"` to the column header row for testability. + +**Touch targets** (RESP-03, satisfies 36px minimum): + +All inline action buttons (Rename, Delete for folders; Share, Move, Delete for files) now have: +- `min-w-[36px] min-h-[36px]` — enforces 36×36px minimum hit area on mobile +- `md:min-w-0 md:min-h-0` — removes the override at desktop so padding-only sizing applies +- `flex items-center justify-center` — keeps icon centered within the larger target + +### Task 7 — Tests + +**`frontend/src/components/storage/__tests__/StorageBrowser.skeleton.test.js`** updated: + +- Replaced old `grid-cols-[2rem_1fr_6rem_8rem_6rem]` assertion (now broken by responsive refactor) with two tests: mobile base class `grid-cols-[2rem_1fr_6rem]` and md breakpoint class `md:grid-cols-[2rem_1fr_6rem_8rem_6rem]`. +- Added new `RESP-02/RESP-03` describe block (8 tests): list header mobile/md classes, folder row, file row, `hidden md:block` size column, `hidden sm:block` modified column, file action button `min-w-[36px]`/`min-h-[36px]`, folder action button touch targets. + +**`frontend/src/__tests__/keyboard.test.js`** extended: + +- Added `RESP-01: App drawer` describe (2 tests): hamburger open/backdrop-close behavior via stub component; route-change watcher closes drawer. +- Added `RESP-05: AdminLayout drawer` describe (3 tests): admin hamburger renders, admin backdrop-close, admin route-change watcher. +- `afterEach` import added; `nextTick` import added. + +## Verification + +- `npm test`: 30 test files, 233 tests pass (219 baseline + 14 new from this plan) +- `npm run build`: succeeds — 5 JS chunks + main bundle, no new errors + +## Deviations from Plan + +None — plan executed exactly as written. + +## Known Stubs + +None. + +## Threat Flags + +None — no network endpoints, auth paths, or schema changes in this plan. All changes are frontend layout/presentation only. + +## Self-Check: PASSED + +- `frontend/src/App.vue`: modified — hamburger header + drawer + Teleport backdrop +- `frontend/src/layouts/AdminLayout.vue`: modified — admin responsive shell +- `frontend/src/components/storage/StorageBrowser.vue`: modified — responsive grid + touch targets +- `frontend/src/__tests__/keyboard.test.js`: modified — drawer tests added +- `frontend/src/components/storage/__tests__/StorageBrowser.skeleton.test.js`: modified — responsive assertions +- Commit `d914761` exists in git log: confirmed +- All 30 test files pass: confirmed +- Build succeeds: confirmed diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 6c0dd2a..f71e86f 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -2,8 +2,41 @@
- -
+ +
+ + DocuVault +
+ + + +
+
+ + +
+ +
+ +
@@ -12,7 +45,7 @@