Registra DD-021 e DD-022 e allinea la documentazione

DD-021 (molle interrompibili con motion) e DD-022 (l'app è solo chiara)
motivano le due scelte che un domani sembreranno arbitrarie: perché è entrata
una libreria di animazione dopo averne tolte 45, e perché il tema scuro è
stato cancellato invece che completato.

DD-021 riporta il numero misurato e scomodo: il bundle client cresce da 267 a
308 KB gzip. Togliere dipendenze mai importate non lo riduce, perché il
tree-shaking già le escludeva; il guadagno è sulle 50 dipendenze dirette che
diventano 21.

ARCHITECTURE e README non descrivevano più lo stack reale (Radix/shadcn) e la
sezione UI ignorava la primitiva Card e il sistema di molle. Tolto anche
`hooks/` dall'albero del progetto: la cartella non esiste più.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-05 12:42:55 +02:00
co-authored by Claude Opus 5
parent 9b28a86f7c
commit 26bacbf700
4 changed files with 144 additions and 14 deletions
+23 -10
View File
@@ -5,12 +5,12 @@ riferimento tecnico — `CLAUDE.md` non ripete questi contenuti, li richiama.
## Stack
| Livello | Tecnologie |
| ------------- | ------------------------------------------------------------------------------------- |
| Frontend | React 19, TypeScript, TanStack Start (SSR), Vite 8, Tailwind CSS 4, Radix UI / shadcn |
| Backend | Supabase (PostgreSQL, Auth, Storage) |
| Hosting | Vercel |
| Versionamento | Git, GitHub |
| Livello | Tecnologie |
| ------------- | -------------------------------------------------------------------------------- |
| Frontend | React 19, TypeScript, TanStack Start (SSR), Vite 8, Tailwind CSS 4, motion, vaul |
| Backend | Supabase (PostgreSQL, Auth, Storage) |
| Hosting | Vercel |
| Versionamento | Git, GitHub |
Le dipendenze sono installate con **bun** (`bun.lock`, `bunfig.toml`). `bunfig.toml` impone
`minimumReleaseAge = 24h` come guardia supply-chain: aggiungere un pacchetto a
@@ -24,7 +24,6 @@ src/
routes/ routing file-based
lib/ logica di dominio, un file per modulo
integrations/ client Supabase e integrazioni esterne
hooks/
assets/
supabase/ migration SQL
test/ suite di test (unit, integration, end-to-end)
@@ -84,9 +83,23 @@ quando il database non risponde.
## UI
Componenti condivisi in `src/components/crapp/` (`ui-bits.tsx` per `PageHeader`, `Section`,
`StatTile`), primitive shadcn in `src/components/ui/`, animazioni in
`src/components/motion/`. Mobile-first (DD-005): poche schermate, pochi click.
Componenti condivisi in `src/components/crapp/` (`ui-bits.tsx` per `Card`, `PageHeader`,
`Section`, `StatTile`), animazioni in `src/components/motion/`. Mobile-first (DD-005): poche
schermate, pochi click.
In `src/components/ui/` restano solo le due primitive shadcn davvero usate, `drawer` (vaul) e
`sonner`: le altre 43 non erano importate da nessuna parte (DD-021). Il resto dell'interfaccia
è composto con Tailwind e la primitiva `Card`, che è l'unica definizione di raggio, sfondo e
ombra delle superfici.
L'app è **solo chiara** (DD-022): non esiste un tema scuro e `:root` dichiara
`color-scheme: light`.
Il movimento usa molle interrompibili di `motion` con i preset in `src/lib/molla.ts`
(DD-021): `molla.ui` di default, `molla.slancio` solo dopo un gesto con inerzia,
`molla.foglio` per drawer e cambi di vista. `proietta()` calcola dove finirebbe un elemento
lanciato, così swipe come quello del calendario atterrano dove il gesto stava andando.
`src/lib/motion.ts` conserva solo il rilevamento del movimento ridotto e i coriandoli.
## Comandi
+37
View File
@@ -6,6 +6,43 @@ qui: sta in [ROADMAP.md](ROADMAP.md).
## Versione attuale — agosto 2026
### Revisione dell'interfaccia: accessibilità, movimento, peso
- **Contrasto**: `--success`, `--info` e `--training` erano tra 3.3:1 e 3.5:1 con il testo
bianco sopra (chip «Presente», «Allenamento», celle del calendario): ora sono sotto la
soglia di luminosità che garantisce 4.5:1. I gradi dei badge usavano `text-oro` e
`text-argento` su bianco, cioè 1.9:1 e 2.5:1 — praticamente invisibili: nascono i token
`--oro-testo`, `--argento-testo`, `--bronzo-testo` per il testo, mentre le versioni chiare
restano su sfondi e bordi.
- **PWA**: mancava `viewport-fit=cover`, quindi `env(safe-area-inset-bottom)` valeva sempre 0
e su iPhone la BottomNav finiva sotto la home bar. `theme-color` e `background_color` erano
`#111111` su un'app chiara: barra di stato nera e splash nero prima di una UI bianca.
- **`lang="it"`** al posto di `lang="en"`, su un'app interamente in italiano; 404 e schermata
d'errore tradotte; anteprima social ripulita dall'immagine Lovable scaduta e da
`twitter:site` che puntava a `@Lovable`.
- **Tocco e tastiera**: nessun `:focus-visible` era definito (ora c'è una regola globale);
chip presenza, filtri e bottoni icona portati a 44px; `aria-current` sulla navigazione,
`aria-pressed` sui controlli a stato, `aria-controls` sulle sezioni a tendina, `aria-busy`
sui caricamenti. Il testo sotto i 12px è sparito (108 occorrenze).
- **Movimento** (DD-021): molle interrompibili di `motion` al posto delle `@keyframes` a
durata fissa. `Reveal` compare quando entra davvero nel viewport (prima consumava
l'animazione a vuoto sotto la piega); `Barra` anima `scaleX` invece di `width`; `Numero`
cambia rotta se il dato cambia a metà conteggio. Il calendario si cambia mese anche con lo
swipe, con il punto d'arrivo scelto proiettando la velocità di rilascio.
- **Meno dipendenze** (DD-021): rimossi 43 componenti `src/components/ui/` non importati da
nessuna parte e ~45 dipendenze (tutti i `@radix-ui/*`, `recharts`, `react-hook-form`,
`date-fns`, `embla`, `cmdk`; `zod` resta perché lo usano le route API). Restano `drawer` e
`sonner`. Il bundle **non** cala per questo — quel codice era già escluso dal
tree-shaking — ma cala la superficie da aggiornare e da controllare: 50 dipendenze dirette
diventano 21. Il bundle client cresce di ~42 KB gzip per `motion` (267 → 308 KB).
- **Primitiva `Card`**: `rounded-3xl bg-card p-4 shadow-card` era ricopiato a mano 22 volte.
- **Tema scuro rimosso** (DD-022): esisteva un blocco `.dark` mai applicato e incoerente.
- Tolte le quattro switch di notifica in `/profilo` che erano `defaultChecked` e non facevano
niente, e la conferma nativa prima di _cambiare_ la foto profilo (resta su quella che la
rimuove, che è irreversibile).
- Le celle del calendario con più tipi di evento non usano più un gradiente a fette con
un'ombra bianca sul numero per restare leggibili: fondo neutro e un puntino per tipo.
### Serie di presenze calcolate sui dati reali
- `serieConsecutiva()` (`src/lib/presenze.ts`) deriva le serie da eventi passati e
+83 -3
View File
@@ -36,12 +36,14 @@ Serve a rispondere a domande del tipo:
| [DD-018](#dd-018--collegamento-automatico-giocatoreaccount-per-email) | Collegamento automatico per email |
| [DD-019](#dd-019--il-branch-dei-commit-lo-decide-lutente) | Il branch lo decide l'utente |
| [DD-020](#dd-020--una-funzione-modificata-senza-test-non-è-finita) | Test obbligatori e verdi |
| [DD-021](#dd-021--molle-interrompibili-al-posto-delle-animazioni-a-durata-fissa) | Molle interrompibili con motion |
| [DD-022](#dd-022--lapp-è-solo-chiara) | App solo chiara |
**In valutazione**
| ID | Titolo |
| ----------------------------------------------------------------- | ---------------------- |
| [DD-014](#dd-014--convergenza-schema-database-eventi-e-presenze) | Convergenza schema DB |
| ID | Titolo |
| ---------------------------------------------------------------- | --------------------- |
| [DD-014](#dd-014--convergenza-schema-database-eventi-e-presenze) | Convergenza schema DB |
**Sostituite**
@@ -668,3 +670,81 @@ dicendo perché.
**Riesame**
Se comparisse un ambiente di staging stabile che rende superflua parte della copertura.
---
### DD-021 — Molle interrompibili al posto delle animazioni a durata fissa
**Data:** 5 settembre 2026
**Stato:** Accettata
**Contesto**
Il movimento era fatto con `@keyframes` CSS e transizioni a durata fissa. Funzionava, ma
nessuna di quelle animazioni può essere interrotta: se l'utente tocca o scorre a metà, la
sequenza va avanti per conto suo, e per ripartire deve prima finire. Mancava del tutto
qualsiasi gesto: il calendario si cambiava solo con due frecce.
Contemporaneamente 43 componenti su 45 in `src/components/ui/` non erano importati da nessuna
parte, e con loro ~45 dipendenze (tutti i `@radix-ui/*`, `recharts`, `react-hook-form`,
`date-fns`, `embla`, `cmdk`, …): superficie di aggiornamento e di sicurezza pagata a vuoto.
**Decisione**
Aggiungere **una** libreria di animazione — `motion` — e toglierne ~45 inutilizzate. I
parametri stanno in `src/lib/molla.ts` e sono i due di Apple (_Designing Fluid Interfaces_):
rimbalzo e durata, non massa/rigidità/smorzamento. `molla.ui` (nessun sorpasso) è il default;
`molla.slancio` si usa **solo** dopo un gesto che portava già inerzia.
**Alternative scartate**
- Tenere solo CSS con easing `linear()` e View Transitions → copre le comparse, non i gesti:
niente handoff di velocità, niente ripartenza dal valore corrente.
- GSAP → più grande e orientato alla timeline, cioè al modello prescritto che stiamo lasciando.
**Conseguenze**
- Le animazioni partono dal valore _a schermo_: un dato che cambia a metà transizione non
produce salti.
- Il movimento è ora codice JavaScript: senza JS non c'è comparsa (l'app già non funziona
senza, per auth e dati).
- `src/lib/motion.ts` resta solo per il movimento ridotto e i coriandoli.
- `src/components/ui/` non è più una libreria: aggiungere una primitiva shadcn significa
installarla, non pescarla da lì.
**Riesame**
Se il peso del bundle client diventasse un problema misurato, o se il web recuperasse
nativamente l'interrompibilità (`ScrollTimeline` e `linear()` sono un primo passo).
---
### DD-022 — L'app è solo chiara
**Data:** 5 settembre 2026
**Stato:** Accettata
**Contesto**
`styles.css` conteneva un blocco `.dark` completo che non veniva mai applicato: nessun
interruttore, nessun `prefers-color-scheme`. Peggio, era incoerente. In `.dark` l'accento
diventava grigio-blu — il rosso del brand spariva — e mancavano del tutto `--success`,
`--warning`, `--info`, `--training`, i metalli dei badge, i due gradienti e le due ombre. Un
terzo stato: presente, sbagliato, morto.
**Decisione**
CrAPP è un'app solo chiara. Il blocco `.dark` è rimosso e `:root` dichiara
`color-scheme: light`, così anche i controlli nativi restano coerenti.
**Alternative scartate**
- Completare il tema scuro → è lavoro vero (gradienti, ombre, i due colori dei metalli, le
superfici traslucide) per una richiesta che nessuno ha fatto.
- Lasciare il blocco lì «per dopo» → un tema mai attivato non si accorge di rompersi.
**Conseguenze**
- Chi riaprirà il tema scuro parte da zero, ma da zero onesto: la palette chiara ha ora
contrasti verificati e i token con suffisso `-testo` per i colori che come testo non
reggono.
- La barra di stato (`theme-color`) e lo splash del manifest sono allineati al fondo chiaro.
**Riesame**
Se arriva una richiesta reale dalla squadra, o se si gioca in palestre al buio abbastanza
spesso da rendere il tema scuro una funzione e non un vezzo.