Skip to content

Commit 2e39dad

Browse files
committed
Recover input density work and add Palette checked-tag batch behavior - PR_26156_183-palette-checkbox-tag-batch-recovery
1 parent 3c7f148 commit 2e39dad

9 files changed

Lines changed: 361 additions & 52 deletions

File tree

assets/theme-v2/css/forms.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ select {
8383
padding: var(--space-12)
8484
}
8585

86+
.tool-form-control {
87+
box-sizing: border-box;
88+
height: var(--space-28);
89+
min-height: var(--space-28);
90+
padding: var(--space-3) var(--space-8);
91+
line-height: var(--line-height-sm)
92+
}
93+
8694
.field-value--readable-disabled:disabled {
8795
color: var(--text);
8896
-webkit-text-fill-color: var(--text);
@@ -169,6 +177,23 @@ input[type="color"][data-palette-swatch-size="large"] {
169177
align-items: flex-start
170178
}
171179

180+
.palette-swatch-item {
181+
position: relative;
182+
display: inline-flex
183+
}
184+
185+
.palette-swatch-check {
186+
position: absolute;
187+
top: calc(var(--space-8) * -1);
188+
left: calc(var(--space-8) * -1);
189+
z-index: var(--z-index-md);
190+
width: var(--space-14);
191+
height: var(--space-14);
192+
margin: var(--space-0);
193+
background: var(--panel);
194+
cursor: pointer
195+
}
196+
172197
.palette-swatch-tile {
173198
position: relative;
174199
display: inline-flex;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# PR_26156_183 Palette Checkbox Tag Batch Recovery Report
2+
3+
## Purpose
4+
Recover from incomplete PR_26156_182 work, keep only valid Palette input-density changes, and add checked-swatch batch tagging to the Active Project Palette.
5+
6+
## Recovery Decisions
7+
- Kept valid PR_26156_182 input-density slice:
8+
- `assets/theme-v2/css/forms.css` reusable `.tool-form-control`.
9+
- Palette-only `tool-form-control` usage in `toolbox/colors/index.html`.
10+
- Palette-only compact form-control assertions in `tests/playwright/tools/PaletteToolMockRepository.spec.mjs`.
11+
- Shared test helper `tests/helpers/toolFormControlAssertions.mjs`.
12+
- Reverted unrelated failed-run spillover:
13+
- `toolbox/assets/index.html`
14+
- `toolbox/game-design/index.html`
15+
- `toolbox/project-workspace/index.html`
16+
- `tests/playwright/tools/AssetToolMockRepository.spec.mjs`
17+
- `tests/playwright/tools/GameDesignMockRepository.spec.mjs`
18+
- `tests/playwright/tools/ProjectWorkspaceMockRepository.spec.mjs`
19+
- stale failed-run coverage guardrail output
20+
21+
## Implementation
22+
- Renamed the left-panel tag editor summary from `Swatch Editor` to `Project Palette Tags`.
23+
- Added a compact `Clear Checked` button at the bottom of Project Palette Tags.
24+
- Added a checkbox control to every Active Project Palette swatch.
25+
- Added `addTagToSwatches` in the Palette repository to append one normalized tag to checked swatches while preserving current selection.
26+
- Updated tag entry behavior:
27+
- checked swatches present: add tag to checked swatches.
28+
- no checked swatches: add tag only to selected swatch.
29+
- empty tag input: no action.
30+
- Added Theme V2 Palette swatch checkbox styling under `assets/theme-v2/css/forms.css`; no page-local CSS, tool-local CSS, inline styles, `<style>` blocks, or inline event handlers were added.
31+
32+
## Validation
33+
- Targeted Palette Tool runtime/UI lane: PASS.
34+
- Checked swatches receive new tags: PASS.
35+
- Clear Checked clears checked swatches: PASS.
36+
- Unchecked swatches are not modified: PASS.
37+
- Selected-only fallback works when none are checked: PASS.
38+
- No auto-add before Enter: PASS.
39+
- Changed-file/static validation: PASS.
40+
- Recovery removed unrelated failed-run edits: PASS.
41+
- Full samples smoke: SKIP by BUILD instruction.
42+
43+
## Required Artifacts
44+
- `docs_build/dev/reports/testing_lane_execution_report.md`
45+
- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
46+
- `docs_build/dev/reports/codex_review.diff`
47+
- `docs_build/dev/reports/codex_changed_files.txt`

docs_build/dev/reports/playwright_v8_coverage_report.txt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,28 @@ Note: entry percentages use function coverage when available, otherwise line cov
1212
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
1313

1414
Exercised tool entry points detected:
15-
(87%) Toolbox Index - exercised 5 runtime JS files
15+
(88%) Toolbox Index - exercised 5 runtime JS files
1616
(0%) Tool Template V2 - not exercised by this Playwright run
1717
(83%) Theme V2 Shared JS - exercised 2 runtime JS files
1818

1919
Changed runtime JS files covered:
20-
(89%) toolbox/colors/palette-workspace-repository.js - executed lines 1244/1244; executed functions 125/140
21-
(96%) toolbox/colors/colors.js - executed lines 831/831; executed functions 82/85
20+
(90%) toolbox/colors/palette-workspace-repository.js - executed lines 1288/1288; executed functions 129/144
21+
(97%) toolbox/colors/colors.js - executed lines 883/883; executed functions 88/91
2222

2323
Files with executed line/function counts where available:
2424
(65%) toolbox/project-workspace/project-workspace-mock-repository.js - executed lines 402/402; executed functions 20/31
2525
(75%) toolbox/toolRegistry.js - executed lines 1754/1754; executed functions 27/36
2626
(80%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 205/205; executed functions 16/20
2727
(87%) assets/theme-v2/js/tool-display-mode.js - executed lines 201/201; executed functions 13/15
28-
(89%) toolbox/colors/palette-workspace-repository.js - executed lines 1244/1244; executed functions 125/140
29-
(96%) toolbox/colors/colors.js - executed lines 831/831; executed functions 82/85
28+
(90%) toolbox/colors/palette-workspace-repository.js - executed lines 1288/1288; executed functions 129/144
29+
(97%) toolbox/colors/colors.js - executed lines 883/883; executed functions 88/91
3030
(100%) toolbox/colors/palette-source-mock-db.js - executed lines 927/927; executed functions 6/6
3131

3232
Uncovered or low-coverage changed JS files:
3333
(100%) none - no low-coverage changed runtime JS files
3434

3535
Changed JS files considered:
36+
(0%) tests/helpers/toolFormControlAssertions.mjs - changed JS file not collected as browser runtime coverage
3637
(0%) tests/playwright/tools/PaletteToolMockRepository.spec.mjs - changed JS file not collected as browser runtime coverage
37-
(89%) toolbox/colors/palette-workspace-repository.js - changed JS file with browser V8 coverage
38-
(96%) toolbox/colors/colors.js - changed JS file with browser V8 coverage
38+
(90%) toolbox/colors/palette-workspace-repository.js - changed JS file with browser V8 coverage
39+
(97%) toolbox/colors/colors.js - changed JS file with browser V8 coverage
Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PR_26156_181 Testing Lane Execution Report
1+
# PR_26156_183 Testing Lane Execution Report
22

33
## Result
44
PASS
@@ -10,43 +10,45 @@ PASS
1010
- PASS
1111
- `node --check tests/playwright/tools/PaletteToolMockRepository.spec.mjs`
1212
- PASS
13-
- `rg -n "DEFAULT_SOURCE_PALETTES|style=|<style|onclick|onchange|oninput|onsubmit" toolbox/colors/index.html toolbox/colors/colors.js toolbox/colors/palette-workspace-repository.js tests/playwright/tools/PaletteToolMockRepository.spec.mjs assets/theme-v2/css/forms.css`
14-
- PASS, no matches
15-
- `npx playwright test tests/playwright/tools/PaletteToolMockRepository.spec.mjs --project=playwright --workers=1 --reporter=list`
16-
- PASS, 3 tests
13+
- `node --check tests/helpers/toolFormControlAssertions.mjs`
14+
- PASS
15+
- `node node_modules/@playwright/test/cli.js test tests/playwright/tools/PaletteToolMockRepository.spec.mjs --project=playwright --workers=1 --reporter=list`
16+
- PASS, 4 tests
1717
- `npm run test:playwright:static`
1818
- PASS
19-
- `git diff --check -- assets/theme-v2/css/forms.css toolbox/colors/index.html toolbox/colors/colors.js toolbox/colors/palette-workspace-repository.js tests/playwright/tools/PaletteToolMockRepository.spec.mjs`
19+
- `Select-String -Path toolbox/colors/index.html -Pattern '<style\\b|\\s(onclick|onchange|oninput|onsubmit|onkeydown|onkeyup|onload)=' -CaseSensitive`
20+
- PASS, no matches
21+
- `Select-String -Path toolbox/colors/index.html -Pattern '<script(?![^>]*\\bsrc=)' -CaseSensitive`
22+
- PASS, no inline script blocks
23+
- `Select-String -Path toolbox/colors/index.html -Pattern '\\sstyle=' -CaseSensitive`
24+
- PASS, no inline styles
25+
- `git diff -- toolbox/assets/index.html toolbox/game-design/index.html toolbox/project-workspace/index.html tests/playwright/tools/AssetToolMockRepository.spec.mjs tests/playwright/tools/GameDesignMockRepository.spec.mjs tests/playwright/tools/ProjectWorkspaceMockRepository.spec.mjs`
26+
- PASS, no remaining unrelated failed-run diffs
27+
- `git diff --check -- assets/theme-v2/css/forms.css toolbox/colors/index.html toolbox/colors/colors.js toolbox/colors/palette-workspace-repository.js tests/playwright/tools/PaletteToolMockRepository.spec.mjs tests/helpers/toolFormControlAssertions.mjs docs_build/dev/reports/palette-checkbox-tag-batch-recovery-report.md docs_build/dev/reports/testing_lane_execution_report.md docs_build/dev/reports/playwright_v8_coverage_report.txt`
2028
- PASS with Git LF-to-CRLF warnings for touched files
2129

22-
## Required Lanes
23-
- Targeted Palette Tool User Defined runtime/UI lane: PASS.
24-
- Changed-file/static validation: PASS.
25-
26-
## Playwright Coverage
27-
- Add User Defined disabled after successful add: PASS.
28-
- Successful add keeps Symbol/Hex/Name visible: PASS.
29-
- Repeat-click duplicate add failure prevented by disabled Add state: PASS.
30-
- Add User Defined re-enables only for a valid unique new swatch: PASS.
31-
- Selecting a source-backed color clears User Defined fields: PASS.
32-
- Selecting a user-defined color populates User Defined fields: PASS.
33-
- Hex preview appears in the left column immediately after the Hex label: PASS.
34-
- Hex preview updates valid/invalid state: PASS.
35-
- Tooltip Source remains newline-separated in browser title text: PASS.
30+
## Runtime/UI Coverage
31+
- Project Palette Tags label replaces Swatch Editor: PASS.
32+
- Each Active Project Palette swatch renders a small upper-left checkbox: PASS.
33+
- Typing in the tag field does not auto-add tags before Enter: PASS.
34+
- With checked swatches, Enter adds the new tag to every checked swatch: PASS.
35+
- Unchecked swatches keep their existing tags unchanged: PASS.
36+
- Clear Checked clears all checked swatches and disables itself: PASS.
37+
- With no checked swatches, Enter falls back to the selected swatch only: PASS.
38+
- Existing Palette add/update/pin/harmony/fullscreen behavior remains covered by the targeted Palette spec: PASS.
3639

3740
## Impacted Lane
38-
- Palette Tool User Defined runtime/UI lane.
41+
- Targeted Palette Tool runtime/UI lane.
3942
- Changed-file/static validation lane.
4043

4144
## Skipped Lanes
42-
- Full samples smoke was skipped by BUILD instruction.
43-
- Broader tool lanes were skipped because behavior changes are confined to Palette Tool User Defined state and a reusable Theme V2 form utility exercised by the targeted Palette Tool spec.
44-
45-
## Not Run
46-
- Full samples smoke was not run, per BUILD instruction.
45+
- Full samples smoke: SKIP by BUILD instruction.
46+
- Broader tool lanes: SKIP because PR_26156_183 changes are confined to Palette Tool runtime/UI, Palette repository tag behavior, Theme V2 Palette swatch styling, and Palette tests.
47+
- Engine lane: SKIP because no engine/core files changed.
4748

4849
## Notes
49-
- Static validation generated companion reports during the run; non-required generated companion report updates were restored to prior contents so the PR remains scoped to requested report artifacts.
50+
- The package script name `test:workspace-v2` remains legacy repo wording; this PR uses user-facing Project Palette Tags and Project Workspace naming in changed UI/report prose.
51+
- Static validation generated companion reports during execution. Non-required companion report updates were restored so the PR remains scoped to requested artifacts.
5052

5153
## Coverage Artifact
52-
- Final V8 coverage artifact: `docs_build/dev/reports/playwright_v8_coverage_report.txt`.
54+
- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { expect } from "@playwright/test";
2+
3+
const COMPACT_TOOL_FORM_CONTROL_MAX_HEIGHT = 32;
4+
const COMPACT_TOOL_FORM_CONTROL_MIN_HEIGHT = 24;
5+
6+
async function controlHeight(locator) {
7+
return locator.evaluate((node) => node.getBoundingClientRect().height);
8+
}
9+
10+
export async function expectCompactToolFormControl(locator) {
11+
await expect(locator).toHaveClass(/tool-form-control/);
12+
const height = await controlHeight(locator);
13+
expect(height).toBeGreaterThanOrEqual(COMPACT_TOOL_FORM_CONTROL_MIN_HEIGHT);
14+
expect(height).toBeLessThanOrEqual(COMPACT_TOOL_FORM_CONTROL_MAX_HEIGHT);
15+
return height;
16+
}
17+
18+
export async function expectCompactToolFormControls(page, selectors) {
19+
const heights = [];
20+
for (const selector of selectors) {
21+
heights.push(await expectCompactToolFormControl(page.locator(selector)));
22+
}
23+
return heights;
24+
}
25+
26+
export async function expectFilePickerRemainsDefault(fileInput, compactReference) {
27+
await expect(fileInput).not.toHaveClass(/tool-form-control/);
28+
const fileHeight = await controlHeight(fileInput);
29+
const compactHeight = await controlHeight(compactReference);
30+
expect(fileHeight).toBeGreaterThan(compactHeight + 4);
31+
return fileHeight;
32+
}

tests/playwright/tools/PaletteToolMockRepository.spec.mjs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from "../../../toolbox/colors/palette-workspace-repository.js";
77
import { startRepoServer } from "../../helpers/playwrightRepoServer.mjs";
88
import { clearPlaywrightStorage, installPlaywrightStorageIsolation } from "../../helpers/playwrightStorageIsolation.mjs";
9+
import { expectCompactToolFormControls } from "../../helpers/toolFormControlAssertions.mjs";
910
import { workspaceV2CoverageReporter } from "../../helpers/workspaceV2CoverageReporter.mjs";
1011

1112
const sourcePaletteRows = [
@@ -341,6 +342,13 @@ test("Palette repository owns active project swatches without mutating invalid p
341342
expect(repeatPinAllResult.message).toContain("0 pinned, 2 already pinned");
342343
expect(repository.listSwatches().filter((swatch) => swatch.source === "reference")).toHaveLength(sourceCountAfterPinAll);
343344
expect(repository.getSnapshot().selectedSwatch).toMatchObject({ name: "Reference Green", symbol: "G" });
345+
const batchTagResult = repository.addTagToSwatches(["J", "R"], "batch");
346+
expect(batchTagResult.ok).toBe(true);
347+
expect(batchTagResult.message).toBe("Added tag batch to 2 checked swatches.");
348+
expect(repository.findSwatch("J")).toMatchObject({ name: "Hero Updated", tags: ["primary", "batch"] });
349+
expect(repository.findSwatch("R")).toMatchObject({ name: "Reference Red", tags: ["batch"] });
350+
expect(repository.findSwatch("G")).toMatchObject({ name: "Reference Green", tags: [] });
351+
expect(repository.getSnapshot().selectedSwatch).toMatchObject({ name: "Reference Green", symbol: "G" });
344352

345353
const bulkPinRepository = createProjectWorkspacePaletteRepository({ sourcePaletteRows });
346354
const bulkSourceSwatches = bulkPinRepository.listSourceSwatches({ sourceId: "reference", sortKey: "hue" });
@@ -477,6 +485,20 @@ test("Palette Tool adds, updates, pins, validates, and shows project-owned detai
477485
await expect(page.locator("[data-palette-tags]")).toBeDisabled();
478486
await expect(page.locator("[data-palette-tags]")).toHaveValue("");
479487
await expect(page.locator("[data-palette-editor-form] input[placeholder], [data-palette-user-swatch-form] input[placeholder]")).toHaveCount(0);
488+
await expectCompactToolFormControls(page, [
489+
"[data-palette-selected-symbol]",
490+
"[data-palette-selected-hex]",
491+
"[data-palette-selected-name]",
492+
"[data-palette-tags]",
493+
"[data-palette-symbol]",
494+
"[data-palette-hex]",
495+
"[data-palette-name]",
496+
"[data-palette-source-select]",
497+
"[data-palette-source-search]",
498+
"[data-palette-harmony-match]",
499+
"[data-palette-harmony-scheme]"
500+
]);
501+
await expect(page.locator("[data-palette-user-hex-preview]")).not.toHaveClass(/tool-form-control/);
480502
await expect(page.locator("[data-palette-editor-tags-input-row] th")).toHaveAttribute("rowspan", "2");
481503
const tagInputRowBox = await page.locator("[data-palette-editor-tags-input-row]").boundingBox();
482504
const tagListRowBox = await page.locator("[data-palette-editor-tags-list-row]").boundingBox();
@@ -849,6 +871,75 @@ test("Palette Tool adds, updates, pins, validates, and shows project-owned detai
849871
}
850872
});
851873

874+
test("Palette Tool batch tags checked project palette swatches", async ({ page }) => {
875+
const failures = await openRepoPage(page, "/toolbox/colors/index.html");
876+
877+
try {
878+
await expect(page.getByText("Project Palette Tags")).toBeVisible();
879+
await expect(page.getByText("Swatch Editor")).toHaveCount(0);
880+
await expect(page.locator("[data-palette-clear-checked]")).toBeDisabled();
881+
882+
await page.locator("[data-palette-source-select]").selectOption("palette-colors008");
883+
await page.locator("[data-palette-source-pin-all]").click();
884+
await expect(page.locator("[data-palette-count]")).toHaveText("8");
885+
await expect(page.locator("[data-palette-swatch-check]")).toHaveCount(8);
886+
887+
const blackItem = page.locator("[data-palette-swatch-item]", {
888+
has: page.locator("[data-palette-swatch-name='Black']")
889+
});
890+
const brownItem = page.locator("[data-palette-swatch-item]", {
891+
has: page.locator("[data-palette-swatch-name='Brown']")
892+
});
893+
const blueItem = page.locator("[data-palette-swatch-item]", {
894+
has: page.locator("[data-palette-swatch-name='Blue']")
895+
});
896+
const blackTile = blackItem.locator("[data-palette-swatch-row]");
897+
const brownTile = brownItem.locator("[data-palette-swatch-row]");
898+
const blueTile = blueItem.locator("[data-palette-swatch-row]");
899+
const blackCheck = blackItem.locator("[data-palette-swatch-check]");
900+
const brownCheck = brownItem.locator("[data-palette-swatch-check]");
901+
902+
await blackTile.click();
903+
await expect(page.locator("[data-palette-selected-summary]")).toHaveText("Black");
904+
const checkBox = await blackCheck.boundingBox();
905+
const tileBox = await blackTile.boundingBox();
906+
expect((checkBox?.x || 0) - (tileBox?.x || 0)).toBeLessThan(10);
907+
expect((checkBox?.y || 0) - (tileBox?.y || 0)).toBeLessThan(10);
908+
909+
await page.locator("[data-palette-tags]").fill("solo");
910+
await expect(blackTile).toHaveAttribute("data-palette-swatch-tags", "");
911+
await page.locator("[data-palette-tags]").press("Enter");
912+
await expect(blackTile).toHaveAttribute("data-palette-swatch-tags", "solo");
913+
await expect(brownTile).toHaveAttribute("data-palette-swatch-tags", "");
914+
await expect(blueTile).toHaveAttribute("data-palette-swatch-tags", "");
915+
916+
await blackCheck.check();
917+
await brownCheck.check();
918+
await expect(page.locator("[data-palette-clear-checked]")).toBeEnabled();
919+
await page.locator("[data-palette-tags]").fill("batch");
920+
await page.locator("[data-palette-tags]").press("Enter");
921+
await expect(blackTile).toHaveAttribute("data-palette-swatch-tags", "solo, batch");
922+
await expect(brownTile).toHaveAttribute("data-palette-swatch-tags", "batch");
923+
await expect(blueTile).toHaveAttribute("data-palette-swatch-tags", "");
924+
925+
await page.locator("[data-palette-clear-checked]").click();
926+
await expect(blackCheck).not.toBeChecked();
927+
await expect(brownCheck).not.toBeChecked();
928+
await expect(page.locator("[data-palette-clear-checked]")).toBeDisabled();
929+
930+
await page.locator("[data-palette-tags]").fill("afterclear");
931+
await page.locator("[data-palette-tags]").press("Enter");
932+
await expect(blackTile).toHaveAttribute("data-palette-swatch-tags", "solo, batch, afterclear");
933+
await expect(brownTile).toHaveAttribute("data-palette-swatch-tags", "batch");
934+
await expect(blueTile).toHaveAttribute("data-palette-swatch-tags", "");
935+
936+
expectNoPageFailures(failures);
937+
} finally {
938+
await workspaceV2CoverageReporter.stop(page);
939+
await failures.server.close();
940+
}
941+
});
942+
852943
test("Palette Tool rejects invalid payloads before render and blocks editing without an active project", async ({ page }) => {
853944
const invalidFailures = await openRepoPage(page, "/toolbox/colors/index.html?palette=invalid");
854945

0 commit comments

Comments
 (0)