Keep filter dropdowns clickable above active filter badges
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s

This commit is contained in:
Shinuwa 2026-10-07 22:53:17 +02:00
parent a921c9ef02
commit 96af62edf0
3 changed files with 40 additions and 0 deletions

View file

@ -589,6 +589,7 @@ Filtres :
- `nds-filter-menu[data-columns="2"]` répartit les options aux libellés courts sur deux colonnes dans la largeur standard du popover, afin de compacter chaque option ;
- les menus multi-sélection gardent les libellés visibles et affichent le nombre de critères actifs dans leur trigger ;
- les listes des popovers de filtres prennent leur hauteur naturelle et n’ajoutent pas de défilement interne ;
- un groupe contenant un menu ouvert passe au-dessus de la section des badges actifs pour que celle-ci n’intercepte pas les clics dans le menu ;
- les sélecteurs de condition comme `ET / OU` ou `≥ / =` restent dans une petite surface bordée afin de les distinguer des options du menu ;
- lorsque la condition ne concerne qu’un groupe avancé, comme les catégories Diablo IV, son sélecteur est placé dans le popover correspondant avec 12 px d’espace avant les options ;
- toute option réduite à son icône doit utiliser le composant commun `Tooltip` et conserver un nom accessible (`aria-label`) ; l’attribut HTML `title` ne remplace pas le tooltip ;

View file

@ -1,6 +1,43 @@
// Rôle : vérifie les variantes horizontales compactes et avancées des filtres de jeux.
import { test, expect } from "@playwright/test";
for (const { game, category, width } of [
{ game: "diablo4/affixes", category: "Catégories", width: 1920 },
{ game: "diablo4/affixes", category: "Catégories", width: 900 },
{ game: "diablo4/affixes", category: "Catégories", width: 768 },
{ game: "aniimo/aniimos", category: "Rôles", width: 1920 }
]) {
test(`${game} dropdown receives clicks over active badges at ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 900 });
await page.goto(`/#/games/${game}`);
const filters = page.locator('.nds-filter-panel[data-variant="horizontal-menu"]');
await filters.getByRole("searchbox").fill("a");
const badges = filters.locator(".nds-active-filters");
await expect(badges).toBeVisible();
await filters.getByRole("button", { name: category, exact: true }).click();
const menu = page.getByRole("dialog", { name: new RegExp(`^${category}`) });
const control = category === "Catégories"
? menu.getByRole("radio", { name: "Ou", exact: true })
: menu.getByRole("checkbox").first();
const controlBox = await control.boundingBox();
const badgesBox = await badges.boundingBox();
const overlapTop = Math.max(controlBox.y, badgesBox.y);
const overlapBottom = Math.min(controlBox.y + controlBox.height, badgesBox.y + badgesBox.height);
expect(overlapBottom).toBeGreaterThan(overlapTop);
await control.click({
position: { x: controlBox.width / 2, y: (overlapTop + overlapBottom) / 2 - controlBox.y },
timeout: 3000
});
if (category === "Catégories") await expect(control).toHaveAttribute("aria-checked", "true");
else await expect(control).toBeChecked();
await expect(menu).toBeVisible();
await page.keyboard.press("Escape");
await badges.getByRole("button").first().click();
await expect(filters.getByRole("searchbox")).toHaveValue("");
});
}
for (const width of [1920, 900]) {
test(`MHW compact filters keep accessible tooltips at ${width}px`, async ({ page }) => {
await page.setViewportSize({ width, height: 900 });

View file

@ -265,6 +265,8 @@
min-width: 176px;
}
// Le groupe parent doit aussi passer devant la section des badges actifs.
.nds-filter-panel > .nds-filter-group:has(.nds-filter-dropdown.is-open),
.nds-filter-dropdown.is-open {
z-index: 2;
}