diff --git a/README.md b/README.md index 3b76514..0eb56e9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ CrAPP è una Progressive Web App sviluppata per digitalizzare completamente la g ## Stack tecnologico -React 19, TypeScript, TanStack Start (SSR), Vite 8, Tailwind CSS 4, Radix UI / shadcn, +React 19, TypeScript, TanStack Start (SSR), Vite 8, Tailwind CSS 4, motion, vaul, Supabase (PostgreSQL, Auth, Storage), Vercel, GitHub. Dettagli in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 47d5f15..3fc424c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -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 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 416f238..9767e12 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -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 diff --git a/docs/DESIGN_DECISIONS.md b/docs/DESIGN_DECISIONS.md index 60d6909..fce01f8 100644 --- a/docs/DESIGN_DECISIONS.md +++ b/docs/DESIGN_DECISIONS.md @@ -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.