feat(b3): M1 — Chip.vue par dimension (échelle outline, fonction pleine, posture safran) + filtres / et /agences

- components/Chip.vue (nouveau) : label/variant(echelle|fonction|posture)/
  active/count/as(button|span)/removable, emits toggle+remove, aria-pressed
  natif sur as=button, croix "Retirer {label}" accessible. Styles 100% tokens
  DS (--primary/--on-primary/--bg-alt/--accent/--on-accent/--focus-ring/
  --dur-fast), hover translateY, focus-visible outline var(--focus-ring),
  transition coupée sous prefers-reduced-motion. Taille compacte 32px de haut
  mesurée (tap ok).
- components/ChipGroup.vue (nouveau) : role="group" + aria-label + flex-wrap
  gap — garantit le wrap propre exigé (jamais une ligne à virgules).
- EchelleFilter.vue, FonctionFilter.vue : rendu remplacé par Chip/ChipGroup,
  props modelValue/counts et événement update:modelValue strictement
  inchangés (NavSidebar.vue n'a rien à changer côté logique). FonctionFilter
  passe le rang de sélection (comme avant) via le prop count de Chip.
- HashtagFilter.vue : seule la liste HASHTAGS (togglable, grammaire fonction)
  passe en Chip/ChipGroup. Les chips FAMILLES gardent leur rendu et leurs
  couleurs propres par famille (hors grammaire échelle/fonction/posture,
  hors périmètre B3 — les changer aurait été une refonte, pas un branchement).
- pages/agences.vue : hashtags par structure (liste sidebar) en
  Chip as="span" variant="fonction" (non cliquables avant, le restent).
- pages/index.vue : la sheet mobile ne passe PAS par NavSidebar/EchelleFilter/
  FonctionFilter — elle a son propre bloc de chips dupliqué (découvert en
  testant le mobile, absent du périmètre écrit du brief). Direction du parti
  design ("chips codées par dimension", mobile-first explicite) : convertie
  en Chip/ChipGroup elle aussi, mêmes handlers toggleEchelle/toggleFonction
  inchangés. Effet de bord positif : le nombre par fonction (déjà calculé,
  jamais affiché sur mobile) apparaît désormais aussi en mobile, à parité
  avec le desktop.
- components/TagBadge.vue supprimé : son seul consommateur, OrgCard.vue,
  n'est importé nulle part dans l'app (grep vérifié) — code mort. OrgCard.vue
  supprimé avec lui plutôt que laissé avec une référence à un composant
  disparu.
- components/TypeBadge.vue : conservé tel quel — ce n'est pas un filtre, et
  sa grammaire couleur par type (7 couleurs Tailwind fixes) est orthogonale
  à échelle/fonction/posture ; le convertir en Chip aurait perdu l'info de
  type ou inventé une 4e variante non validée.

Vérifié : npm run build OK. Chips wrap avec gap en clair/sombre/mobile
(390px, hauteur mesurée 32px). Dark mode : contraste texte/fond conforme
(safran = texte sombre, jamais blanc).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jules
2026-09-25 12:03:22 +02:00
co-authored by Claude Sonnet 5
parent 0903b8989b
commit 4b1340f160
9 changed files with 242 additions and 148 deletions
+8 -31
View File
@@ -1,39 +1,16 @@
<template>
<div class="space-y-1.5">
<p class="text-xs font-bold uppercase tracking-widest" style="color: var(--nav-text-muted);">Échelle</p>
<!-- Inline sur 1 ligne — même pattern que FonctionFilter -->
<div class="flex flex-wrap gap-x-4 gap-y-1.5">
<label
<ChipGroup aria-label="Filtrer par échelle">
<Chip
v-for="option in ECHELLES"
:key="option"
class="flex items-center gap-1.5 cursor-pointer select-none transition-opacity"
>
<!-- Case carrée -->
<span
class="flex items-center justify-center shrink-0 transition-all"
style="width: 18px; height: 18px; border: 1.5px solid; border-radius: 3px;"
:style="isSelected(option)
? 'background: var(--nav-primary); border-color: var(--nav-primary); color: #ffffff;'
: 'background: var(--nav-bg-alt); border-color: rgba(26,34,56,0.25); color: transparent;'"
>
<svg v-if="isSelected(option)" width="11" height="11" viewBox="0 0 12 12" fill="none">
<polyline points="2,6 5,9 10,3" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</span>
<!-- Label -->
<span
class="text-sm leading-tight"
:style="isSelected(option) ? 'color: var(--nav-text); font-weight: 600;' : 'color: var(--nav-text);'"
>{{ option }}</span>
<!-- Input réel (masqué) -->
<input
type="checkbox"
class="sr-only"
:checked="isSelected(option)"
@change="toggle(option)"
/>
</label>
</div>
:label="option"
variant="echelle"
:active="isSelected(option)"
@toggle="toggle(option)"
/>
</ChipGroup>
</div>
</template>