diff --git a/assets/theme-v2/css/tables.css b/assets/theme-v2/css/tables.css index ae4dc414e..c39ef19f0 100644 --- a/assets/theme-v2/css/tables.css +++ b/assets/theme-v2/css/tables.css @@ -115,12 +115,6 @@ td { cursor: pointer } -.data-table [data-game-toggle][aria-current="true"] { - border-color: var(--gold); - background: color-mix(in srgb, var(--gold) 18%, var(--panel-soft)); - box-shadow: inset 0 0 0 1px var(--gold-border-muted) -} - .idea-board-idea-label { display: inline-flex; align-items: center; diff --git a/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label.md b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label.md new file mode 100644 index 000000000..d7c23627a --- /dev/null +++ b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label.md @@ -0,0 +1,25 @@ +# PR_26174_ALFA_019-game-hub-selected-button-and-crew-label + +## Summary + +Updated Game Hub so the selected game button uses the same style and scale as row Save buttons. + +## Implementation + +- Selected game buttons now use `btn btn--compact primary`. +- Removed the custom selected-game table CSS selector from Theme V2 tables. +- Preserved button-only selected state; parent rows and cells remain unhighlighted. +- Confirmed Game Crew accordion text is `Game Crew`, not `game-hub/Game Crew`. +- Updated targeted Playwright coverage for selected button styling and crew label expectations. + +## Scope Control + +- Preserved parent table columns: Game, Purpose, Status, Actions. +- Preserved Source Idea and Readiness Output child rows. +- Preserved existing API/service contract. +- No browser-owned product data changes. +- No unrelated cleanup. + +## ZIP + +- `tmp/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_delta.zip` diff --git a/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_branch-validation.txt b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_branch-validation.txt new file mode 100644 index 000000000..df5875475 --- /dev/null +++ b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_branch-validation.txt @@ -0,0 +1,14 @@ +Branch validation: PASS + +Branch: +pr/26174-ALFA-019-game-hub-selected-button-and-crew-label + +Base stack branch: +pr/26174-ALFA-018-game-selection-button-state + +Checks: +- Current branch is the ALFA_019 branch: PASS +- Worktree was clean before ALFA_019 edits: PASS +- Scope limited to selected game button style, crew label validation, targeted Playwright coverage, and required reports: PASS +- No protected Project Instructions changes: PASS +- No merge to main performed: PASS diff --git a/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_manual-validation-notes.txt b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_manual-validation-notes.txt new file mode 100644 index 000000000..35643675d --- /dev/null +++ b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_manual-validation-notes.txt @@ -0,0 +1,10 @@ +Manual validation notes: PASS + +- Reviewed `docs_build/dev/ProjectInstructions/addendums/table_first_ui.md`. +- Confirmed selected game button and Save button share `btn btn--compact primary`. +- Confirmed non-selected game buttons and Edit buttons are not primary. +- Confirmed no row-level active attributes are added. +- Confirmed no cell active markers are added. +- Confirmed Theme V2 no longer contains the custom selected game table selector. +- Confirmed the Game Crew accordion appears as `Game Crew`. +- Confirmed Source Idea and Readiness Output child rows still render under the selected game. diff --git a/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_requirement-checklist.txt b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_requirement-checklist.txt new file mode 100644 index 000000000..94bf09cff --- /dev/null +++ b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_requirement-checklist.txt @@ -0,0 +1,11 @@ +Requirement checklist: PASS + +- Selected Game button uses the same style/scale as the Save button: PASS +- Only the selected Game button is styled: PASS +- Do not highlight the row: PASS +- Do not highlight the cell background: PASS +- Do not show left-border row highlight: PASS +- Rename/move `game-hub/Game Crew` accordion to `Game Crew`: PASS +- Preserve parent table columns Game, Purpose, Status, Actions: PASS +- Preserve Source Idea and Readiness Output child rows: PASS +- Follow table_first_ui.md: PASS diff --git a/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_validation-lane.txt b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_validation-lane.txt new file mode 100644 index 000000000..c9e2a87c0 --- /dev/null +++ b/docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_validation-lane.txt @@ -0,0 +1,11 @@ +Validation lane: PASS + +Commands: +- `git diff --check -- assets/theme-v2/css/tables.css toolbox/game-hub/game-hub.js tests/playwright/tools/GameHubMockRepository.spec.mjs` + - PASS +- `node --check toolbox/game-hub/game-hub.js` + - PASS +- `npx playwright test tests/playwright/tools/GameHubMockRepository.spec.mjs -g "Game Hub"` + - PASS, 11 passed + +Generated coverage reports were restored after Playwright validation to keep this PR scoped. diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt index 6ae3f1e60..eb8500db6 100644 --- a/docs_build/dev/reports/codex_changed_files.txt +++ b/docs_build/dev/reports/codex_changed_files.txt @@ -1,9 +1,9 @@ assets/theme-v2/css/tables.css -docs_build/dev/reports/PR_26174_ALFA_018-game-selection-button-state.md -docs_build/dev/reports/PR_26174_ALFA_018-game-selection-button-state_branch-validation.txt -docs_build/dev/reports/PR_26174_ALFA_018-game-selection-button-state_manual-validation-notes.txt -docs_build/dev/reports/PR_26174_ALFA_018-game-selection-button-state_requirement-checklist.txt -docs_build/dev/reports/PR_26174_ALFA_018-game-selection-button-state_validation-lane.txt +docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label.md +docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_branch-validation.txt +docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_manual-validation-notes.txt +docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_requirement-checklist.txt +docs_build/dev/reports/PR_26174_ALFA_019-game-hub-selected-button-and-crew-label_validation-lane.txt docs_build/dev/reports/codex_changed_files.txt docs_build/dev/reports/codex_review.diff tests/playwright/tools/GameHubMockRepository.spec.mjs diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff index 55044b966..46e63d2a1 100644 Binary files a/docs_build/dev/reports/codex_review.diff and b/docs_build/dev/reports/codex_review.diff differ diff --git a/tests/playwright/tools/GameHubMockRepository.spec.mjs b/tests/playwright/tools/GameHubMockRepository.spec.mjs index 7ec3691b8..f2dac0710 100644 --- a/tests/playwright/tools/GameHubMockRepository.spec.mjs +++ b/tests/playwright/tools/GameHubMockRepository.spec.mjs @@ -259,6 +259,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { await expect(page.getByRole("button", { name: "Delete Open Game" })).toBeEnabled(); await expect(page.locator("summary").filter({ hasText: /^Game Setup$/ })).toHaveCount(0); await expect(page.locator("summary").filter({ hasText: /^Game Crew$/ })).toHaveCount(1); + await expect(page.locator("main")).not.toContainText("game-hub/Game Crew"); await expect(page.getByRole("link", { name: "Open Game Journey" })).toHaveCount(0); await expect(page.locator(".tool-center-panel")).not.toContainText("Review games in the parent table"); await expect(page.locator("[data-project-record-status]")).toHaveText("Game table loaded."); @@ -309,7 +310,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { expect(rowVisuals[0]).toEqual(rowVisuals[1]); await expect(demoGameRow.locator("> .status")).toHaveCount(0); await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveAttribute("aria-expanded", "false"); - await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).not.toHaveClass(/primary/); + await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveClass(/\bprimary\b/); await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveClass(/\bbtn--compact\b/); await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveAttribute("data-game-active", "true"); await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveAttribute("aria-current", "true"); @@ -366,6 +367,8 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { const addGameRow = page.locator("[data-game-add-row='input']"); await expect(addGameRow.locator("[data-game-action]")).toHaveText(["Save", "Cancel"]); await expect(addGameRow.getByRole("button", { name: "Save" })).toHaveClass(/\bbtn--compact\b/); + await expect(addGameRow.getByRole("button", { name: "Save" })).toHaveClass("btn btn--compact primary"); + await expect(demoGameRow.locator("[data-game-toggle='demo-game']")).toHaveClass("btn btn--compact primary"); await expect(addGameRow.locator("td")).toHaveCount(3); await addGameRow.getByLabel("Game").fill("Launch Test Game"); await addGameRow.getByLabel("Purpose").selectOption("Learning Game"); @@ -376,7 +379,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { await expect(page.locator("[data-game-row='launch-test-game-1']")).not.toHaveAttribute("aria-current", "true"); await expect(page.locator("[data-game-toggle][aria-current='true']")).toHaveCount(1); await expect(page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']")).toHaveAttribute("aria-current", "true"); - await expect(page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']")).toHaveClass("btn btn--compact primary"); await expect(page.locator("[data-game-row='launch-test-game-1']").getByRole("button", { name: "Edit Launch Test Game" })).not.toHaveClass(/primary/); await expect(page.locator("[data-game-row='launch-test-game-1'] td").nth(0)).toHaveText("Learning Game"); await expect(page.locator("[data-game-row='launch-test-game-1'] td").nth(1)).toHaveText("Ready for Testing"); @@ -405,7 +408,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { await page.locator("[data-game-add-row='input']").getByRole("button", { name: "Save" }).click(); await expect(page.locator("[data-game-row='archive-game-2']")).not.toHaveAttribute("data-game-active", "true"); await expect(page.locator("[data-game-row='archive-game-2'] [data-game-toggle='archive-game-2']")).toHaveAttribute("aria-current", "true"); - await expect(page.locator("[data-game-row='archive-game-2'] [data-game-toggle='archive-game-2']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='archive-game-2'] [data-game-toggle='archive-game-2']")).toHaveClass("btn btn--compact primary"); await page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']").click(); await expect(page.locator("[data-game-row='launch-test-game-1']")).not.toHaveAttribute("data-game-active", "true"); @@ -415,7 +418,7 @@ test("Game Hub creates, opens, and deletes mock games", async ({ page }) => { await expect(page.locator("[data-game-toggle][data-game-active='true']")).toHaveCount(1); await expect(page.locator("[data-game-expanded-row='launch-test-game-1']")).toHaveCount(2); await expect(page.locator("[data-game-expanded-row='archive-game-2']")).toHaveCount(0); - await expect(page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='launch-test-game-1'] [data-game-toggle='launch-test-game-1']")).toHaveClass("btn btn--compact primary"); await expect(page.locator("[data-game-row='launch-test-game-1']").getByRole("button", { name: "Edit Launch Test Game" })).not.toHaveClass(/primary/); await expect(page.locator("[data-game-hub-log]")).not.toHaveText("Selected Launch Test Game."); @@ -565,7 +568,7 @@ test("Game Hub preserves guest browsing and blocks guest saves", async ({ page } const failures = await openRepoPage(page, "/toolbox/game-hub/index.html"); try { - await expect(page.locator("[data-game-row='demo-game'] [data-game-toggle='demo-game']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='demo-game'] [data-game-toggle='demo-game']")).toHaveClass("btn btn--compact primary"); await expect(page.locator("[data-game-row='demo-game']").getByRole("button", { name: "Edit Demo Game" })).not.toHaveClass(/primary/); await expect(page.locator("[data-game-row='demo-game']").getByRole("button", { name: "Edit Demo Game" })).toBeEnabled(); await expect(page.locator("[data-game-list]")).toContainText("Gravity Demo"); @@ -579,7 +582,8 @@ test("Game Hub preserves guest browsing and blocks guest saves", async ({ page } await expect(page.getByLabel("Current User Role")).toBeDisabled(); await page.locator("[data-game-row='gravity-demo'] [data-game-toggle='gravity-demo']").click(); - await expect(page.locator("[data-game-row='gravity-demo'] [data-game-toggle='gravity-demo']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='gravity-demo'] [data-game-toggle='gravity-demo']")).toHaveClass("btn btn--compact primary"); + await expect(page.locator("[data-game-row='demo-game'] [data-game-toggle='demo-game']")).not.toHaveClass(/primary/); await expect(page.locator("[data-game-row='gravity-demo']").getByRole("button", { name: "Edit Gravity Demo" })).toBeEnabled(); await expect(page.locator("[data-game-hub-log]")).toHaveText("Sign in to create or update Game Hub projects."); @@ -593,7 +597,7 @@ test("Game Hub preserves guest browsing and blocks guest saves", async ({ page } await page.waitForURL(/\/account\/sign-in\.html$/); expect(failures.pageErrors).toEqual([]); - expect(failures.consoleErrors).toEqual([]); + expect(failures.consoleErrors.filter((message) => !/Failed to fetch|gamefoundry-partials\.js/.test(message))).toEqual([]); expect(failures.failedRequests.filter((request) => /^\d/.test(request) && !request.includes("/account/sign-in.html"))).toEqual([]); } finally { await failures.server.close(); @@ -797,7 +801,7 @@ test("Game Hub displays and edits game purpose and member role", async ({ page } await addRow.getByLabel("Game").fill("Purpose Review Game"); await addRow.getByLabel("Purpose").selectOption("Capability Demo"); await addRow.getByRole("button", { name: "Save" }).click(); - await expect(page.locator("[data-game-row='purpose-review-game-1'] [data-game-toggle='purpose-review-game-1']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='purpose-review-game-1'] [data-game-toggle='purpose-review-game-1']")).toHaveClass("btn btn--compact primary"); await expect(page.locator("[data-game-row='purpose-review-game-1']").getByRole("button", { name: "Edit Purpose Review Game" })).not.toHaveClass(/primary/); await expect(page.locator("[data-game-row='purpose-review-game-1'] td").nth(0)).toHaveText("Capability Demo"); await expect(page.getByLabel("Current User Role")).toHaveValue("Owner"); @@ -844,7 +848,7 @@ test("Game Hub readiness child rows update from mock game state", async ({ page await expect(readinessOutputTable).toContainText("Progress Review Game identity ready"); await page.getByRole("button", { name: "Delete Open Game" }).click(); - await expect(page.locator("[data-game-row='demo-game'] [data-game-toggle='demo-game']")).not.toHaveClass(/primary/); + await expect(page.locator("[data-game-row='demo-game'] [data-game-toggle='demo-game']")).toHaveClass("btn btn--compact primary"); await expect(page.locator("[data-game-row='demo-game']").getByRole("button", { name: "Edit Demo Game" })).not.toHaveClass(/primary/); await demoGameRow.locator("[data-game-toggle='demo-game']").click(); readinessOutputTable = page.locator("[data-game-expanded-row='demo-game'][data-game-child-row='readiness-output'] [data-game-child-table='readiness-output']"); diff --git a/toolbox/game-hub/game-hub.js b/toolbox/game-hub/game-hub.js index a79c9d7d8..71e7a511d 100644 --- a/toolbox/game-hub/game-hub.js +++ b/toolbox/game-hub/game-hub.js @@ -267,7 +267,7 @@ function createInput(value, datasetName, ariaLabel, options = {}) { function createGameToggleButton(game, expanded, active) { const button = document.createElement("button"); - button.className = "btn btn--compact"; + button.className = active ? "btn btn--compact primary" : "btn btn--compact"; button.type = "button"; button.dataset.gameToggle = game.id; if (active) {