Skip to content

Commit e34a5e2

Browse files
authored
Merge pull request #278 from ToolboxAid/PR_26179_CHARLIE_038-sprites-grid-dimension-fix
PR_26179_CHARLIE_038-sprites-grid-dimension-fix
2 parents 5bee276 + 9fb2e4c commit e34a5e2

6 files changed

Lines changed: 318 additions & 144 deletions

File tree

assets/theme-v2/css/gamefoundrystudio.css

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,21 +1164,24 @@ body.tool-focus-mode .tool-column:last-of-type {
11641164
}
11651165

11661166
.sprite-canvas-grid {
1167-
--sprite-grid-size: 16;
1167+
box-sizing: border-box;
11681168
display: grid;
1169-
grid-template-columns: repeat(var(--sprite-grid-size), minmax(0, 1fr));
1169+
gap: 0;
11701170
width: min(100%, 520px);
11711171
aspect-ratio: 1;
1172+
overflow: hidden;
11721173
border: 1px solid var(--line);
11731174
background: var(--panel)
11741175
}
11751176

11761177
.sprite-canvas-grid[data-sprites-grid-size="16"] {
1177-
--sprite-grid-size: 16
1178+
grid-template-columns: repeat(16, minmax(0, 1fr));
1179+
grid-template-rows: repeat(16, minmax(0, 1fr))
11781180
}
11791181

11801182
.sprite-canvas-grid[data-sprites-grid-size="32"] {
1181-
--sprite-grid-size: 32
1183+
grid-template-columns: repeat(32, minmax(0, 1fr));
1184+
grid-template-rows: repeat(32, minmax(0, 1fr))
11821185
}
11831186

11841187
.sprite-canvas-shell[data-sprites-zoom-level="2"] .sprite-canvas-grid {
@@ -1190,6 +1193,7 @@ body.tool-focus-mode .tool-column:last-of-type {
11901193
}
11911194

11921195
.sprite-canvas-cell {
1196+
box-sizing: border-box;
11931197
min-width: 0;
11941198
min-height: 0;
11951199
padding: 0;

dev/tests/playwright/tools/SpritesToolShell.spec.mjs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,52 @@ async function expectCenterAndPreviewEmpty(page, row, column) {
249249
expect(await previewCellHasPaint(page, row, column)).toBe(false);
250250
}
251251

252+
async function gridDimensionMetrics(page) {
253+
return page.locator("[data-sprites-pixel-grid]").evaluate((grid) => {
254+
const cells = Array.from(grid.querySelectorAll("[role='gridcell']"));
255+
const gridRect = grid.getBoundingClientRect();
256+
let maxRight = 0;
257+
let maxBottom = 0;
258+
const styles = getComputedStyle(grid);
259+
const templateTrackCount = (value) => value.split(" ").filter(Boolean).length;
260+
261+
for (const cell of cells) {
262+
const rect = cell.getBoundingClientRect();
263+
maxRight = Math.max(maxRight, rect.right);
264+
maxBottom = Math.max(maxBottom, rect.bottom);
265+
}
266+
267+
const lastRowCells = cells.slice(-Number(grid.dataset.spritesGridSize || 0));
268+
return {
269+
cellCount: cells.length,
270+
columnCount: templateTrackCount(styles.gridTemplateColumns),
271+
heightDelta: Math.abs(maxBottom - gridRect.bottom),
272+
lastCellColumn: cells.at(-1)?.dataset.spritePixelColumn || "",
273+
lastCellRow: cells.at(-1)?.dataset.spritePixelRow || "",
274+
lastRowCellCount: lastRowCells.length,
275+
lastRowColumns: lastRowCells.map((cell) => cell.dataset.spritePixelColumn),
276+
lastRowRows: lastRowCells.map((cell) => cell.dataset.spritePixelRow),
277+
rowCount: templateTrackCount(styles.gridTemplateRows),
278+
widthDelta: Math.abs(maxRight - gridRect.right),
279+
};
280+
});
281+
}
282+
283+
async function expectExactGridDimensions(page, expectedSize) {
284+
await expect(page.locator("[data-sprites-pixel-grid] [role='gridcell']")).toHaveCount(expectedSize * expectedSize);
285+
const metrics = await gridDimensionMetrics(page);
286+
expect(metrics.cellCount).toBe(expectedSize * expectedSize);
287+
expect(metrics.columnCount).toBe(expectedSize);
288+
expect(metrics.rowCount).toBe(expectedSize);
289+
expect(metrics.lastRowCellCount).toBe(expectedSize);
290+
expect(metrics.lastCellRow).toBe(String(expectedSize));
291+
expect(metrics.lastCellColumn).toBe(String(expectedSize));
292+
expect(metrics.lastRowRows.every((row) => row === String(expectedSize))).toBe(true);
293+
expect(metrics.lastRowColumns).toEqual(Array.from({ length: expectedSize }, (_, index) => String(index + 1)));
294+
expect(metrics.widthDelta).toBeLessThanOrEqual(1);
295+
expect(metrics.heightDelta).toBeLessThanOrEqual(1);
296+
}
297+
252298
test("Sprite Creator shell loads with visible tool, canvas, details, and status regions", async ({ page }) => {
253299
const server = await startSpriteShellTestServer();
254300
const failures = collectPageFailures(page);
@@ -418,6 +464,34 @@ test("Sprite Creator shell loads with visible tool, canvas, details, and status
418464
}
419465
});
420466

467+
test("Sprite Creator canvas grid dimensions stay exact across modes and zoom", async ({ page }) => {
468+
const server = await startSpriteShellTestServer();
469+
const failures = collectPageFailures(page);
470+
471+
try {
472+
await page.goto(`${server.baseUrl}/toolbox/sprites/index.html`, { waitUntil: "networkidle" });
473+
474+
await expectExactGridDimensions(page, 16);
475+
for (const zoomLabel of ["200%", "400%", "100%"]) {
476+
await page.getByRole("button", { name: zoomLabel }).click();
477+
await expectExactGridDimensions(page, 16);
478+
}
479+
480+
await page.getByRole("button", { name: "32x32" }).click();
481+
await expectExactGridDimensions(page, 32);
482+
for (const zoomLabel of ["200%", "400%", "100%"]) {
483+
await page.getByRole("button", { name: zoomLabel }).click();
484+
await expectExactGridDimensions(page, 32);
485+
}
486+
487+
expect(failures.failedRequests).toEqual([]);
488+
expect(failures.pageErrors).toEqual([]);
489+
expect(failures.consoleErrors).toEqual([]);
490+
} finally {
491+
await server.close();
492+
}
493+
});
494+
421495
test("Sprite Creator keeps center canvas and right preview in sync", async ({ page }) => {
422496
const server = await startSpriteShellTestServer();
423497
const failures = collectPageFailures(page);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# PR_26179_CHARLIE_038-sprites-grid-dimension-fix
2+
3+
Team: CHARLIE
4+
5+
Mode: Batch governance stacked bug-fix workflow
6+
7+
Base branch: PR_26179_CHARLIE_037-sprites-animation-export
8+
9+
Branch: PR_26179_CHARLIE_038-sprites-grid-dimension-fix
10+
11+
## Summary
12+
13+
Fixed Sprite Creator center canvas grid dimensions. The Sprite Creator page now loads the shared `gamefoundrystudio.css` stylesheet that owns the canvas styles, and the canvas grid uses explicit 16x16 and 32x32 CSS row/column templates instead of an invalid custom-property repeat count. This prevents orphan or partial rows/columns and keeps zoom display controls from changing logical grid dimensions.
14+
15+
## Branch Validation
16+
17+
PASS
18+
19+
- Built from `PR_26179_CHARLIE_037-sprites-animation-export`.
20+
- Scope stayed limited to Sprite Creator grid dimensions and regression coverage.
21+
- No DB/API/schema changes.
22+
- No browser-owned authoritative product data added.
23+
- No start_of_day files changed.
24+
- ZIP package created at the requested path.
25+
26+
## Requirement Checklist
27+
28+
PASS - 16x16 mode renders exactly 16 columns and 16 rows.
29+
30+
PASS - 32x32 mode renders exactly 32 columns and 32 rows.
31+
32+
PASS - Prevents orphan or extra cells at bottom/right edge.
33+
34+
PASS - Zoom levels 100%, 200%, and 400% do not change row/column count.
35+
36+
PASS - Preview/export behavior unchanged.
37+
38+
PASS - No DB/API/schema changes.
39+
40+
PASS - No browser-owned authoritative product data.
41+
42+
PASS - No start_of_day changes.
43+
44+
PASS - Targeted Playwright coverage added.
45+
46+
## Validation Lane
47+
48+
PASS - `node --check dev/tests/playwright/tools/SpritesToolShell.spec.mjs`
49+
50+
PASS - `git diff --check -- toolbox/sprites/index.html assets/theme-v2/css/gamefoundrystudio.css dev/tests/playwright/tools/SpritesToolShell.spec.mjs`
51+
52+
PASS - Runtime guard scan found no prohibited inline style/script/event-handler or stale placeholder text in touched runtime files.
53+
54+
PASS - `npx playwright test dev/tests/playwright/tools/SpritesToolShell.spec.mjs --workers=1 --reporter=list`
55+
56+
## Manual Validation Notes
57+
58+
1. Open `toolbox/sprites/index.html`.
59+
2. Confirm the 16x16 canvas shows a complete square with 16 rows and 16 columns.
60+
3. Switch to 32x32 and confirm a complete 32-row, 32-column grid.
61+
4. Switch through 100%, 200%, and 400% zoom and confirm the cell count and rows/columns do not change.
62+
5. Confirm no partial trailing row or right-edge orphan cells are visible.
63+
64+
## ZIP
65+
66+
`dev/workspace/zip/PR_26179_CHARLIE_038-sprites-grid-dimension-fix_delta.zip`
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
assets/toolbox/sprites/js/index.js
1+
assets/theme-v2/css/gamefoundrystudio.css
22
dev/tests/playwright/tools/SpritesToolShell.spec.mjs
3-
docs_build/dev/reports/PR_26179_CHARLIE_037-sprites-animation-export.md
3+
docs_build/dev/reports/PR_26179_CHARLIE_038-sprites-grid-dimension-fix.md
44
docs_build/dev/reports/codex_changed_files.txt
55
docs_build/dev/reports/codex_review.diff
66
toolbox/sprites/index.html

0 commit comments

Comments
 (0)