Riduce il lag su Android: tab memoizzate, vetro/blur/drag disattivati sui device deboli
- squadra.tsx e classifica.tsx: il contenuto di ogni tab di BarraSottosezioni è ora memoizzato con useMemo, cosi' uno stato locale o un refetch in background non ricalcolano piu' anche le sezioni nascoste. - BottomNav, BarraSottosezioni, calendario: useMotoRidotto (RAM bassa o prefers-reduced-motion) disattiva sui device deboli la catena di filtri SVG piu' pesante di .vetro, il backdrop-blur della barra tab e il drag orizzontale; su iOS e device performanti resta tutto invariato. - styles.css: rimossa l'utility .materiale, orfana da quando BottomNav e' passata a .vetro. - ui-bits.tsx: decoding="async" su TeamLogo. - todo.md: traccia le cause individuate e lo stato di applicazione di ciascuna. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { useEffect, useRef, useState, type ReactNode } from "react";
|
||||
import { motion, useReducedMotion } from "motion/react";
|
||||
import { motion } from "motion/react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { proietta } from "@/lib/molla";
|
||||
import { useMotoRidotto } from "@/lib/motion";
|
||||
|
||||
export type VoceSottosezione = {
|
||||
id: string;
|
||||
@@ -38,7 +39,11 @@ export function BarraSottosezioni({
|
||||
const [attiva, setAttiva] = useState(defaultId ?? voci[0]?.id ?? "");
|
||||
const direzione = useRef(0);
|
||||
const tabRefs = useRef<Record<string, HTMLButtonElement | null>>({});
|
||||
const ridotto = useReducedMotion();
|
||||
// `useMotoRidotto` copre anche i device deboli (RAM bassa), non solo
|
||||
// `prefers-reduced-motion`: qui disattiva sia lo swipe orizzontale sia il
|
||||
// blur della barra tab, i due costi maggiori all'ingresso in una pagina con
|
||||
// sottosezioni (Squadra, Campionato, Profilo).
|
||||
const ridotto = useMotoRidotto();
|
||||
const indice = Math.max(
|
||||
0,
|
||||
voci.findIndex((v) => v.id === attiva),
|
||||
@@ -69,7 +74,8 @@ export function BarraSottosezioni({
|
||||
<div
|
||||
className={cn(
|
||||
"min-w-0 max-w-full border-b border-border bg-background",
|
||||
!sottolineatura && "bg-background/80 pt-3 backdrop-blur-md",
|
||||
!sottolineatura &&
|
||||
(ridotto ? "bg-background pt-3" : "bg-background/80 pt-3 backdrop-blur-md"),
|
||||
)}
|
||||
>
|
||||
{/* Solo la barra tab può scrollare in orizzontale: non allarga il layout pagina. */}
|
||||
@@ -136,7 +142,9 @@ export function BarraSottosezioni({
|
||||
key={voce.id}
|
||||
role="tabpanel"
|
||||
aria-label={voce.label}
|
||||
drag="x"
|
||||
// Sui device deboli lo swipe orizzontale (pointer listener + hit-testing
|
||||
// ad ogni frame) resta disattivato: si cambia tab solo toccando la barra.
|
||||
drag={ridotto ? false : "x"}
|
||||
dragConstraints={{ left: 0, right: 0 }}
|
||||
dragElastic={0.12}
|
||||
dragMomentum={false}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { CalendarDays, Home, Trophy, Users } from "lucide-react";
|
||||
import { motion, useReducedMotion } from "motion/react";
|
||||
import { motion } from "motion/react";
|
||||
import { molla } from "@/lib/molla";
|
||||
import { useMotoRidotto } from "@/lib/motion";
|
||||
|
||||
// Quattro voci e non cinque: il profilo sta in alto a destra
|
||||
// nell'intestazione di ogni pagina, dove lo cerca chi arriva da iOS.
|
||||
@@ -13,7 +14,10 @@ const items = [
|
||||
] as const;
|
||||
|
||||
export function BottomNav() {
|
||||
const ridotto = useReducedMotion();
|
||||
// `useMotoRidotto` copre anche i device deboli (RAM bassa), non solo
|
||||
// `prefers-reduced-motion`: qui disattiva sia la molla della capsula sia il
|
||||
// vetro sfocato, i due costi maggiori ad ogni cambio di rotta.
|
||||
const ridotto = useMotoRidotto();
|
||||
|
||||
return (
|
||||
<nav
|
||||
@@ -62,7 +66,13 @@ export function BottomNav() {
|
||||
*/}
|
||||
{/* `vetro` porta con sé le proprie ombre, quindi niente `shadow-chrome`:
|
||||
sarebbero due `box-shadow` sullo stesso elemento e una vincerebbe. */}
|
||||
<div className="vetro pointer-events-auto mx-auto grid h-[var(--altezza-nav)] max-w-md grid-cols-4 rounded-full border border-white/40 p-1.5">
|
||||
<div
|
||||
className="vetro pointer-events-auto mx-auto grid h-[var(--altezza-nav)] max-w-md grid-cols-4 rounded-full border border-white/40 p-1.5"
|
||||
// Su device deboli il backdrop-filter con feTurbulence/feDisplacementMap
|
||||
// (solo Blink, cioè Android) e la molla della capsula sotto sono i due
|
||||
// costi maggiori ad ogni cambio di rotta: `data-leggero` li disattiva.
|
||||
{...(ridotto ? { "data-leggero": "" } : {})}
|
||||
>
|
||||
{items.map(({ to, label, icon: Icon }) => (
|
||||
<Link
|
||||
key={to}
|
||||
|
||||
@@ -25,6 +25,7 @@ export function TeamLogo({
|
||||
alt="CRAP Volley"
|
||||
width={192}
|
||||
height={192}
|
||||
decoding="async"
|
||||
className={cn("shrink-0 rounded-2xl object-cover shadow-pop", className)}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user