Skip to content

Commit 016ebee

Browse files
committed
PR_26175_ALFA_050 theme v2 layout utility icons
1 parent 245c30d commit 016ebee

14 files changed

Lines changed: 442 additions & 102 deletions

assets/theme-v2/css/buttons.css

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,16 @@
112112
transition: opacity var(--transition-duration-fast) ease, transform var(--transition-duration-fast) ease, color var(--transition-duration-fast) ease, border-color var(--transition-duration-fast) ease, background var(--transition-duration-fast) ease
113113
}
114114

115-
.return-to-top span {
115+
.return-to-top span,
116+
.return-to-top__icon {
116117
transform: translateY(var(--return-to-top-glyph-shift))
117118
}
118119

120+
.return-to-top__icon {
121+
height: var(--icon-size-sm);
122+
width: var(--icon-size-sm)
123+
}
124+
119125
.return-to-top.is-visible {
120126
opacity: 1;
121127
pointer-events: auto;

assets/theme-v2/css/icons.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@
107107
--theme-v2-icon-url: url("/assets/theme-v2/svg/gfs-warning.svg")
108108
}
109109

110+
.layout-icon {
111+
height: var(--icon-size-sm);
112+
width: var(--icon-size-sm)
113+
}
114+
110115
.status-icon {
111116
height: var(--icon-size-sm);
112117
width: var(--icon-size-sm)

assets/theme-v2/css/panels.css

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ body.tool-focus-mode .tool-center-panel:has(>details.vertical-accordion)>p {
298298
display: none
299299
}
300300

301+
.tool-display-mode__mode-icon {
302+
color: var(--cyan)
303+
}
304+
301305
.tool-display-mode__chevron {
302306
position: absolute;
303307
right: var(--space-12);
@@ -340,6 +344,27 @@ body.tool-focus-mode .tool-center-panel:has(>details.vertical-accordion)>p {
340344
flex-wrap: wrap
341345
}
342346

347+
.tool-display-mode__navigation-link {
348+
align-items: center;
349+
color: var(--text);
350+
display: inline-flex;
351+
gap: var(--space-6);
352+
line-height: var(--line-height-tight)
353+
}
354+
355+
.tool-display-mode__navigation-link:hover,
356+
.tool-display-mode__navigation-link:focus-visible {
357+
color: var(--gold)
358+
}
359+
360+
.tool-display-mode__navigation-link--disabled {
361+
color: var(--muted)
362+
}
363+
364+
.tool-display-mode__navigation-icon {
365+
color: currentColor
366+
}
367+
343368
.tool-display-mode__character {
344369
grid-column: 1;
345370
grid-row: 1 / span 2;

assets/theme-v2/js/gamefoundry-partials.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127

128128
const currentScript = document.currentScript || document.querySelector("script[src*='gamefoundry-partials.js']");
129129
const assetRoot = currentScript ? new URL("../", currentScript.src) : null;
130+
let themeIconRegistry = window.ThemeV2Icons || null;
130131
let navigationAdminMenuCache = null;
131132
let publicConfigCache = null;
132133
let publicConfigDataCache = null;
@@ -325,6 +326,54 @@
325326
return new URL(path.replace(/^assets\//, ""), assetRoot).href;
326327
}
327328

329+
function fallbackThemeIconFileName(name) {
330+
return "gfs-" + name + ".svg";
331+
}
332+
333+
function createThemeIconNode(name, className) {
334+
if (themeIconRegistry && typeof themeIconRegistry.createThemeIcon === "function") {
335+
return themeIconRegistry.createThemeIcon(name, { className });
336+
}
337+
338+
const icon = document.createElement("span");
339+
icon.className = ["theme-icon", "theme-icon--" + name, className].filter(Boolean).join(" ");
340+
icon.dataset.themeIcon = name;
341+
icon.dataset.themeIconFile = fallbackThemeIconFileName(name);
342+
icon.setAttribute("aria-hidden", "true");
343+
return icon;
344+
}
345+
346+
function horizontalToggleIconName(button) {
347+
const expanded = button.getAttribute("aria-expanded") !== "false";
348+
const isLeft = button.classList.contains("horizontal-accordion-toggle--left");
349+
if (isLeft) {
350+
return expanded ? "chevron-left" : "chevron-right";
351+
}
352+
return expanded ? "chevron-right" : "chevron-left";
353+
}
354+
355+
function updateHorizontalToggleIcon(button) {
356+
button.replaceChildren(createThemeIconNode(horizontalToggleIconName(button), "layout-icon horizontal-accordion-toggle__icon"));
357+
}
358+
359+
function updateReturnToTopIcon(button) {
360+
button.replaceChildren(createThemeIconNode("chevron-up", "layout-icon return-to-top__icon"));
361+
}
362+
363+
function refreshUtilityIcons(root) {
364+
(root || document).querySelectorAll(".horizontal-accordion-toggle").forEach(updateHorizontalToggleIcon);
365+
(root || document).querySelectorAll("[data-return-to-top]").forEach(updateReturnToTopIcon);
366+
}
367+
368+
function loadThemeIcons() {
369+
import(assetUrl("js/theme-icons.js")).then(function (module) {
370+
themeIconRegistry = module;
371+
refreshUtilityIcons(document);
372+
}).catch(function () {
373+
themeIconRegistry = window.ThemeV2Icons || themeIconRegistry;
374+
});
375+
}
376+
328377
function currentPagePath() {
329378
const parts = window.location.pathname.split("/").filter(Boolean);
330379
const rootIndex = parts.findIndex(function (part) {
@@ -934,7 +983,7 @@
934983
button.dataset.accountSideNavCollapse = "";
935984
button.setAttribute("aria-label", "Collapse " + label);
936985
button.setAttribute("aria-expanded", "true");
937-
button.textContent = "<";
986+
updateHorizontalToggleIcon(button);
938987
header.insertBefore(button, header.firstChild);
939988

940989
button.addEventListener("click", function () {
@@ -943,15 +992,16 @@
943992
if (accountPanel) {
944993
accountPanel.classList.toggle("is-left-collapsed", collapsed);
945994
}
946-
button.textContent = collapsed ? ">" : "<";
947995
button.setAttribute("aria-expanded", collapsed ? "false" : "true");
948996
button.setAttribute("aria-label", (collapsed ? "Expand " : "Collapse ") + label);
997+
updateHorizontalToggleIcon(button);
949998
});
950999
}
9511000

9521001
function wireReturnToTop(root) {
9531002
const button = root.querySelector("[data-return-to-top]");
9541003
if (!button) return;
1004+
updateReturnToTopIcon(button);
9551005

9561006
function updateVisibility() {
9571007
button.classList.toggle("is-visible", window.scrollY > 280);
@@ -1075,6 +1125,7 @@
10751125
}
10761126

10771127
enforcePageProtection();
1128+
loadThemeIcons();
10781129
document.addEventListener("DOMContentLoaded", function () {
10791130
enforcePageProtection();
10801131
const slots = Array.from(document.querySelectorAll("[data-partial]"));

assets/theme-v2/js/tool-display-mode.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,14 @@
7979
replaceIconNode(summary, ":scope > .tool-display-mode__chevron", shell);
8080
}
8181

82+
function updateToolDisplayModeModeIcon() {
83+
const iconName = document.body.classList.contains("tool-focus-mode") || document.fullscreenElement
84+
? "exit-fullscreen"
85+
: "fullscreen";
86+
const icon = createThemeIconNode(iconName, "layout-icon tool-display-mode__mode-icon");
87+
replaceIconNode(summary, ":scope > .tool-display-mode__mode-icon", icon);
88+
}
89+
8290
function horizontalToggleIconName(button) {
8391
const expanded = button.getAttribute("aria-expanded") !== "false";
8492
const isLeft = button.classList.contains("horizontal-accordion-toggle--left");
@@ -98,6 +106,7 @@
98106

99107
function refreshThemeIcons() {
100108
refreshVerticalAccordionChevrons();
109+
updateToolDisplayModeModeIcon();
101110
updateToolDisplayModeChevron();
102111
refreshHorizontalToggleIcons();
103112
}
@@ -137,6 +146,7 @@
137146
const summary = document.createElement("summary");
138147
summary.setAttribute("aria-label", "Tool Display Mode");
139148
summary.title = "Tool Display Mode";
149+
summary.appendChild(createThemeIconNode("fullscreen", "layout-icon tool-display-mode__mode-icon"));
140150

141151
const badge = document.createElement("img");
142152
badge.className = "tool-display-mode__badge";
@@ -175,22 +185,26 @@
175185
function createNavigationControl(direction, target) {
176186
const controlLabel = direction === "previous" ? "Previous" : "Next";
177187
const dataAttribute = direction === "previous" ? "toolNavPrevious" : "toolNavNext";
188+
const iconName = direction === "previous" ? "chevron-left" : "chevron-right";
189+
const icon = createThemeIconNode(iconName, "layout-icon tool-display-mode__navigation-icon");
190+
const label = document.createTextNode(controlLabel + ": " + (target?.label || "Unavailable"));
178191

179192
if (!target || target.disabled) {
180193
const disabledText = document.createElement("span");
181-
disabledText.className = "pill";
194+
disabledText.className = "pill tool-display-mode__navigation-link tool-display-mode__navigation-link--disabled";
182195
disabledText.dataset[dataAttribute] = "disabled";
183-
disabledText.textContent = controlLabel + ": " + (target?.label || "Unavailable");
196+
disabledText.append(icon, label);
184197
return disabledText;
185198
}
186199

187200
const link = document.createElement("a");
201+
link.className = "tool-display-mode__navigation-link";
188202
link.href = target.href;
189203
link.dataset[dataAttribute] = target.kind;
190204
if (target.group) {
191205
link.dataset.toolNavGroup = target.group;
192206
}
193-
link.textContent = controlLabel + ": " + target.label;
207+
link.append(icon, label);
194208
return link;
195209
}
196210

@@ -259,6 +273,7 @@
259273
async function enterToolMode() {
260274
document.body.classList.add("tool-focus-mode");
261275
displayMode.open = false;
276+
updateToolDisplayModeModeIcon();
262277

263278
try {
264279
if (!document.fullscreenElement && document.documentElement.requestFullscreen) {
@@ -272,6 +287,7 @@
272287
async function exitToolMode() {
273288
document.body.classList.remove("tool-focus-mode");
274289
displayMode.open = true;
290+
updateToolDisplayModeModeIcon();
275291

276292
try {
277293
if (document.fullscreenElement && document.exitFullscreen) {
@@ -296,6 +312,7 @@
296312
if (!document.fullscreenElement && document.body.classList.contains("tool-focus-mode")) {
297313
document.body.classList.remove("tool-focus-mode");
298314
displayMode.open = true;
315+
refreshThemeIcons();
299316
}
300317
});
301318

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# PR_26175_ALFA_050 Manual Validation Notes
2+
3+
## Notes
4+
- Manual validation was performed through the required targeted Playwright lanes rather than an ad hoc browser session.
5+
- Route tests pin the API/site URL to the repo test server so the pages do not drift to a local dev endpoint.
6+
- Toolbox vote route assertions were made deterministic against the configured product-data provider by reading current vote state, asserting state transitions, and restoring touched Colors metadata/order.
7+
- No visual redesign was performed; changes are limited to replacing utility text/placeholders with shared Theme V2 SVG icon nodes and matching compact CSS.
8+
- No files under `start_of_day` were read or modified.
9+
10+
## Residual Risk
11+
- Full cross-browser or mobile manual review was not run beyond the existing targeted Playwright coverage.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# PR_26175_ALFA_050-theme-v2-layout-utility-icons Report
2+
3+
## Summary
4+
- Branch validation: PASS.
5+
- Base branch state: `245c30dda` (`Merge PR #167: PR_26175_CHARLIE_027-final-charlie-audit`).
6+
- Scope: Theme V2 layout utility controls now use shared registry SVG icons for fullscreen mode, previous/next navigation, horizontal column toggles, and return-to-top.
7+
- Runtime/UI scope: no broad redesign, no engine core changes, no `start_of_day` changes, and no page-local inline styles or style blocks introduced.
8+
9+
## Changed Files
10+
- `assets/theme-v2/css/buttons.css`
11+
- `assets/theme-v2/css/icons.css`
12+
- `assets/theme-v2/css/panels.css`
13+
- `assets/theme-v2/js/gamefoundry-partials.js`
14+
- `assets/theme-v2/js/tool-display-mode.js`
15+
- `tests/playwright/tools/ThemeV2SvgIconRegistry.spec.mjs`
16+
- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
17+
- `tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs`
18+
- `docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_report.md`
19+
- `docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_validation-lane.md`
20+
- `docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_requirements-checklist.md`
21+
- `docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_manual-validation-notes.md`
22+
- `docs_build/dev/reports/codex_review.diff`
23+
- `docs_build/dev/reports/codex_changed_files.txt`
24+
25+
## Implementation Notes
26+
- `tool-display-mode.js` renders shared fullscreen/exit-fullscreen icons in the mode summary and shared chevron icons for previous/next controls while preserving existing labels and links.
27+
- `gamefoundry-partials.js` loads the Theme V2 icon registry for shared partial utilities, replacing account side-nav text glyphs and return-to-top placeholders with registry icons.
28+
- `icons.css`, `buttons.css`, and `panels.css` add compact shared layout-icon sizing and layout utility presentation without inline styles.
29+
- Tests assert the new layout utility icons and keep route coverage deterministic against the configured product-data provider.
30+
31+
## Validation Summary
32+
- PASS: syntax checks for the touched Theme V2 scripts.
33+
- PASS: targeted Playwright registry, selected-game status bar, and route suites.
34+
- PASS: inline style/style-block scan returned no matches.
35+
- PASS: `git diff --check`.
36+
37+
## Branch Validation
38+
- PASS: Branch is `codex/pr-26175-alfa-050-theme-v2-layout-utility-icons`.
39+
- PASS: Changes are limited to ALFA_050 target implementation, tests, and required reports.
40+
- PASS: Repo-structured ZIP will be emitted under `tmp/` and not staged.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# PR_26175_ALFA_050 Requirements Checklist
2+
3+
| Requirement | Status | Evidence |
4+
| --- | --- | --- |
5+
| Use shared icons for fullscreen enter/exit controls. | PASS | `tool-display-mode.js` adds fullscreen and exit-fullscreen registry icons; status-bar Playwright asserts both files. |
6+
| Use shared icons for previous/next navigation. | PASS | Tool display navigation prepends shared chevron-left/chevron-right icons; Playwright asserts both files. |
7+
| Use shared icons for column collapse/expand controls. | PASS | Horizontal accordion toggles render shared chevron icons through the Theme V2 helper path. |
8+
| Use shared icons for return-to-top controls. | PASS | Shared partials replace return-to-top content with the registry chevron-up icon; route Playwright asserts it. |
9+
| Preserve accessible names, roles, and keyboard behavior. | PASS | Existing button/link labels and aria attributes are retained while icons are `aria-hidden`. |
10+
| Preserve fullscreen bottom status bar anchoring and content reserve. | PASS | Selected-game status bar Playwright suite passed. |
11+
| Keep utility controls compact and stable. | PASS | Shared `.layout-icon` sizing and navigation-link styles were added without layout refactors. |
12+
| Avoid page-local utility icon markup when shared helpers can own it. | PASS | Shared partial/helper paths own return-to-top and horizontal toggle icon replacement. |
13+
| No inline styles, style blocks, or page-local CSS introduced. | PASS | Targeted `rg` scan returned no matches. |
14+
| No unrelated page/tool redesign. | PASS | Changes are limited to layout utility icon rendering, compact CSS, tests, and reports. |
15+
| No engine core or `start_of_day` changes. | PASS | No engine or `start_of_day` files changed. |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# PR_26175_ALFA_050 Validation Lane
2+
3+
## Static Checks
4+
- PASS: `node --check assets/theme-v2/js/theme-icons.js`
5+
- PASS: `node --check assets/theme-v2/js/tool-display-mode.js`
6+
- PASS: `node --check assets/theme-v2/js/gamefoundry-partials.js`
7+
- PASS: `rg -n "<[s]tyle|[s]tyle=" assets/theme-v2/js/theme-icons.js assets/theme-v2/js/tool-display-mode.js assets/theme-v2/js/gamefoundry-partials.js assets/theme-v2/css/icons.css assets/theme-v2/css/layout.css assets/theme-v2/css/buttons.css assets/theme-v2/css/panels.css tests/playwright/tools/ThemeV2SvgIconRegistry.spec.mjs tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs tests/playwright/tools/ToolboxRoutePages.spec.mjs` returned no matches.
8+
- PASS: `git diff --check`
9+
10+
## Playwright
11+
- PASS: `npx playwright test tests/playwright/tools/ThemeV2SvgIconRegistry.spec.mjs --workers=1` (8 passed)
12+
- PASS: `npx playwright test tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs --workers=1` (7 passed)
13+
- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --workers=1` (11 passed)
14+
15+
## Branch Validation
16+
- PASS: Built from refreshed main after latest main refresh (`245c30dda`).
17+
- PASS: Changed files are scoped to the PLAN target implementation, target tests, and required BUILD reports.
18+
- PASS: Generated Playwright coverage report diffs were restored before packaging.
Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
docs_build/dev/reports/codex_changed_files.txt
2-
docs_build/dev/reports/PR_26175_CHARLIE_027-final-charlie-audit.md
3-
docs_build/dev/reports/PR_26175_CHARLIE_027-final-charlie-audit-branch-validation.md
4-
docs_build/dev/reports/PR_26175_CHARLIE_027-final-charlie-audit-manual-validation-notes.md
5-
docs_build/dev/reports/PR_26175_CHARLIE_027-final-charlie-audit-requirement-checklist.md
6-
docs_build/dev/reports/PR_26175_CHARLIE_027-final-charlie-audit-validation.md
1+
assets/theme-v2/css/buttons.css
2+
assets/theme-v2/css/icons.css
3+
assets/theme-v2/css/panels.css
4+
assets/theme-v2/js/gamefoundry-partials.js
5+
assets/theme-v2/js/tool-display-mode.js
6+
docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_manual-validation-notes.md
7+
docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_report.md
8+
docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_requirements-checklist.md
9+
docs_build/dev/reports/PR_26175_ALFA_050-theme-v2-layout-utility-icons_validation-lane.md
10+
docs_build/dev/reports/codex_changed_files.txt
11+
docs_build/dev/reports/codex_review.diff
12+
tests/playwright/tools/ThemeV2SvgIconRegistry.spec.mjs
13+
tests/playwright/tools/ToolboxRoutePages.spec.mjs
14+
tests/playwright/tools/ToolboxSelectedGameStatusBar.spec.mjs

0 commit comments

Comments
 (0)