feat(a11y): add aria-pressed and group semantics to filter pills

- Wrap each .filters__pills in role=group with aria-labelledby pointing
  to the label
- Add type=button to all pill buttons
- Toggle aria-pressed alongside .is-active class on click
- All inactive pills start with aria-pressed=false
This commit is contained in:
2026-07-25 19:29:33 +02:00
parent 1b5ffe6a7a
commit 592412fec7
+15 -13
View File
@@ -9,26 +9,26 @@ const { municipios, temas, fuentes } = Astro.props;
<div class="filters" id="filters">
<div class="filters__group">
<span class="filters__label">Municipi</span>
<div class="filters__pills" data-filter-type="municipio">
<button class="pill is-active" data-value="">Tots</button>
{municipios.map((m) => <button class="pill" data-value={m}>{m}</button>)}
<span class="filters__label" id="filter-label-municipi">Municipi</span>
<div class="filters__pills" role="group" aria-labelledby="filter-label-municipi" data-filter-type="municipio">
<button type="button" class="pill is-active" aria-pressed="true" data-value="">Tots</button>
{municipios.map((m) => <button type="button" class="pill" aria-pressed="false" data-value={m}>{m}</button>)}
</div>
</div>
<div class="filters__group">
<span class="filters__label">Tema</span>
<div class="filters__pills" data-filter-type="tema">
<button class="pill is-active" data-value="">Tots</button>
{temas.map((t) => <button class="pill" data-value={t}>{t}</button>)}
<span class="filters__label" id="filter-label-temes">Tema</span>
<div class="filters__pills" role="group" aria-labelledby="filter-label-temes" data-filter-type="tema">
<button type="button" class="pill is-active" aria-pressed="true" data-value="">Tots</button>
{temas.map((t) => <button type="button" class="pill" aria-pressed="false" data-value={t}>{t}</button>)}
</div>
</div>
<div class="filters__group">
<span class="filters__label">Font</span>
<div class="filters__pills" data-filter-type="fuente">
<button class="pill is-active" data-value="">Totes</button>
{fuentes.map((f) => <button class="pill" data-value={f}>{f}</button>)}
<span class="filters__label" id="filter-label-fonts">Font</span>
<div class="filters__pills" role="group" aria-labelledby="filter-label-fonts" data-filter-type="fuente">
<button type="button" class="pill is-active" aria-pressed="true" data-value="">Totes</button>
{fuentes.map((f) => <button type="button" class="pill" aria-pressed="false" data-value={f}>{f}</button>)}
</div>
</div>
@@ -120,10 +120,12 @@ const { municipios, temas, fuentes } = Astro.props;
const type = group?.dataset.filterType as keyof FilterState | undefined;
if (!type) return;
for (const sibling of group!.querySelectorAll('.pill')) {
for (const sibling of group!.querySelectorAll<HTMLButtonElement>('.pill')) {
sibling.classList.remove('is-active');
sibling.setAttribute('aria-pressed', 'false');
}
btn.classList.add('is-active');
btn.setAttribute('aria-pressed', 'true');
state[type] = btn.dataset.value ?? '';
apply();
});