perf(movimento): sem tela vazia, passagens em CSS e vitrine leve
Projetos sobem sobre o palco do hero e o celular tem hero de uma tela sem mergulho; passagens com animation-timeline em CSS, sem GSAP nem motion; troca da vitrine sem texto duplicado; moldura de celular só com pôster e scrub reencodado em 960 px (9,4 para 5,2 MB); 3D monta na primeira interação e para quando parado; transição entre páginas do mesmo segmento; foco em anel duplo; texto de 15 px no celular; código morto removido.
This commit is contained in:
1 parent
10f170abf4
commit
318a764190
77 files changed
+4293
-4951
No files matched your search
@@ -1,31 +1,28 @@
|
||||
"use client";
|
||||
|
||||
import { useReducedMotion as useFramerReducedMotion } from "motion/react";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const QUERY = "(prefers-reduced-motion: reduce)";
|
||||
|
||||
/**
|
||||
* Hook que detecta a preferência prefers-reduced-motion do sistema operacional.
|
||||
* Wrapper sobre o hook useReducedMotion do Framer Motion.
|
||||
*
|
||||
* @returns {boolean} true se prefers-reduced-motion está ativo, false caso contrário
|
||||
* Preferência `prefers-reduced-motion` do sistema operacional, lida com matchMedia (sem biblioteca de animação).
|
||||
* Falso no servidor e na primeira renderização no navegador, para o HTML hidratar igual ao do servidor.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const reducedMotion = useReducedMotion();
|
||||
*
|
||||
* return (
|
||||
* <motion.div
|
||||
* animate={{ opacity: 1, y: reducedMotion ? 0 : 20 }}
|
||||
* />
|
||||
* );
|
||||
* ```
|
||||
* return <div data-calm={reducedMotion || undefined} />;
|
||||
*/
|
||||
export function useReducedMotion(): boolean {
|
||||
const systemPreference = useFramerReducedMotion();
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
const [reduced, setReduced] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsMounted(true);
|
||||
if (typeof window.matchMedia !== "function") return;
|
||||
const query = window.matchMedia(QUERY);
|
||||
const update = () => setReduced(query.matches);
|
||||
update();
|
||||
query.addEventListener("change", update);
|
||||
return () => query.removeEventListener("change", update);
|
||||
}, []);
|
||||
|
||||
return isMounted && systemPreference === true;
|
||||
return reduced;
|
||||
}
|
||||
Reference in new issue
Block a user