Files
kite/.planning/phases/11-visual-design-responsive-layout-cleanup/11-03-SUMMARY.md
T

132 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 <body> via <Teleport to='body'> — 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:** `<header class="lg:hidden fixed ...">` contains the hamburger button (`data-test="hamburger-btn"`) and the DocuVault wordmark. Only shown below `lg`.
- **Backdrop:** `<Teleport to="body">` wraps a semi-transparent overlay `<div>` 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 `<main>` 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