perf(movimento): uma transição, 3D leve e vídeo certo por aparelho

Passagens com fade e 32 px, cena anterior termina em opacidade 0, sem visibility nem clip-path. 3D do hero como fundo ambiente, sob demanda e desligado em toque, aparelho fraco, saveData e movimento reduzido. Lenis fora do toque e salto direto em âncoras distantes. Vitrine só de clientes, até 3 capítulos, fixa só no desktop e carrossel no celular; vídeo só do projeto em cena com preload metadata. Rótulos mono a partir de 12 px e limão só no contato.
This commit is contained in:
Evandro Fonseca Junior committed 2026-10-14 03:32:23 -03:00
1 parent 8d07b8c6bb
commit c9a0b80656
48 files changed
+7210 -1241

No files matched your search

@@ -4,6 +4,7 @@ import {
buildShowcaseItems,
ShowcaseProvider,
useShowcaseCard,
useShowcaseOpen,
} from "./ShowcaseProvider";
let reducedMotion = false;
@@ -157,6 +158,59 @@ describe("ShowcaseProvider", () => {
).toEqual([]);
});
it("serves the reel with only the client projects the home passes in, in showcase order", () => {
const clients = projects.filter((project) =>
["as-servicos", "sc-plus", "lavacao-047", "sev-modaintima"].includes(
project.id,
),
);
expect(buildShowcaseItems(clients).map((item) => item.config.id)).toEqual([
"sev-modaintima",
"lavacao-047",
"sc-plus",
"as-servicos",
]);
});
it("works with no cards at all: no per-scroll work, and the enlarged window still opens and navigates", () => {
const clients = projects.filter((project) =>
["sev-modaintima", "lavacao-047", "sc-plus", "as-servicos"].includes(
project.id,
),
);
function Opener() {
const open = useShowcaseOpen();
return (
<button type="button" onClick={() => open("sc-plus")}>
abrir sc-plus
</button>
);
}
const frames = jest.spyOn(window, "requestAnimationFrame");
render(
<ShowcaseProvider projects={clients}>
<Opener />
</ShowcaseProvider>,
);
flush();
frames.mockClear();
act(() => {
window.dispatchEvent(new Event("scroll"));
window.dispatchEvent(new Event("resize"));
});
flush();
expect(frames).not.toHaveBeenCalled();
fireEvent.click(screen.getByRole("button", { name: "abrir sc-plus" }));
// posição 3 de 4 na lista que a home passou (o NutriScan não está nela)
expect(screen.getByRole("dialog", { name: "ampliado" })).toHaveTextContent(
"aberto:2",
);
fireEvent.click(screen.getByRole("button", { name: "fechar" }));
expect(screen.queryByRole("dialog")).toBeNull();
frames.mockRestore();
});
it("plays nothing until a card is on screen, then the one closest to the middle", () => {
const { frames } = setup();
flush();