feat: refine portfolio showcase, services and quality lab
CI / verify (push) Failing after 5m9s

Align the notebook browser with the physical LCD, refresh real project captures and navigation, simplify service content, and stabilize hero hydration.
This commit is contained in:
Evandro Fonseca Junior committed 2026-09-05 14:20:54 -03:00
1 parent e2b20bc699
commit 8b12e51bc5
35 files changed
+2359 -1299

No files matched your search

+60 -111
View File
@@ -1,126 +1,75 @@
import { getNotebookFrame } from "./notebookTimeline";
import { getNotebookFrame, getNotebookSeekProgress } from "./notebookTimeline";
describe("getNotebookFrame", () => {
it("clamps progress below zero and starts with a closed device", () => {
expect(getNotebookFrame(-1, 4)).toMatchObject({
phase: "approach",
lidAngle: 0,
activeTabIndex: -1,
cursorVisible: false,
});
describe("notebook choreography", () => {
it("opens and boots before browsing, then blanks the display before closing", () => {
const frames = Array.from({ length: 1001 }, (_, index) =>
getNotebookFrame(index / 1000, 4),
);
const phases = [...new Set(frames.map((frame) => frame.phase))];
expect(phases).toEqual([
"approach",
"open",
"boot",
"cursor-in",
"browse",
"hold",
"close",
]);
for (const frame of frames) {
if (frame.phase === "open") expect(frame.screenOpacity).toBe(0);
if (frame.cursorVisible) expect(frame.screenOpacity).toBe(1);
if (frame.phase === "close" && frame.lidAngle < 112)
expect(frame.screenOpacity).toBe(0);
}
expect(getNotebookFrame(-1, 4).lidAngle).toBe(0);
expect(getNotebookFrame(2, 4).lidAngle).toBe(0);
});
it("clamps progress above one and ends with a closed device", () => {
expect(getNotebookFrame(2, 4)).toMatchObject({
phase: "close",
lidAngle: 0,
activeTabIndex: -1,
cursorVisible: false,
});
});
it("keeps the phase boundaries deterministic", () => {
expect(getNotebookFrame(0.1, 4).phase).toBe("open");
expect(getNotebookFrame(0.25, 4).phase).toBe("boot");
expect(getNotebookFrame(0.34, 4).phase).toBe("cursor-in");
expect(getNotebookFrame(0.44, 4).phase).toBe("browse");
expect(getNotebookFrame(0.78, 4).phase).toBe("hold");
expect(getNotebookFrame(0.87, 4).phase).toBe("close");
});
it("opens the lid before the browser starts", () => {
const frame = getNotebookFrame(0.22, 4);
expect(frame.phase).toBe("open");
expect(frame.lidAngle).toBeGreaterThan(0);
expect(frame.screenOpacity).toBe(0);
});
it("boots the screen before the cursor enters", () => {
expect(getNotebookFrame(0.25, 4).screenOpacity).toBe(0);
expect(getNotebookFrame(0.34, 4).screenOpacity).toBe(1);
expect(getNotebookFrame(0.4, 4).cursorVisible).toBe(true);
});
it("turns the screen off before the lid closes", () => {
const screenOff = getNotebookFrame(0.9, 4);
const closing = getNotebookFrame(0.95, 4);
expect(screenOff).toMatchObject({
phase: "close",
lidAngle: 112,
screenOpacity: 0,
});
expect(closing.screenOpacity).toBe(0);
expect(closing.lidAngle).toBeGreaterThan(0);
expect(closing.lidAngle).toBeLessThan(112);
});
it("selects each tab only inside the browse window", () => {
expect(getNotebookFrame(0.43, 4).activeTabIndex).toBe(-1);
expect(getNotebookFrame(0.48, 4).activeTabIndex).toBe(0);
expect(getNotebookFrame(0.57, 4).activeTabIndex).toBe(1);
expect(getNotebookFrame(0.67, 4).activeTabIndex).toBe(2);
expect(getNotebookFrame(0.76, 4).activeTabIndex).toBe(3);
});
it("holds the final tab until the closing phase", () => {
expect(getNotebookFrame(0.84, 4)).toMatchObject({
phase: "hold",
activeTabIndex: 3,
cursorVisible: true,
});
expect(getNotebookFrame(0.88, 4)).toMatchObject({
phase: "close",
activeTabIndex: -1,
cursorVisible: false,
});
});
it("emits a deterministic cursor click pulse for each tab", () => {
const first = getNotebookFrame(0.475, 4);
const later = getNotebookFrame(0.56, 4);
expect(first.cursorClicking).toBe(true);
expect(later.cursorClicking).toBe(true);
expect(first.cursorX).toBeGreaterThanOrEqual(0);
expect(first.cursorX).toBeLessThanOrEqual(1);
expect(first.cursorY).toBeGreaterThanOrEqual(0);
expect(first.cursorY).toBeLessThanOrEqual(1);
});
it("moves the cursor between tab targets instead of teleporting", () => {
const previous = getNotebookFrame(0.525, 4);
const moving = getNotebookFrame(0.532, 4);
const target = getNotebookFrame(0.56, 4);
expect(moving.cursorX).toBeGreaterThan(previous.cursorX);
expect(moving.cursorX).toBeLessThan(target.cursorX);
expect(moving.cursorY).toBe(target.cursorY);
});
it("lands the click pulse on the center of the selected tab", () => {
for (const progress of [0.475, 0.56, 0.65, 0.735]) {
const frame = getNotebookFrame(progress, 4);
expect(frame.cursorClicking).toBe(true);
expect(frame.cursorX).toBeCloseTo((frame.activeTabIndex + 0.5) / 4, 6);
it("keeps the previous project until cursor arrival, including reverse scroll", () => {
const frames = Array.from({ length: 10001 }, (_, index) =>
getNotebookFrame(index / 10000, 4),
);
for (let selected = 1; selected < 4; selected += 1) {
const arrival = frames.findIndex(
(frame) => frame.activeTabIndex === selected,
);
const before = getNotebookFrame((arrival - 1) / 10000, 4);
const atClick = frames[arrival];
expect(before.activeTabIndex).toBe(selected - 1);
expect(before.cursorClicking).toBe(false);
expect(atClick.cursorClicking).toBe(true);
expect(atClick.cursorX).toBeCloseTo((selected + 0.5) / 4);
const reversed = getNotebookFrame((arrival - 2) / 10000, 4);
expect(reversed.activeTabIndex).toBe(selected - 1);
expect(reversed.cursorX).toBeLessThan(atClick.cursorX);
expect(reversed.cursorX).toBeGreaterThan((selected - 0.5) / 4);
}
});
it("tracks the real number of tabs", () => {
expect(getNotebookFrame(0.68, 2).cursorX).toBeCloseTo(0.75, 6);
expect(getNotebookFrame(0.6, 3).cursorX).toBeCloseTo(0.5, 6);
it("seeks directly into a readable hold for the requested project", () => {
for (const count of [1, 4]) {
for (let index = 0; index < count; index += 1) {
const progress = getNotebookSeekProgress(index, count);
const frame = getNotebookFrame(progress, count);
expect(frame.activeTabIndex).toBe(index);
expect(frame.screenOpacity).toBe(1);
expect(frame.cursorClicking).toBe(false);
expect(getNotebookFrame(progress + 0.03, count).activeTabIndex).toBe(
index,
);
}
}
expect(
getNotebookFrame(getNotebookSeekProgress(99, 4), 4).activeTabIndex,
).toBe(3);
});
it("is deterministic when rewound to the same progress", () => {
expect(getNotebookFrame(0.61, 4)).toEqual(getNotebookFrame(0.61, 4));
});
it("does not expose an invalid tab when there are no projects", () => {
it("does not expose a tab or cursor for empty or invalid project counts", () => {
expect(getNotebookFrame(0.6, 0)).toMatchObject({
activeTabIndex: -1,
cursorVisible: false,
cursorClicking: false,
});
expect(getNotebookFrame(0.6, Number.NaN).activeTabIndex).toBe(-1);
});
});