From c84dcb77c15adbdc2980c8a5ae840180e7193af0 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Sun, 14 Jun 2026 22:04:12 +0200 Subject: [PATCH] docs(phase-10): research UX & interaction --- .../phases/10-ux-interaction/10-RESEARCH.md | 923 ++++++++++++++++++ 1 file changed, 923 insertions(+) create mode 100644 .planning/phases/10-ux-interaction/10-RESEARCH.md diff --git a/.planning/phases/10-ux-interaction/10-RESEARCH.md b/.planning/phases/10-ux-interaction/10-RESEARCH.md new file mode 100644 index 0000000..6b7025d --- /dev/null +++ b/.planning/phases/10-ux-interaction/10-RESEARCH.md @@ -0,0 +1,923 @@ +# Phase 10: UX & Interaction — Research + +**Researched:** 2026-06-14 +**Domain:** Vue 3 Options API / Composition API hybrid — frontend UX patterns +**Confidence:** HIGH (all findings grounded in direct source reading of the actual component files) + +--- + + +## User Constraints (from CONTEXT.md) + +### Locked Decisions + +**Toast Notifications (UX-10)** +- D-01: Position: bottom-right, stacking upward from the corner. +- D-02: Visual differentiation: colored left-border accent + inline icon per type. Green/success, red/error, amber/warning, blue/info. Toast body background white/neutral. +- D-03: Injection: `ToastContainer.vue` uses ``. +- D-04: The `show(message, type, duration)` signature is locked from Phase 8's stub. Phase 10 implements rendering without changing the signature or any Phase 8 call sites. + +**Empty States (UX-01)** +- D-05: Each context gets its own icon from the existing Heroicons-style set (stroke-based 24×24 viewBox). +- D-06: `EmptyState.vue` takes explicit props: `icon` (SVG path string or AppIcon name), `headline` (string), `subtext` (string). +- D-07: CTA is an optional named `#cta` slot. EmptyState.vue renders nothing where slot is empty. + +**AppIcon SVG Centralization (CODE-05)** +- D-08: AppIcon.vue uses a `name → SVG path string` map. No new dependency. +- D-09: Outline/stroke only — no `variant` prop, no solid variant. +- D-10: Prop interface: ``. `class` forwarded to outer ``. Unknown names log a warning in dev mode and render nothing. + +**BreadcrumbBar (UX-12)** +- D-11: Props-driven — every view computes its own `segments` array and passes it to `BreadcrumbBar.vue`. +- D-12: `BreadcrumbBar.vue` emits `@navigate(index)` — parent handles navigation. Last segment is non-clickable plain text. +- D-13: Admin/settings/topics views provide static `segments` computed property. File manager and cloud folder views use folder store `breadcrumb` array. + +**Keyboard Shortcuts (UX-05 through UX-08)** +- D-14: Global `keydown` listener in `mounted()` / `beforeUnmount()`. Guard: `['INPUT','TEXTAREA','SELECT'].includes(document.activeElement?.tagName) || document.activeElement?.isContentEditable` → early return. +- D-15: `/` → focus search bar; `Escape` → close modals + clear search; `U` → trigger upload file picker; `N` → start new folder inline input. + +**Drag-and-Drop (UX-09, UX-11)** +- D-16: OS drop overlay: `dataTransfer.types.includes('Files')` detection. Overlay attached at `window`/`document` level, not inside `StorageBrowser`. +- D-17: Drag-to-move drop highlight: `ring-2 ring-inset ring-amber-300` on valid folder targets. +- D-18: `DocumentCard.vue` dedicated drag handle element to prevent `dragend`-then-`click` navigation. + +### Claude's Discretion + +- Icon name assignments in AppIcon.vue's internal map (researcher resolves below) +- Exact icon choices for each EmptyState context (researcher resolves below) +- Keyboard shortcut global listener architectural home (researcher resolves below) +- Exact query/store plumbing for `U` shortcut to reach upload input ref (researcher resolves below) +- Dropdown/modal clipping audit (researcher resolves below) + +### Deferred Ideas (OUT OF SCOPE) + +None — discussion stayed within phase scope. + + + +## Phase Requirements + +| ID | Description | Research Support | +|----|-------------|------------------| +| UX-01 | EmptyState.vue across 7+ zero-content contexts | Component Inventory §3 maps all contexts | +| UX-02 | StorageBrowser 5-col skeleton grid during loading | Architecture Patterns §Skeleton Pattern | +| UX-03 | Sidebar folder tree + topics skeleton during loading | Architecture Patterns §Skeleton Pattern | +| UX-04 | Admin user table + audit log table skeleton rows | Architecture Patterns §Skeleton Pattern | +| UX-05 | `/` focuses search bar (no input focused) | Keyboard Shortcuts section | +| UX-06 | `Escape` closes any open modal + clears search | Keyboard Shortcuts section | +| UX-07 | `U` triggers file upload picker | Keyboard Shortcuts section; Upload Input Ref Chain | +| UX-08 | `N` starts new folder inline input | Keyboard Shortcuts section; New-Folder Trigger Chain | +| UX-09 | OS drag-onto-window → full-screen overlay → upload | Drag-and-Drop section | +| UX-10 | Toast notification system — implement Phase 8 stub | Toast System section | +| UX-11 | Drag-to-move end-to-end wiring + ring highlight | Drag-to-Move Current State section | +| UX-12 | Shared BreadcrumbBar.vue across all views | BreadcrumbBar Extraction section | +| UX-13 | Dropdown viewport-edge clipping fixes | Component Inventory §2 | +| UX-14 | Remove sidebar "New" folder button | AppSidebar.vue analysis | +| CODE-05 | Centralize ~66 inline SVGs into AppIcon.vue | Component Inventory §1 (full SVG audit) | + + +--- + +## Summary + +Phase 10 is a pure frontend UX phase. The backend is untouched. Every deliverable is a Vue component, store, or directive change. The codebase has been directly audited for this research document — all findings are from reading source files, not from training-data assumptions. + +The key findings: (1) `StorageBrowser.vue` already has ~80% of drag-to-move implemented — folder `@dragover` / `@drop` handlers exist, `draggingFile` ref is tracked, and `ring-2 ring-inset ring-amber-300` highlight is already wired; the missing piece is that `emit('file-move')` succeeds but the drop from OS files (UX-09) is entirely separate. (2) `FolderBreadcrumb.vue` already exists as a component — `BreadcrumbBar.vue` (UX-12) renames and universalizes it, adding static segments support for admin/settings views. (3) `AppIcon.vue` is new; the SVG audit found **66 `` elements across 29 files**, with **32 distinct path strings** mapping to **21 named icons**. (4) The folder picker dropdown in both `StorageBrowser.vue` and `DocumentCard.vue` is the primary clipping risk; `SearchableModelSelect.vue` already uses `` with `getBoundingClientRect()` and is the correct reference pattern. (5) App.vue uses ` +``` + +### Global keydown handler in App.vue (Composition API) + +```javascript +// Source: direct audit of App.vue (uses