# Technology Stack — DocuVault v0.2: UI Overhaul and Optimization **Milestone:** v0.2 — UI Overhaul and Optimization **Researched:** 2026-06-07 **Scope:** New additions only. The v0.1 stack (FastAPI, Vue 3, Pinia, Vue Router 4, Vite, Tailwind CSS, PostgreSQL, MinIO) is unchanged and not re-researched here. --- ## Existing Stack Baseline (Confirmed, Do Not Change) | Component | Current Version (package.json / requirements.txt) | Notes | |-----------|--------------------------------------------------|-------| | Vue | `^3.4.0` | Must bump to `^3.5.0` (see VueUse note below) | | Vite | `^5.2.0` | Must bump to `^6.0.0` — Vite 8 is latest; skip 8 (too new) | | Tailwind CSS | `^3.4.0` | Stay on v3; v4 is out but requires config rewrite | | Pinia | `^2.1.0` | No change needed | | Vue Router | `^4.3.0` | No change needed | --- ## New Frontend Dependencies ### 1. VueUse — `@vueuse/core` + `@vueuse/integrations` **Recommended:** `@vueuse/core@^14.3.0`, `@vueuse/integrations@^14.3.0` **Confidence:** HIGH (verified from Context7 docs and npm registry) **Why:** VueUse provides three composables this milestone needs, each saving 30-100 lines of custom code that would otherwise require careful browser-compatibility testing: - `useDropZone` — drop-target zones for drag-and-drop file upload (handles `dragenter`/`dragleave`/`drop`, exposes `isOverDropZone` reactive ref, correct `dataTypes` filtering, Safari limitations documented) - `onKeyStroke` — keyboard shortcut registration without manual `addEventListener`/`removeEventListener` lifecycle management - `useSortable` (from `@vueuse/integrations`) — thin wrapper over SortableJS for list/folder reordering, auto-syncs to reactive array **Bundle impact:** `@vueuse/core` unpacked size is ~870 KB but it is fully tree-shakeable — only imported composables are included in the bundle. Each composable is typically 1-3 KB gzipped. This is the correct way to import: ```js import { useDropZone, onKeyStroke } from '@vueuse/core' import { useSortable } from '@vueuse/integrations/useSortable' ``` **Critical version constraint:** VueUse v14.0+ requires `vue@^3.5.0`. The current `package.json` pins `^3.4.0`. Vue 3.5 has no breaking changes for Options API components (confirmed from official Vue blog — purely additive release: reactivity improvements, -56% memory usage). Bump Vue to `^3.5.0` as part of this milestone's first phase. **`@vueuse/integrations` peer deps:** `useSortable` requires `sortablejs@^1` as a peer dependency. Install `sortablejs` alongside. ```bash npm install @vueuse/core@^14.3.0 @vueuse/integrations@^14.3.0 sortablejs@^1.15.7 npm install -D @types/sortablejs ``` **Do NOT use VueUse as a global plugin** (`app.use(VueUse)`) — it doesn't have one. Import composables individually, always. --- ### 2. vue-virtual-scroller — `vue-virtual-scroller` **Recommended:** `vue-virtual-scroller@^3.0.4` **Confidence:** HIGH (verified from Context7 docs and npm registry; published 2026-05-20, actively maintained) **Why:** Document lists can reach hundreds or thousands of entries per user. Without virtual scrolling, rendering all `DocumentCard` components simultaneously degrades scroll performance significantly on mobile. `vue-virtual-scroller` is the canonical Vue 3 virtual list library by Guillaume Chau (Akryum, Vue core team contributor). It ships ESM-only, is Vite-native, and requires Vue 3.3+ (compatible with our 3.5 bump). **Components used:** - `` — fixed item height, highest performance. Use for the main document grid where item height is deterministic. - `` — variable item height. Use only if needed (e.g. list view with text previews of different lengths). **Bundle size:** Unpacked ~461 KB; ESM-only means Rollup tree-shakes unused components. Requires importing its CSS: `import 'vue-virtual-scroller/index.css'`. **Integration note:** Because `RecycleScroller` pools and reuses DOM nodes, every item component must be fully reactive from props alone — no internal `mounted()` side effects that assume a fresh component per item. Options API components that follow the props-down / events-up pattern (as required by the existing architecture) are fully compatible. ```bash npm install vue-virtual-scroller@^3.0.4 ``` --- ### 3. Drag-and-Drop for File Upload — Native HTML5 + VueUse `useDropZone` **Recommended:** No additional library. Use `useDropZone` from `@vueuse/core` (already added above). **Confidence:** HIGH **Why not a dedicated library:** The drag-and-drop requirement for this milestone is drop-zone file upload (files dragged from OS to a browser area). `useDropZone` covers this completely. Dedicated upload libraries like `dropzone-vue` or `vue-file-uploader` are either poorly maintained, opinionated about UI, or duplicate what the existing upload flow already does. The existing backend upload endpoint and progress tracking are already implemented — adding a library that wraps both drop detection and upload would require replacing working code. **For folder/list reordering** (drag document into a different folder), use `useSortable` from `@vueuse/integrations` (already added above via SortableJS). SortableJS handles this precisely: it is a low-level, pure-DOM drag-sort library with no Vue-specific assumptions. **Do NOT use `vue-draggable-plus` (0.6.1, last published 2026-01-11):** It wraps SortableJS but adds a Vue component abstraction layer that conflicts with the project's data-provider view pattern. It also adds bundle overhead that `useSortable` avoids. The last publish date of January 2026 is acceptable for a stable library, but there is no reason to prefer it over the VueUse integration that is already in the bundle. --- ### 4. Keyboard Shortcuts — VueUse `onKeyStroke` **Recommended:** `onKeyStroke` from `@vueuse/core` (already added). No additional library. **Confidence:** HIGH **Why no dedicated library:** Libraries like `vue-shortkey` or `hotkeys-js` exist but are unnecessary overhead. `onKeyStroke` from VueUse handles: - Single key listening: `onKeyStroke('/', handler)` (focus search) - Modifier combos: check `event.ctrlKey` / `event.metaKey` inside the handler - Automatic cleanup when the component is unmounted (it wraps `addEventListener`/`removeEventListener` with `onUnmounted`) For a document manager, typical shortcuts are: `/` (search focus), `Escape` (close modal/panel), `Delete` (delete selected), `Enter` (open/confirm). All fit `onKeyStroke` with no wrapper library. **Implementation pattern:** ```js // In setup() or a composable import { onKeyStroke } from '@vueuse/core' onKeyStroke('/', (e) => { e.preventDefault() searchInput.value?.focus() }) ``` --- ### 5. Loading Skeletons — Pure Tailwind CSS **Recommended:** No library. Use `animate-pulse` utility with placeholder shapes. **Confidence:** HIGH **Why no library:** Skeleton loaders in this app are simple rectangular placeholders — cards, list rows, and a few text lines. Tailwind's `animate-pulse` combined with `bg-gray-200 dark:bg-gray-700` rounded shapes is sufficient and produces zero additional bundle weight. A skeleton library (`vue3-skeleton`, etc.) would add a dependency for something that is 5 lines of Tailwind HTML per component. **Recommended pattern for a document card skeleton:** ```html
``` For a shimmer effect (more polished than pulse), use a CSS `@keyframes` background-position animation — still zero JS dependency. Only add a library if shimmer is required across 10+ distinct skeleton shapes that need consistent management. --- ### 6. Tailwind CSS Plugins **Recommended:** `@tailwindcss/forms@^0.5.11` **Confidence:** HIGH (official Tailwind Labs plugin, 4,500+ GitHub stars, supports both v3 and v4) **Why `@tailwindcss/forms`:** DocuVault has several form-heavy screens (login, registration, upload dialog, admin user management, cloud credential entry). Browser defaults for ``, `