Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions web/src/app/pattern-lab/LabPanels.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,14 @@
.layerControlRow select {
min-height: 44px;
}

/* A finger has no Alt key, right button or middle button. On a 390×844
phone this line wrapped the Pixel status bar to 51px, which left the
picture a 372×151 viewport and fitted it at 1×. Without it the viewport
is 372×177, and 2× needs 168. */
.pixelMouseHint {
display: none;
}
}

/* ── Pixel editor panel ── */
Expand Down
14 changes: 13 additions & 1 deletion web/src/app/pattern-lab/labCss.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
// and 44×44px after, in a header 59px tall both times. On a 390×844 touch
// screen the tab strip under Preview was 736px for 333px of room, and every
// tab carried a 27×27px ×. Without the × it is 520px and Knobs shows whole.
// On the same screen Del was 37×28px, the layer eye 20×17px and Push 40×22px.
// On the same screen Del was 37×28px, the layer eye 20×17px and Push 40×22px,
// and the Pixel status bar was 51px, two lines with the mouse gestures.

import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
Expand Down Expand Up @@ -168,3 +169,14 @@ describe("Layers and Knobs on a touch screen", () => {
expect(knobs.lastIndexOf("@media (hover: none) {")).toBeGreaterThan(knobs.indexOf("@media (max-width: 980px) {"));
});
});

describe("Pixel status line on a touch screen", () => {
const dock = css("LabPanels.module.css");
const pixel = css("panels/PixelPanel.tsx");

it("drops the mouse gestures, and nothing else", () => {
expect(mediaRule(dock, "(hover: none)", ".pixelMouseHint")).toMatch(/display: none;/);
expect(pixel).toContain("<span className={dock.pixelMouseHint}>alt-click picks · right-drag erases · middle-drag pans</span>");
expect(mediaRule(dock, "(hover: none)", ".pixelStatus")).toBe("");
});
});
26 changes: 22 additions & 4 deletions web/src/app/pattern-lab/panels/PixelPanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { act, createEvent, fireEvent, render, screen } from "@testing-library/react";
import PixelPanel from "./PixelPanel";
import { zoomToFit } from "./pixel/usePixelViewport";
import { useLabStore } from "@/lib/lab/store";
import type { PixelLayer } from "@/lib/lab/types";

Expand Down Expand Up @@ -285,13 +286,20 @@ describe("PixelPanel", () => {
};

it("on a phone the picture opens fitted, all of it in view", () => {
// the Pixel viewport on a 390×844 phone, measured in Chromium
panelSize(372, 151);
// the Pixel viewport on a 390×844 touch phone, measured in Chromium
panelSize(372, 177);
mount();
expect(screen.getByText("zoom 1×")).toBeTruthy();
expect(screen.getByText("zoom 2×")).toBeTruthy();
// and the zoom stays the user's to change
fireEvent.click(screen.getByLabelText("Zoom in"));
expect(screen.getByText("zoom 2×")).toBeTruthy();
expect(screen.getByText("zoom 3×")).toBeTruthy();
});

it("the mouse gestures sit apart in the status line, where a touch screen can drop them", () => {
mount();
const hint = screen.getByText("alt-click picks · right-drag erases · middle-drag pans");
expect(hint.className).toBe("pixelMouseHint");
expect(hint.parentElement?.textContent).toContain("zoom 6×");
});

it("a desktop panel narrower than the picture at 6× opens fitted too", () => {
Expand Down Expand Up @@ -440,3 +448,13 @@ describe("PixelPanel", () => {
expect(screen.queryByTitle(/Stamp the selection down/)).toBeNull();
});
});

describe("zoomToFit", () => {
it("fits 128×64 at 2× from a 168px-tall viewport, 64 × 2 and 40 of padding", () => {
expect(zoomToFit(372, 167, 128, 64)).toBe(1);
expect(zoomToFit(372, 168, 128, 64)).toBe(2);
// a 390×844 phone, with and without the mouse gestures under the picture
expect(zoomToFit(372, 151, 128, 64)).toBe(1);
expect(zoomToFit(372, 177, 128, 64)).toBe(2);
});
});
2 changes: 1 addition & 1 deletion web/src/app/pattern-lab/panels/PixelPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export default function PixelPanel() {
</span>
)}
<span style={{ flex: 1 }} />
<span>alt-click picks · right-drag erases · middle-drag pans</span>
<span className={dock.pixelMouseHint}>alt-click picks · right-drag erases · middle-drag pans</span>
</div>

{importOpen && (
Expand Down
2 changes: 1 addition & 1 deletion web/src/app/pattern-lab/panels/pixel/usePixelViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ZOOM_MAX = 32;
/**
* The largest whole zoom that shows the picture entire inside a viewport of
* this size: 16 px of padding a side and 4 px of air. Never below 1×. For
* 128×64 that is 1× in a 390×844 phone's 372×151 viewport, and 4× in the
* 128×64 that is 2× in a 390×844 phone's 372×177 viewport, and 4× in the
* 649×648 one at 1440×900.
*/
export function zoomToFit(viewportWidth: number, viewportHeight: number, width: number, height: number) {
Expand Down
Loading