- 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>
53 lines
1.4 KiB
Vue
53 lines
1.4 KiB
Vue
<template>
|
|
<div class="space-y-1.5">
|
|
<p class="text-xs font-bold uppercase tracking-widest" style="color: var(--nav-text-muted);">Fonction</p>
|
|
<ChipGroup aria-label="Filtrer par fonction">
|
|
<Chip
|
|
v-for="fn in FONCTIONS"
|
|
:key="fn"
|
|
:label="fn"
|
|
variant="fonction"
|
|
:active="modelValue.includes(fn)"
|
|
:count="modelValue.includes(fn) ? (modelValue.indexOf(fn) + 1) : (counts[fn] ?? 0)"
|
|
@toggle="toggle(fn)"
|
|
/>
|
|
</ChipGroup>
|
|
<p v-if="modelValue.length" class="text-xs pt-0.5" style="color: var(--nav-text-muted);">
|
|
{{ modelValue.length }} actif{{ modelValue.length > 1 ? 's' : '' }}
|
|
<button @click="emit('update:modelValue', [])" class="ml-2 underline hover:opacity-70">Effacer</button>
|
|
</p>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const FONCTIONS = [
|
|
'Juridique',
|
|
'Technique',
|
|
'Économique',
|
|
'Administratif',
|
|
'Chantier',
|
|
'Comptabilité',
|
|
'Développement',
|
|
'Formation',
|
|
"Gestion d'agence",
|
|
'Santé mentale',
|
|
] as const
|
|
|
|
const props = defineProps<{
|
|
modelValue: string[]
|
|
counts: Record<string, number>
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
'update:modelValue': [value: string[]]
|
|
}>()
|
|
|
|
function toggle(fn: string) {
|
|
if (props.modelValue.includes(fn)) {
|
|
emit('update:modelValue', props.modelValue.filter(f => f !== fn))
|
|
} else {
|
|
emit('update:modelValue', [...props.modelValue, fn])
|
|
}
|
|
}
|
|
</script>
|