Skip to content

Commit b781f40

Browse files
committed
Restore sorting and grouping on root tools index after migration - PR_26152_040-root-tools-index-sort-group-fix
1 parent e5c814d commit b781f40

3 files changed

Lines changed: 159 additions & 237 deletions

File tree

GameFoundryStudio/assets/js/tools-page-accordions.js

Lines changed: 91 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
tools: [
1414
{
1515
title: "Asset Studio",
16-
href: "asset-studio.html",
17-
image: "../assets/images/tools/asset-studio.png",
16+
href: "tools/asset-studio.html",
17+
image: "assets/images/tools/asset-studio.png",
1818
description: "Create sprites, animations, vectors and palettes.",
1919
role: "Pixel Smith",
2020
mascot: "pixel-smith",
@@ -27,17 +27,17 @@
2727
tools: [
2828
{
2929
title: "Object Vector Studio",
30-
href: "object-vector-studio.html",
31-
image: "../assets/images/tools/object-vector-studio.png",
30+
href: "tools/object-vector-studio.html",
31+
image: "assets/images/tools/object-vector-studio.png",
3232
description: "Create object-ready vector assets and reusable scene pieces.",
3333
role: "Pixel Smith",
3434
mascot: "pixel-smith",
3535
theme: "pixel"
3636
},
3737
{
3838
title: "World Vector Studio",
39-
href: "world-vector-studio.html",
40-
image: "../assets/images/tools/world-vector-studio.png",
39+
href: "tools/world-vector-studio.html",
40+
image: "assets/images/tools/world-vector-studio.png",
4141
description: "Shape world layouts, maps, terrain, and scene geometry.",
4242
role: "Pixel Smith",
4343
mascot: "pixel-smith",
@@ -50,8 +50,8 @@
5050
tools: [
5151
{
5252
title: "Palette Manager",
53-
href: "palette-manager.html",
54-
image: "../assets/images/tools/palette-manager.png",
53+
href: "tools/palette-manager.html",
54+
image: "assets/images/tools/palette-manager.png",
5555
description: "Craft and manage color palettes for your games.",
5656
role: "Pixel Smith",
5757
mascot: "pixel-smith",
@@ -64,8 +64,8 @@
6464
tools: [
6565
{
6666
title: "Game Builder",
67-
href: "game-builder.html",
68-
image: "../assets/images/tools/game-builder.png",
67+
href: "tools/game-builder.html",
68+
image: "assets/images/tools/game-builder.png",
6969
description: "Assemble components and build your game from scratch.",
7070
role: "ForgeBot",
7171
mascot: "forgebot",
@@ -78,8 +78,8 @@
7878
tools: [
7979
{
8080
title: "Game Design Studio",
81-
href: "game-design-studio.html",
82-
image: "../assets/images/tools/game-design-studio.png",
81+
href: "tools/game-design-studio.html",
82+
image: "assets/images/tools/game-design-studio.png",
8383
description: "Design gameplay, systems, rules, and player experience.",
8484
role: "ForgeBot",
8585
mascot: "forgebot",
@@ -92,8 +92,8 @@
9292
tools: [
9393
{
9494
title: "Publish Studio",
95-
href: "publisher.html",
96-
image: "../assets/images/tools/publish-studio.png",
95+
href: "tools/publisher.html",
96+
image: "assets/images/tools/publish-studio.png",
9797
description: "Prepare publishing workflows and release-ready game packages.",
9898
role: "ForgeBot",
9999
mascot: "forgebot",
@@ -106,17 +106,17 @@
106106
tools: [
107107
{
108108
title: "Animation Studio",
109-
href: "animation-studio.html",
110-
image: "../assets/images/tools/animation-studio.png",
109+
href: "tools/animation-studio.html",
110+
image: "assets/images/tools/animation-studio.png",
111111
description: "Create timing, animation states, and motion workflows.",
112112
role: "Spark",
113113
mascot: "spark",
114114
theme: "pixel"
115115
},
116116
{
117117
title: "Particle Studio",
118-
href: "particle-studio.html",
119-
image: "../assets/images/tools/particle-studio.png",
118+
href: "tools/particle-studio.html",
119+
image: "assets/images/tools/particle-studio.png",
120120
description: "Author visual effects, emitters, and particle looks.",
121121
role: "Spark",
122122
mascot: "spark",
@@ -129,17 +129,17 @@
129129
tools: [
130130
{
131131
title: "MIDI Studio",
132-
href: "midi-studio.html",
133-
image: "../assets/images/tools/midi-studio.png",
132+
href: "tools/midi-studio.html",
133+
image: "assets/images/tools/midi-studio.png",
134134
description: "Build MIDI-driven audio and music interaction flows.",
135135
role: "Foundry Bot",
136136
mascot: "foundry-bot",
137137
theme: "bot"
138138
},
139139
{
140140
title: "Sound Studio",
141-
href: "sound-studio.html",
142-
image: "../assets/images/tools/sound-studio.png",
141+
href: "tools/sound-studio.html",
142+
image: "assets/images/tools/sound-studio.png",
143143
description: "Prepare audio, sound effects, and game sound workflows.",
144144
role: "Foundry Bot",
145145
mascot: "foundry-bot",
@@ -152,8 +152,8 @@
152152
tools: [
153153
{
154154
title: "AI Assistant",
155-
href: "ai-assistant.html",
156-
image: "../assets/images/tools/ai-assistant.png",
155+
href: "tools/ai-assistant.html",
156+
image: "assets/images/tools/ai-assistant.png",
157157
description: "Get guided technical help for game creation workflows.",
158158
role: "Foundry Bot",
159159
mascot: "foundry-bot",
@@ -166,17 +166,17 @@
166166
tools: [
167167
{
168168
title: "Code Studio",
169-
href: "code-studio.html",
170-
image: "../assets/images/tools/code-studio.png",
169+
href: "tools/code-studio.html",
170+
image: "assets/images/tools/code-studio.png",
171171
description: "Write code, extend systems and build custom logic.",
172172
role: "Foundry Bot",
173173
mascot: "foundry-bot",
174174
theme: "bot"
175175
},
176176
{
177177
title: "Input Studio",
178-
href: "input-studio.html",
179-
image: "../assets/images/tools/input-studio.png",
178+
href: "tools/input-studio.html",
179+
image: "assets/images/tools/input-studio.png",
180180
description: "Map player controls and configure input workflows.",
181181
role: "Foundry Bot",
182182
mascot: "foundry-bot",
@@ -189,8 +189,8 @@
189189
tools: [
190190
{
191191
title: "Marketplace",
192-
href: "../marketplace/index.html",
193-
image: "../assets/images/tools/marketplace.png",
192+
href: "marketplace/index.html",
193+
image: "assets/images/tools/marketplace.png",
194194
description: "Browse community-ready tools, assets, listings, and distribution surfaces.",
195195
role: "Community",
196196
mascot: "foundry-bot",
@@ -203,8 +203,8 @@
203203
tools: [
204204
{
205205
title: "Localization Studio",
206-
href: "localization-studio/index.html",
207-
image: "../assets/images/tools/localization-studio.png",
206+
href: "tools/localization-studio/index.html",
207+
image: "assets/images/tools/localization-studio.png",
208208
description: "Plan game translation, language coverage, and contributor review workflows.",
209209
role: "Community / Media",
210210
mascot: "localization-studio",
@@ -217,8 +217,8 @@
217217
tools: [
218218
{
219219
title: "Arcade",
220-
href: "../arcade/index.html",
221-
image: "../assets/images/tools/arcade.png",
220+
href: "arcade/index.html",
221+
image: "assets/images/tools/arcade.png",
222222
description: "Play and review available games from the Game Foundry arcade.",
223223
role: "Play",
224224
mascot: "forgebot",
@@ -231,8 +231,8 @@
231231
tools: [
232232
{
233233
title: "Storage Inspector",
234-
href: "storage-inspector.html",
235-
image: "../assets/images/tools/storage-inspector.png",
234+
href: "tools/storage-inspector.html",
235+
image: "assets/images/tools/storage-inspector.png",
236236
description: "Inspect local storage, saved state, and tool data.",
237237
role: "Foundry Bot",
238238
mascot: "foundry-bot",
@@ -252,6 +252,20 @@
252252
"Community & Marketplace": "tool-group-community-marketplace",
253253
"Play": "tool-group-play"
254254
};
255+
const groupSwatchMap = {
256+
"Build & Create": "swatch-pink",
257+
"Content & Assets": "swatch-orange",
258+
"Media & Audio": "swatch-red",
259+
"AI & Learning": "swatch-purple",
260+
"Platform & Cloud": "swatch-blue",
261+
"Development & System": "swatch-gray",
262+
"Community / Media": "swatch-gold",
263+
"Community & Marketplace": "swatch-gold",
264+
"Play": "swatch-green"
265+
};
266+
const badgeMap = {
267+
"Publish Studio": "publish-studio"
268+
};
255269
const allTools = toolGroups.flatMap((group) => group.tools.map((tool) => ({
256270
...tool,
257271
group: group.group
@@ -261,6 +275,17 @@
261275
return groupClassMap[groupName] || "";
262276
}
263277

278+
function groupSwatch(groupName) {
279+
return groupSwatchMap[groupName] || "swatch-orange";
280+
}
281+
282+
function badgeName(tool) {
283+
if (badgeMap[tool.title]) {
284+
return badgeMap[tool.title];
285+
}
286+
return tool.image.split("/").pop().replace(".png", "");
287+
}
288+
264289
function setActiveButton(mode) {
265290
if (orderButton) {
266291
orderButton.setAttribute("aria-pressed", String(mode !== "grouped"));
@@ -303,10 +328,10 @@
303328

304329
function createGroupLabel(groupName) {
305330
const label = document.createElement("span");
306-
label.className = "tool-group-label";
331+
label.className = "content-cluster";
307332

308333
const swatch = document.createElement("span");
309-
swatch.className = "tool-group-swatch";
334+
swatch.className = "brand-color-swatch " + groupSwatch(groupName);
310335
swatch.setAttribute("role", "img");
311336
swatch.setAttribute("aria-label", groupName + " group color");
312337
swatch.title = groupName + " color";
@@ -320,36 +345,46 @@
320345

321346
function createToolCard(tool) {
322347
const article = document.createElement("article");
323-
article.className = `tool-card ${tool.theme} ${groupClass(tool.group)}`;
348+
article.className = `card ${groupClass(tool.group)}`;
324349
article.dataset.mascot = tool.mascot;
325350

326-
const link = document.createElement("a");
327-
link.href = tool.href;
328-
351+
const media = document.createElement("div");
352+
media.className = "card-media";
329353
const image = document.createElement("img");
330354
image.src = tool.image;
331-
image.alt = tool.title;
355+
image.alt = tool.title + " preview";
356+
media.append(image);
332357

333358
const body = document.createElement("div");
334-
body.className = "body";
359+
body.className = "card-body";
360+
361+
const badgeCluster = createGroupLabel(tool.group);
362+
const badge = document.createElement("object");
363+
badge.data = "assets/images/badges/" + badgeName(tool) + ".png";
364+
badge.type = "image/png";
365+
badge.width = 48;
366+
badge.height = 48;
367+
badge.setAttribute("aria-label", tool.title + " badge");
368+
badge.textContent = tool.title + " badge";
369+
badgeCluster.append(badge);
370+
371+
const group = document.createElement("div");
372+
group.className = "kicker";
373+
group.textContent = tool.group;
335374

336375
const title = document.createElement("h3");
337376
title.textContent = tool.title;
338377

339378
const description = document.createElement("p");
340379
description.textContent = tool.description;
341380

342-
const pill = document.createElement("span");
343-
pill.className = "pill";
344-
pill.textContent = "Open page";
345-
346-
const group = document.createElement("span");
347-
group.className = "role";
348-
group.append(createGroupLabel(tool.group));
381+
const link = document.createElement("a");
382+
link.className = "btn";
383+
link.href = tool.href;
384+
link.textContent = tool.href.indexOf("tools/") === 0 ? "Open Tool" : "Open Page";
349385

350-
body.append(title, description, pill, group);
351-
link.append(image, body);
352-
article.append(link);
386+
body.append(badgeCluster, group, title, description, link);
387+
article.append(media, body);
353388
return article;
354389
}
355390

@@ -366,7 +401,7 @@
366401
body.className = "accordion-body";
367402

368403
const grid = document.createElement("div");
369-
grid.className = "tool-grid";
404+
grid.className = "card-grid";
370405

371406
group.tools.forEach((tool) => {
372407
grid.append(createToolCard(tool));
@@ -379,7 +414,7 @@
379414

380415
function createToolGrid(tools) {
381416
const grid = document.createElement("div");
382-
grid.className = "tool-grid";
417+
grid.className = "card-grid";
383418
tools.forEach((tool) => {
384419
grid.append(createToolCard(tool));
385420
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# PR_26152_040 Root Tools Index Sort Group Validation
2+
3+
## Scope
4+
5+
- Restored missing sorting and grouping behavior on root `/tools/index.html`.
6+
- Kept work limited to the root Tools index and its existing supporting JS path.
7+
- Preserved existing tool data, images, badges, descriptions, grouping colors, and links.
8+
- Did not add CSS.
9+
- Did not change `GameFoundryStudio/assets/css/theme/v2`.
10+
- Did not migrate individual tool pages.
11+
- Did not change tool runtime behavior.
12+
13+
## Changed Files
14+
15+
- `tools/index.html`
16+
- `GameFoundryStudio/assets/js/tools-page-accordions.js`
17+
- `docs/dev/commit_comment.txt`
18+
- `docs/dev/reports/codex_changed_files.txt`
19+
- `docs/dev/reports/codex_review.diff`
20+
- `docs/dev/reports/root_tools_index_sort_group_validation.md`
21+
22+
## Validation Commands
23+
24+
- PASS: `node --check GameFoundryStudio/assets/js/tools-page-accordions.js`
25+
- External Tools index renderer syntax is valid.
26+
- PASS: `rg -n "data-tools-order|data-tools-sort|data-tools-accordion-list|tools-page-accordions\.js" tools/index.html`
27+
- Root Tools index contains the existing order control, grouped control, render target, and external JS reference.
28+
- PASS: `rg -n --pcre2 "<script(?![^>]*\bsrc=)|<style|\son[a-z]+\s*=" tools/index.html`
29+
- No inline script blocks, style blocks, or inline event handlers found.
30+
- PASS: `rg -n "render\(\"ascending\"\)|render\(\"grouped\"\)|dataset\.toolsOrder|tools\.sort|tools\.reverse|createAccordion|getGroupedTools|createToolGrid" GameFoundryStudio/assets/js/tools-page-accordions.js`
31+
- Existing ascending, descending, and grouped behavior paths are present.
32+
- PASS: `rg -n "assets/images/tools/|assets/images/badges/|brand-color-swatch|card-grid|vertical-accordion|className = \`card|className = \"btn\"|href = tool.href" GameFoundryStudio/assets/js/tools-page-accordions.js`
33+
- Rendered cards include tool images, badges, color indicators, Theme V2 cards, grouped accordions, and links.
34+
- PASS: `rg -n "assets/css/theme/v2|<link rel=\"stylesheet\"|tools-page-accordions\.js|data-tools-accordion-list" tools/index.html`
35+
- Root Tools index still loads Theme V2 and the existing external sorting/grouping renderer.
36+
- PASS: `git status --short -- GameFoundryStudio/assets/css/theme/v2`
37+
- No Theme V2 CSS files changed.
38+
- PASS: `git status --short -- GameFoundryStudio/assets/css/theme/v2 tools/index.html GameFoundryStudio/assets/js/tools-page-accordions.js docs/dev/commit_comment.txt docs/dev/reports/codex_review.diff docs/dev/reports/codex_changed_files.txt docs/dev/reports/root_tools_index_sort_group_validation.md`
39+
- Scoped status shows only the root Tools index, existing supporting JS, and required reports.
40+
41+
## Behavior Validation
42+
43+
- Tool data loads from `GameFoundryStudio/assets/js/tools-page-accordions.js`.
44+
- Initial render calls `render("ascending")`.
45+
- Ascending sort uses `title.localeCompare`.
46+
- Descending sort reverses the sorted list.
47+
- Grouped render uses the existing `toolGroups` source and `createAccordion`.
48+
- Sorted and grouped renders both call the same Theme V2 card builder, so cards retain:
49+
- tool images
50+
- tool badges
51+
- descriptions
52+
- grouping labels
53+
- grouping color indicators
54+
- links
55+
56+
## Skipped
57+
58+
- Repo-wide tests were not run by request.
59+
- Tests outside the root Tools index were not run by request.
60+
- Full samples smoke test was not run by request.
61+
- Individual tool runtime validation was not run by request.
62+
- Browser/package tooling discovery was attempted, but the Windows sandbox repeatedly blocked process launch with:
63+
- `windows sandbox: spawn setup refresh`

0 commit comments

Comments
 (0)