Add responsive game filters and hybrid toolbox drawer
All checks were successful
Deploy Sokko G / deploy (push) Successful in 20s

This commit is contained in:
Shinuwa 2026-09-27 18:00:49 +02:00
parent 1ee460b94f
commit 00e73f0062
32 changed files with 1202 additions and 241 deletions

View file

@ -115,10 +115,12 @@ export function validateSiteContent(site) {
"aniimo.name",
"aniimo.searchPlaceholder",
"aniimo.prismanaOnly",
"aniimo.prismana",
"aniimo.elements",
"aniimo.roles",
"aniimo.role",
"aniimo.abilities",
"aniimo.abilityActions",
"aniimo.minimum",
"aniimo.exactLevel",
"aniimo.levelMode",

View file

@ -8,6 +8,8 @@ test("vite entrypoint and app shell are wired", async () => {
const source = await readFile("website/src/main.jsx", "utf8");
const gameFiltersHook = await readFile("website/src/hooks/useGameFilters.js", "utf8");
const shell = await readFile("website/src/components/Shell.jsx", "utf8");
const toolboxPages = await readFile("website/src/features/toolboxes/ToolboxPages.jsx", "utf8");
const importButton = await readFile("website/src/components/ImportButton.jsx", "utf8");
const overlays = await readFile("website/src/components/AppOverlays.jsx", "utf8");
const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8");
const homePage = await readFile("website/src/pages/HomePage.jsx", "utf8");
@ -26,6 +28,15 @@ test("vite entrypoint and app shell are wired", async () => {
assert.match(shell, /sidebar-about-link/);
assert.match(shell, /dragon-sidebar\.png/);
assert.match(shell, /ImportButton/);
assert.match(shell, /compactSidebar/);
assert.match(shell, /compactSidebar = Boolean\(drawerGameId\)/);
assert.doesNotMatch(shell, /import\.meta\.env\.DEV \|\| Boolean\(drawerGameId\)/);
assert.match(shell, /data-variant=\{compactSidebar \? "compact"/);
assert.match(shell, /toolbox-drawer-open/);
assert.match(shell, /position="right"/);
assert.match(importButton, /tooltipPosition/);
assert.match(toolboxPages, /DRAWER_INITIAL_WIDTH = 700/);
assert.doesNotMatch(toolboxPages, /drawerWidth|dbGetSetting|dbSetSetting/);
assert.match(overlays, /\.\/ImageViewer\.jsx/);
assert.match(overlays, /uid\("marker"\)/);
assert.match(imageViewer, /export function ImageViewer/);

View file

@ -9,6 +9,8 @@ test("generic game routes and shared game components are wired", async () => {
const gameRoute = await readFile("website/src/features/games/GameRoute.jsx", "utf8");
const gameLoaders = await readFile("website/src/features/games/loaders.js", "utf8");
const gameFiltersPanel = await readFile("website/src/features/games/GameFiltersPanel.jsx", "utf8");
const gameFilterDropdown = await readFile("website/src/features/games/GameFilterDropdown.jsx", "utf8");
const activeFilterBadges = await readFile("website/src/features/games/ActiveFilterBadges.jsx", "utf8");
const checklistCopyButton = await readFile("website/src/features/games/CopyChecklistItemsButton.jsx", "utf8");
const gameListsPage = await readFile("website/src/features/games/GameListsPage.jsx", "utf8");
@ -30,6 +32,17 @@ test("generic game routes and shared game components are wired", async () => {
assert.match(gameLoaders, /filterOptionKeys/);
assert.match(gameFiltersPanel, /export function GameFiltersPanel/);
assert.match(gameFiltersPanel, /filter-reset-button/);
assert.match(gameFiltersPanel, /horizontal-compact/);
assert.match(gameFiltersPanel, /horizontal-menu/);
assert.match(gameFiltersPanel, /Tooltip/);
assert.match(gameFiltersPanel, /aria-pressed/);
assert.match(gameFilterDropdown, /CompactDropdown/);
assert.match(gameFilterDropdown, /aria-expanded/);
assert.match(gameFilterDropdown, /nds-filter-count/);
assert.match(gameFilterDropdown, /data-columns/);
assert.match(activeFilterBadges, /export function ActiveFilterBadges/);
assert.match(activeFilterBadges, /Retirer le filtre/);
assert.match(gameFiltersPanel, /ActiveFilterBadges/);
assert.match(checklistCopyButton, /formatChecklistImportItems/);
assert.match(checklistCopyButton, /formatChecklistImportSections/);
assert.match(checklistCopyButton, /\$\{entry\.label\}:\$\{entry\.quantity\}/);
@ -54,6 +67,7 @@ test("mhwilds and diablo pages expose expected route pieces", async () => {
const mhwildsListing = await readFile("website/src/features/games/mhwilds/MhwildsListing.jsx", "utf8");
const mhwildsLists = await readFile("website/src/features/games/mhwilds/MhwildsLists.jsx", "utf8");
const aniimoPage = await readFile("website/src/features/games/aniimo/AniimoPage.jsx", "utf8");
const aniimoFilters = await readFile("website/src/features/games/aniimo/AniimoFilters.jsx", "utf8");
const aniimoLists = await readFile("website/src/features/games/aniimo/AniimoLists.jsx", "utf8");
const mhwildsFilters = await readFile("website/src/features/games/mhwilds/MhwildsFilters.jsx", "utf8");
const monsterCard = await readFile("website/src/features/games/mhwilds/cards/MonsterCard.jsx", "utf8");
@ -66,6 +80,7 @@ test("mhwilds and diablo pages expose expected route pieces", async () => {
assert.match(diablo4Listing, /CopyChecklistItemsButton/);
assert.match(diablo4Filters, /export function Diablo4Filters/);
assert.match(diablo4Filters, /GameFiltersPanel/);
assert.match(diablo4Filters, /variant="horizontal-menu"/);
assert.match(diablo4AffixCard, /export function Diablo4AffixCard/);
assert.match(diablo4AffixCard, /categoryMap/);
assert.match(diablo4Utils, /getFilteredDiablo4Affixes/);
@ -83,9 +98,16 @@ test("mhwilds and diablo pages expose expected route pieces", async () => {
assert.match(mhwildsLists, /selectedListId/);
assert.match(aniimoPage, /AniimoLists/);
assert.match(aniimoPage, /games\/aniimo\/lists/);
assert.match(aniimoFilters, /data-variant="horizontal-menu"/);
assert.match(aniimoFilters, /GameFilterDropdown/);
assert.match(aniimoFilters, /content\.roles/);
assert.match(aniimoFilters, /content\.elements/);
assert.match(aniimoFilters, /content\.abilities/);
assert.equal((aniimoFilters.match(/columns=\{2\}/g) || []).length, 2);
assert.match(aniimoLists, /GameListsPage/);
assert.match(mhwildsFilters, /export function MhwildsFilters/);
assert.match(mhwildsFilters, /GameFiltersPanel/);
assert.match(mhwildsFilters, /variant="horizontal-compact"/);
assert.match(monsterCard, /export function MonsterCard/);
assert.match(monsterCard, /ui-icon-flip/);
assert.match(endemicCard, /export function EndemicCard/);

View file

@ -51,6 +51,24 @@ test("product components keep the public NDS pattern vocabulary", async () => {
}
});
test("filter patterns expose vertical, compact and menu layouts", async () => {
const attributes = await readFile("website/src/styles/design-system/attributes/_patterns.scss", "utf8");
const catalog = await readFile("website/src/pages/DesignSystemPage.jsx", "utf8");
const documentation = await readFile("DESIGN_SYSTEM.md", "utf8");
for (const variant of ["vertical", "horizontal-compact", "horizontal-menu"]) {
assert.match(catalog, new RegExp(variant));
assert.match(documentation, new RegExp(variant));
}
assert.match(attributes, /nds-filter-menu/);
assert.match(attributes, /data-columns="2"/);
assert.match(attributes, /grid-template-columns: repeat\(2/);
assert.match(attributes, /nds-filter-option-label/);
const gameFilters = await readFile("website/src/styles/games/_filters.scss", "utf8");
assert.match(gameFilters, /nds-active-filters/);
assert.match(gameFilters, /nds-active-filter/);
assert.match(documentation, /composant commun `Tooltip`/);
});
test("large sass files stay split by stable responsibility", async () => {
const orchestrators = [
"website/src/styles/home/_library.scss",