Drag-reorderable tile grid with per-tile width control + view-scoped
persistence. Native HTML5 drag — zero runtime deps (no @dnd-kit).
──────────────────────────────────────────────────────────────────
Module surface
──────────────────────────────────────────────────────────────────
<Workspace tiles storageKey persistence? columns? readOnly?>
Wave 13.F.1 + .2
- Native HTML5 drag-and-drop (draggable + dragover + drop)
- role=grid + per-cell role=gridcell + tabIndex=0
- Keyboard shortcuts on focused tile:
← / → resize span down/up (clamped 1..columns)
↑ / ↓ move tile up/down by one slot
- Per-tile 1/2/3/4 size buttons (suppressed in readOnly)
- Drop target gets dashed accent outline
- Reset-layout CTA (suppressed in readOnly)
useWorkspaceLayout(tiles, { storageKey, persistence })
- move(from, to) / resize(id, span) / reset()
- hydrated flag — true once initial load resolves
- One-shot load on mount, save on every change (post-hydration)
reconcile(layout, tiles) · exported pure fn
- Drops entries referencing removed tiles
- Appends new tiles in registry order with defaultSpan fallback
- Used by the hook on every tile-registry change
(defensive against schema drift between releases)
localStoragePersistence · default; SSR-safe (returns null when
window is absent)
──────────────────────────────────────────────────────────────────
Quality gates
──────────────────────────────────────────────────────────────────
✓ 10/10 tests passing
- reconcile: 3 cases (drop unknown / append new / preserve order)
- hook: 4 cases (hydrate defaults / move / resize / reset)
- component: 3 cases (renders cells / keyboard resize / readOnly)
✓ tsc build clean
──────────────────────────────────────────────────────────────────
Roadmap (lands in subsequent commit)
──────────────────────────────────────────────────────────────────
13.F.1 Drag-resize tiles
13.F.2 Saved views per route + persistence layer
Showcase /futurism/workspace (MAG.6) lands in the paired showcase
commit.
3 lines
130 B
TypeScript
3 lines
130 B
TypeScript
import { defineConfig } from 'vitest/config';
|
|
export default defineConfig({ test: { environment: 'happy-dom', pool: 'forks' } });
|