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:
1 parent
8d07b8c6bb
commit
c9a0b80656
48 files changed
+7210
-1241
No files matched your search
@@ -18,6 +18,10 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
Object.defineProperty(navigator, "connection", {
|
||||
configurable: true,
|
||||
value: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
describe("ProjectVideo", () => {
|
||||
@@ -31,7 +35,7 @@ describe("ProjectVideo", () => {
|
||||
expect(element).toHaveAttribute("autoplay");
|
||||
expect(element).toHaveAttribute("loop");
|
||||
expect(element).toHaveAttribute("playsinline");
|
||||
expect(element).toHaveAttribute("preload", "none");
|
||||
expect(element).toHaveAttribute("preload", "metadata");
|
||||
expect(element).toHaveAttribute("poster", video.poster);
|
||||
expect(element?.muted).toBe(true);
|
||||
expect(element).toHaveAttribute("data-ready", "false");
|
||||
@@ -70,6 +74,62 @@ describe("ProjectVideo", () => {
|
||||
expect(element).toHaveAttribute("data-ready", "true");
|
||||
});
|
||||
|
||||
it("does not even request the poster while the card is far from the screen", () => {
|
||||
const { container, rerender } = render(
|
||||
<ProjectVideo
|
||||
video={video}
|
||||
title="Demo"
|
||||
active={false}
|
||||
showPoster={false}
|
||||
/>,
|
||||
);
|
||||
expect(container.querySelector("video")).not.toHaveAttribute("poster");
|
||||
|
||||
rerender(
|
||||
<ProjectVideo video={video} title="Demo" active={false} showPoster />,
|
||||
);
|
||||
expect(container.querySelector("video")).toHaveAttribute(
|
||||
"poster",
|
||||
video.poster,
|
||||
);
|
||||
});
|
||||
|
||||
it("swaps to the sources of the new device when the version changes", () => {
|
||||
const mobile = getShowcaseAssets("nutriscan", "mobile");
|
||||
const { container, rerender } = render(
|
||||
<ProjectVideo video={video} title="Demo" active />,
|
||||
);
|
||||
const loads = jest.mocked(HTMLMediaElement.prototype.load).mock.calls
|
||||
.length;
|
||||
|
||||
rerender(<ProjectVideo video={mobile} title="Demo" active />);
|
||||
expect(
|
||||
[...container.querySelectorAll("source")].map((source) =>
|
||||
source.getAttribute("src"),
|
||||
),
|
||||
).toEqual(mobile.sources.map((source) => source.src));
|
||||
expect(
|
||||
jest.mocked(HTMLMediaElement.prototype.load).mock.calls.length,
|
||||
).toBeGreaterThan(loads);
|
||||
});
|
||||
|
||||
it("shows only the poster, with no video element, when the data saver is on", () => {
|
||||
Object.defineProperty(navigator, "connection", {
|
||||
configurable: true,
|
||||
value: { saveData: true },
|
||||
});
|
||||
const { container } = render(
|
||||
<ProjectVideo video={video} title="Demo" active />,
|
||||
);
|
||||
|
||||
expect(container.querySelector("video")).toBeNull();
|
||||
expect(container.querySelector("source")).toBeNull();
|
||||
expect(
|
||||
screen.getByRole("img", { name: "Captura de tela de Demo" }),
|
||||
).toBeInTheDocument();
|
||||
expect(HTMLMediaElement.prototype.play).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows only the poster, with no video element, when the user prefers reduced motion", () => {
|
||||
reducedMotion = true;
|
||||
const { container } = render(
|
||||
|
||||
Reference in new issue
Block a user