trainlog/docs/design/web_dashboard_grid_v1.md

86 lines
4.5 KiB
Markdown
Raw Permalink 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.

# Web Dashboard grid V1
Status: `WEB_DASHBOARD_GRID_V1=PASS/FROZEN`
## Library spike
The spike was performed on 2026-09-16 against React 19.3.0, TypeScript 7 and
Vite 8.3.0. Package metadata and upstream documentation were checked before
installation.
| Candidate | Version checked | Fit | Decision |
|---|---:|---|---|
| `react-grid-layout` | 2.2.4 | MIT; React peer `>=16.3`; TypeScript v2 implementation; 12-column layouts, drag, two-axis resize, per-item min/max, configurable enablement, vertical compaction, responsive primitives and serializable layouts. Active 2026 releases. Mouse interaction is mature but has no complete keyboard grid editor. | Selected, with a Trainlog keyboard layer and independent model/validator. |
| `gridstack` | 13.3.0 | MIT; active maintenance; framework-neutral drag, resize, responsive columns and constraints. Its package is substantially larger and React integration remains an imperative wrapper around a DOM engine rather than a native typed React state boundary. | Rejected for this React-owned surface. |
| `@dnd-kit/core` | 6.3.1 | MIT; strong sensors and keyboard support, but it is a drag/drop toolkit rather than a heterogeneous dashboard-grid engine. It supplies neither resize nor the required collision/compaction policy; upstream guidance requires a custom sorting strategy for mixed grid sizes. | Rejected because Trainlog would have to build the missing engine. |
`react-grid-layout` has no external service, runtime telemetry, CDN or backend
dependency. Trainlog imports the v2 API directly and does not expose the
library's `{i,w,h}` representation outside its adapter.
## Trainlog model and invariants
The authoritative frontend shape is:
```text
TileLayout { id, x, y, width, height }
```
The seven stable IDs are `next-session`, `activity`, `progression`,
`last-session`, `max-records`, `muscle-distribution`, and `cardio-recovery`.
The desktop layout alone is canonical and uses 12 columns. The adapter maps it
to and from the library shape. A separate Trainlog validator requires exactly
those IDs, integral coordinates and dimensions, each tile's min/max bounds,
`x >= 0`, `y >= 0`, `x + width <= 12`, `y <= 200`, and no overlap.
The deterministic default is:
| Tile | x | y | width | height | min/max width | min/max height |
|---|---:|---:|---:|---:|---:|---:|
| Prochaine séance | 0 | 0 | 5 | 4 | 4–8 | 3–7 |
| Activité | 5 | 0 | 7 | 4 | 5–12 | 3–7 |
| Progression | 0 | 4 | 8 | 5 | 6–12 | 4–9 |
| Dernière séance | 8 | 4 | 4 | 3 | 3–7 | 3–6 |
| Records / MAX | 8 | 7 | 4 | 3 | 3–8 | 3–7 |
| Répartition musculaire | 0 | 9 | 6 | 5 | 5–12 | 4–9 |
| Cardio / récupération | 6 | 10 | 6 | 4 | 5–12 | 4–8 |
Vertical compaction is deterministic; overlap is forbidden and collisions
push/reflow other items. Library output is accepted into React state only after
conversion and Trainlog validation.
## Interaction and responsive contract
Normal mode disables drag and resize and emits no resize handles. Explicit
`Modifier l'agencement` mode enables them on desktop. `Annuler` restores the
entry snapshot, `Réinitialiser` restores the Trainlog default in the edit
draft, and `Enregistrer pour cette session` accepts the draft only in current
React memory. Reload deliberately restores the default: persistence belongs to
`WEB_DASHBOARD_LAYOUT_V1`.
Focused tiles support Arrow keys for movement and Shift+Arrow keys for resize.
Focus is visible and a polite live region announces logical coordinates and
dimensions. Mouse resize exposes east, south and south-east handles. Reduced
motion disables grid transitions.
Widths below 1100 px derive a six-column projection; widths below 700 px derive
a stable one-column projection. These projections preserve canonical ordering,
remain non-authoritative and never update the desktop layout. Editing at those
breakpoints is deliberately disabled with an explicit explanation.
The existing `/api/v1/dashboard` fetch and factual Footer remain unchanged.
Tile bodies retain placeholders; logical `compact`, `medium`, and `large`
presentation levels depend only on tile dimensions and add no business facts.
## Bundle impact
Vite production output before the dependency was 229.07 kB JavaScript and
7.14 kB CSS. V1 output is 301.61 kB JavaScript and 13.42 kB CSS: an increase of
72.54 kB JavaScript and 6.28 kB CSS before transport compression. This is
accepted for the complete drag, resize, constraint and compaction engine.
Upstream references:
- <https://github.com/react-grid-layout/react-grid-layout>
- <https://github.com/gridstack/gridstack.js>
- <https://github.com/clauderic/dnd-kit>