@arche-mc2/vue-ui-lib

Bibliothèque de composants UI Vue 3 + TypeScript.
32,827
Install
npm install @arche-mc2/vue-ui-lib
Latest Version:1.2.69
Vue:3
License:Proprietary
Last Updated:Oct 22, 2026
Links: npm
Maintainer: gilles.vasse

@arche-mc2/vue-ui-lib

Bibliothèque de composants UI Vue 3 + TypeScript.

Stack : Vue 3 · TypeScript · Vite · SCSS · Storybook 9


Installation

yarn add @arche-mc2/vue-ui-lib
# ou
npm install @arche-mc2/vue-ui-lib

Setup

Dans main.ts, importer les styles et initialiser le système de toast :

import { createApp } from 'vue'
import '@arche-mc2/vue-ui-lib/dist/vue-ui-lib.css'
import { provideToast } from '@arche-mc2/vue-ui-lib'
import App from './App.vue'

const app = createApp(App)
provideToast(app)  // requis pour les toasts
app.mount('#app')

Placer <ToastBase /> une seule fois dans App.vue :

<template>
  <RouterView />
  <ToastBase />
</template>

Utilisation

import { ButtonBase, InputBase, SelectBase } from '@arche-mc2/vue-ui-lib'
import type { Option, ButtonTypes, IconName } from '@arche-mc2/vue-ui-lib'

Composants disponibles (45)

Composant Description
ButtonBase Bouton avec variantes, icône, loader
InputBase Input texte/date/password/search avec label flottant
SelectBase Dropdown mono/multi-sélection
CheckboxBase Case à cocher avec état indéterminé
RadioBase Bouton radio
ToggleBase Interrupteur on/off
SliderBase Curseur de valeur avec libellé et valeur « {n} pts » affichée
ToggleAdvanced Interrupteur 2 boutons gauche/droite
SegmentedButton Bouton 3 positions (gauche/centre/droite)
ModalBase Modale avec titre et overlay
ToastBase Notifications (système inject/provide)
TooltipBase Tooltip au survol
FlyoutMenu Menu contextuel positionné
SideMenu Menu latéral hiérarchique
TabBar Barre d'onglets
DataGrid Grille de données avancée
WidgetBase Carte conteneur avec slots
CalendarBase Calendrier (FullCalendar)
DatePicker Sélecteur de date
DayNavigator Navigation jour précédent / suivant du planning, avec le jour courant
SvgIcon Icône SVG (532 icônes)
LoaderBase Indicateur de chargement
TagBase Badge coloré
TagStatus Statut d'intervention : pastille décorative + libellé, sans fond
ListWithSearch Liste filtrée avec recherche
SelectionGroup Tags de sélection avec débordement
AvatarBase Avatar photo ou initiales en fallback
HistoryItem Ligne d'historique expandable (badge, avatar, diff)
DiffValue Rendu d'un diff ancienne → nouvelle valeur
HistoryBadge Badge de type d'action (modification/création/suppression)
HistoryFilter Bouton de filtre d'historique
AppointmentPopup Popup d'info au survol d'un rendez-vous du planning
InterventionCard Carte d'un créneau d'intervention du planning (activité, statut, icônes)
TripPopup Popup d'info au survol d'un trajet du planning (type, transport, durée, distance, indemnisation)
HoursCounterPopup Popup d'info au survol du compteur d'heures d'un intervenant (méthode de suivi, heures planifiées, objectifs, écart, heures perdues)
ScoreBadge Pastille ronde du score global de compatibilité (%), couleur selon le niveau (seuils 75 / 50)
CompatibilityPopup Popup d'info au survol et au focus du score de compatibilité d'un intervenant (score global, critères avec barre de progression)
CriterionRow Ligne de critère du CompatibilityPopup : point, libellé, score X/Y et barre value / max
ScoringPanel Panneau de paramétrage du scoring d'affectation : un curseur 0–50 pts par critère, pied Rétablir / Appliquer
FilterPanel Panneau latéral de filtres du planning (6 filtres, 2 options d'affichage), mise à jour en direct
StatCard Carte de statistique du planning : libellé, valeur mise en avant et plage (non interactive)
HomeStep Carte d'étape du planning : départ du domicile ou retour au domicile de l'intervenant
WorkerDayPanel Panneau de détail de la journée d'un intervenant : en-tête, synthèse en StatCard, slot carte, parcours du jour défilant
WorkerDayJourney « Parcours du jour » du WorkerDayPanel : liste ordonnée défilante domicile → trajets → interventions → domicile
Alert Bandeau d'alerte inline (success, error, info, warning) : titre, description, croix, action « Annuler » optionnelle

API des composants

ButtonBase

Bouton avec variantes de style, icône optionnelle et état de chargement. Couleurs par jetons, plus de style inline : libellé en text/* (SCSS), icône en couleur concrète icon/* calculée par le composant (currentColor ne résiste pas au * { color } d'Ogust) : Purple / Pink × Primary / Secondary conformes à la fiche Button (Pink en secondary/strong, hover Secondary en brand/surface), texte body/md, focus visible, Disabled sans opacité (fond background/muted, texte text/secondary) avec aria-disabled.

Props :

Prop Type Défaut Description
type ButtonTypes 'primary' Variante visuelle
iconName IconName — Icône à gauche du texte
loading boolean — Affiche un loader, remplace le contenu
disabled boolean — Désactive le bouton
active boolean — État actif (classe CSS)
id string — Attribut id HTML
inert boolean — Attribut inert HTML

Slots : default (texte/contenu du bouton)

ButtonTypes : 'primary' 'primary-pink' 'secondary' 'secondary-pink' 'action1'…'action7'

<ButtonBase type="primary" @click="save">Enregistrer</ButtonBase>
<ButtonBase type="secondary" icon-name="plus" :loading="isSaving">Ajouter</ButtonBase>
<ButtonBase type="action1" :disabled="true">Désactivé</ButtonBase>

InputBase

Champ de saisie avancé : texte, nombre, email, password, recherche, tel, url, date (avec masque dd/mm/yyyy et datepicker intégré), suggestions autocomplete.

Props :

Prop Type Défaut Description
modelValue string | number — Valeur (v-model)
label string — Label flottant
type 'text'|'number'|'time'|'search'|'email'|'password'|'tel'|'url'|'date' 'text' Type d'input
iconName IconName — Icône (gauche sans label, droite avec label)
clearable boolean — Bouton de vidage
passwordControl boolean — Bouton afficher/masquer mdp
disabled boolean — Désactivé
error boolean — État d'erreur (bordure rouge)
errorMessage string — Message d'erreur affiché sous le champ
required boolean — Affiche badge "Requis"
placeholder string — Placeholder
suggestions Option[] — Liste de suggestions autocomplete

Événements : update:modelValue(value: string | number)

<InputBase v-model="name" label="Nom" />
<InputBase v-model="search" type="search" icon-name="search" clearable placeholder="Rechercher..." />
<InputBase v-model="password" type="password" label="Mot de passe" password-control />
<InputBase v-model="birthdate" type="date" label="Date de naissance" />
<InputBase v-model="email" type="email" label="Email" :error="hasError" error-message="Email invalide" required />
<InputBase v-model="city" label="Ville" :suggestions="citySuggestions" />

Le type date intègre un masque dd/mm/yyyy et un DatePicker popup automatique.


SelectBase

Liste déroulante mono ou multi-sélection avec recherche, s'ouvre via Teleport.

Props :

Prop Type Défaut Description
modelValue Option[] — Sélection courante (v-model, toujours un tableau)
options Option[] requis Liste des options
label string — Label flottant
placeholder string — Texte placeholder
multiple boolean — Multi-sélection
searchable boolean — Activer la recherche
clearable boolean true Bouton de suppression sur les tags
disabled boolean — Désactivé

Événements : update:modelValue(value: Option[])

const civility = ref<Option[]>([])
const options = [
  { value: 'mr', label: 'Monsieur' },
  { value: 'mme', label: 'Madame' },
]
<SelectBase v-model="civility" :options="options" label="Civilité" placeholder="Choisir..." />
<SelectBase v-model="tags" :options="tagOptions" label="Tags" multiple searchable />

CheckboxBase

Case à cocher avec label optionnel, état indéterminé et thème personnalisable.

Props :

Prop Type Défaut Description
modelValue boolean false Coché ou non (v-model)
label string — Texte affiché à droite
icon IconName — Icône supplémentaire
iconStyle {height?,width?} — Taille de l'icône
theme {--amc2-checkbox-color?, --amc2-checkbox-disabled-color?, --amc2-checkmark-color?} — Couleurs custom
indeterminate boolean — État partiel (icône minus)
disabled boolean — Désactivé
className string — Classe CSS additionnelle

Événements natifs : change

<CheckboxBase v-model="accepted" label="J'accepte les conditions" />
<CheckboxBase v-model="allSelected" :indeterminate="isPartial" />

RadioBase

Bouton radio. Toujours utilisé avec v-model partagé + prop value distincte par option.

Props :

Prop Type Défaut Description
modelValue any — Valeur courante du groupe (v-model)
value any requis Valeur de cette option
label string — Texte affiché
icon IconName — Icône
theme {--amc2-radio-color?, --amc2-radio-disabled-color?, --amc2-radio-point-color?, --amc2-radio-point-disabled-color?} — Couleurs custom
disabled boolean — Désactivé
className string — Classe CSS additionnelle

Événements : update:modelValue(value: any)

<RadioBase v-model="gender" value="male" label="Homme" />
<RadioBase v-model="gender" value="female" label="Femme" />

ToggleBase

Interrupteur on/off simple avec label et icône optionnels.

Props :

Prop Type Défaut Description
modelValue boolean — État (v-model)
label string — Texte affiché
icon string — Nom d'icône
theme ToggleTheme — CSS custom properties de couleurs
disabled boolean — Désactivé

Événements : update:modelValue(value: boolean)

<ToggleBase v-model="notifications" label="Notifications" />
<ToggleBase v-model="darkMode" :disabled="isPremium === false" />

SliderBase

Curseur de valeur (Figma « Slider », 4306:567), extrait de ScoringPanel : libellé label/md au-dessus, piste 7 px (background/muted) avec remplissage et pouce 18 px brand/primary, valeur « {n} pts » en affichage seul (text/subtle sur background/subtle) à droite. Curseur natif <input type="range"> lié au libellé, réglable à la souris et au clavier (la valeur affichée suit), zone de clic de 32 px de haut, anneau de focus tracé vers l'intérieur, annoncé « 25 points ». Centre du pouce = position de la valeur = fin du remplissage. Largeur fluide (piste = 80 % de la ligne), hauteur 60 px. Données non typées : valeur et bornes acceptées en chaîne décimale ; valeur absente ou illisible → « non défini » (champ visible, sans pouce, « — », annoncé via emptyLabel), rien n'est émis avant une action ; hors bornes → bornée à l'affichage ; alignée sur le pas sans dépasser la dernière valeur atteignable (ajustements affichés seulement, l'hôte garde sa valeur jusqu'à une action) ; libellé vide ou bornes incohérentes → non rendu. Copie locale : la valeur suit le curseur même sans v-model (un hôte sans v-model qui réaffecte la même valeur ne remet pas le curseur en place). Nombre formaté selon locale. disabled : visible, non réglable, teintes text/secondary sans opacité.

Props :

Prop Type Défaut Description
modelValue number | string — Valeur (v-model)
label string | number — Libellé, nom accessible du curseur
min / max / step number | string 0 / 100 / 1 Bornes et pas (le Slider du scoring est en 0–50)
unitLabel string pts Unité affichée ; "" → aucune
unitSpokenLabel string unité affichée, sinon points Unité lue ; "" → aucune
locale string fr-FR Format du nombre affiché et lu
disabled boolean false Visible mais non réglable
emptyLabel string non défini Annonce quand aucune valeur n'est définie

Événements : update:modelValue(value: number)

<SliderBase v-model="poids" label="Compatibilité bénéficiaire" :max="50" />

ToggleAdvanced

Interrupteur à deux boutons (gauche/droite) avec labels et icônes.

Props :

Prop Type Défaut Description
modelValue boolean — true = gauche actif, false = droite actif (v-model)
labelLeft string — Texte bouton gauche
iconLeft IconName — Icône bouton gauche
labelRight string — Texte bouton droit
iconRight IconName — Icône bouton droit
theme ToggleTheme — Couleurs custom
disabled boolean — Désactivé

Événements : update:modelValue(value: boolean)

<ToggleAdvanced v-model="isListView" label-left="Liste" label-right="Grille"
  icon-left="list" icon-right="grid" />

SegmentedButton

Bouton segmenté 3 positions (gauche/centre/droite) avec tooltips. Conçu pour le tri.

Props :

Prop Type Défaut Description
modelValue 'left'|'center'|'right' 'center' Position active (v-model)
labelLeft string 'Croissant' —
iconLeft IconName 'arrow-down-a-z' —
toolTipLabelLeft string — Tooltip gauche
labelCenter string 'Aucun tri' —
iconCenter IconName — —
toolTipLabelCenter string — Tooltip centre
labelRight string 'Décroissant' —
iconRight IconName 'arrow-down-z-a' —
toolTipLabelRight string — Tooltip droit
disabled boolean — —
theme SegmentedButtonTheme — CSS vars de couleur

Événements : update:modelValue(value: 'left' | 'center' | 'right')

<SegmentedButton v-model="sortOrder" label-left="A→Z" label-right="Z→A" />

ModalBase

Modale avec titre, fond sombre, croix de fermeture. Supporte les modales empilées.

Props :

Prop Type Défaut Description
visible boolean requis Affichage
title string requis Titre de la modale
additionnal boolean — Modale secondaire (style décalé)

Événements : close

Slots : default (contenu de la modale)

<ModalBase :visible="showModal" title="Confirmer la suppression" @close="showModal = false">
  <p>Cette action est irréversible.</p>
  <ButtonBase type="secondary" @click="showModal = false">Annuler</ButtonBase>
  <ButtonBase type="primary" @click="confirmDelete">Supprimer</ButtonBase>
</ModalBase>

ToastBase + useToast

Système de notifications. Nécessite provideToast(app) dans main.ts. Placer <ToastBase /> une seule fois dans App.vue.

Setup main.ts : provideToast(app) (voir section Setup)

Utilisation :

import { useToast } from '@arche-mc2/vue-ui-lib'
const toast = useToast()
toast.show('Enregistré avec succès', 'success')        // durée défaut 3000ms
toast.show('Email invalide', 'error', 5000)
toast.show('Mise à jour disponible', 'info')
toast.show('Attention, données incomplètes', 'warning')

Intents disponibles : 'success' | 'warning' | 'error' | 'info'


TooltipBase

Tooltip au survol, positionnée automatiquement, avec flèche.

Props :

Prop Type Défaut Description
position Position 'bottom' Côté d'apparition
className string — Classe CSS sur le tooltip
style CSSProperties — Styles inline
removeDelay number — Délai de disparition en ms (utile si contenu cliquable)

Slots : default (élément déclencheur), content (contenu du tooltip)

<TooltipBase position="top">
  <ButtonBase>Supprimer</ButtonBase>
  <template #content>Cette action est irréversible</template>
</TooltipBase>

FlyoutMenu

Menu contextuel positionné, déclenché au clic. Peut afficher une liste d'items ou du contenu libre.

Props :

Prop Type Défaut Description
items FlyoutMenuItem[] — Liste de {label, onClick?} (mode liste simple)
position Position 'bottom' Position du menu
displayEl HTMLElement | null — Conteneur scrollable (pour repositionnement)
autoClose boolean true Fermeture automatique après clic item

Événements : close

Slots : default (déclencheur), content (contenu libre, si pas de prop items)

<!-- Mode liste -->
<FlyoutMenu :items="[{ label: 'Éditer', onClick: edit }, { label: 'Supprimer', onClick: del }]">
  <ButtonBase>Actions</ButtonBase>
</FlyoutMenu>

<!-- Mode contenu libre -->
<FlyoutMenu position="bottom-left">
  <SvgIcon icon-name="settings" />
  <template #content>
    <div>Contenu personnalisé</div>
  </template>
</FlyoutMenu>

SideMenu

Menu latéral de navigation avec items hiérarchiques (2 niveaux), icônes, et sélection active.

Props :

Prop Type Défaut Description
items MenuItem[] requis Arbre de navigation
idSelected number — ID de l'item actif au montage

La navigation appelle item.action?.() à la sélection. Les sous-menus s'ouvrent en accordéon.

const menuItems: MenuItem[] = [
  { id: 1, label: 'Tableau de bord', icon: 'home', action: () => router.push('/') },
  {
    id: 2, label: 'Gestion', icon: 'users',
    children: [
      { id: 3, label: 'Clients', action: () => router.push('/clients') },
      { id: 4, label: 'Contrats', action: () => router.push('/contracts') },
    ]
  },
]
<SideMenu :items="menuItems" :id-selected="currentId" />

TabBar

Barre d'onglets simple avec liste de labels.

Props :

Prop Type Défaut Description
listItems string[] requis Labels des onglets
listType string requis Onglet actif courant

Événements : change(selectedItem: string)

const tabs = ['Informations', 'Contrats', 'Documents']
const activeTab = ref('Informations')
<TabBar :list-items="tabs" :list-type="activeTab" @change="activeTab = $event" />

DataGrid

Grille de données avec colonnes configurables, tri, filtre, sélection par checkbox, scroll infini, menu d'actions par ligne, et colonne de paramétrage de visibilité des colonnes.

Props :

Prop Type Défaut Description
headers DatagridHeader[] requis Définition des colonnes
items any[] requis Données. Chaque item doit avoir id: number, et peut avoir isSelected: boolean, actions: FlyoutMenuItem[], onClick_<key>: () => void
hasMore boolean requis Indique s'il y a plus de données à charger
selection boolean false Activer colonne de checkboxes
allCheckState {isChecked: boolean, partially: boolean} {false,false} État checkbox "tout cocher"
displaySettingsHeader boolean true Afficher la colonne de paramétrage
displaySettings boolean true Afficher le menu d'actions par ligne
modalFilter (header: DatagridHeader) => void — Callback clic filtre
dataSort (header: DatagridHeader) => void — Callback clic tri

Événements :

  • loadMore — déclenché au scroll infini (et au montage)
  • updateCheckItem(id: number, isChecked: boolean) — checkbox ligne
  • updateCheckAll(isChecked: boolean) — checkbox header

Expose : resetScroll(), checkLoadMore()

Contenu d'un item :

  • item[header.key] → valeur texte, nombre, date, ou tableau (formaté automatiquement)
  • item[header.key] = { render: Component } → rendu d'un composant Vue dans la cellule
  • item['onClick_<key>'] → rend la cellule cliquable (lien <a>)
  • item.actions → tableau FlyoutMenuItem[] pour le menu d'actions rapides
  • item.isSelected → état de sélection checkbox
import { DataGrid } from '@arche-mc2/vue-ui-lib'
import type { DatagridHeader, FlyoutMenuItem } from '@arche-mc2/vue-ui-lib'

const headers = ref<DatagridHeader[]>([
  {
    key: 'name', label: 'Nom', dataType: 'string', sortable: true,
    visibility: { isShown: true, isDisabled: false, update: (v) => { headers.value[0].visibility.isShown = v } }
  },
  {
    key: 'date', label: 'Date', dataType: 'date', sortable: true,
    visibility: { isShown: true, isDisabled: false, update: (v) => { headers.value[1].visibility.isShown = v } }
  },
])

const items = ref([
  { id: 1, name: 'Alice', date: '01/01/2024', isSelected: false,
    actions: [{ label: 'Voir', onClick: () => openDetail(1) }] },
])

const gridRef = ref()
const page = ref(0)

const loadMore = async () => {
  const data = await fetchPage(page.value++)
  items.value = [...items.value, ...data]
  hasMore.value = data.length === PAGE_SIZE
}
<DataGrid
  ref="gridRef"
  :headers="headers"
  :items="items"
  :has-more="hasMore"
  selection
  @load-more="loadMore"
  @update-check-item="(id, checked) => toggleItem(id, checked)"
  @update-check-all="(checked) => toggleAll(checked)"
/>

WidgetBase

Conteneur carte avec slots header/body/footer, état de chargement, et état vide automatique.

Props :

Prop Type Défaut Description
width string '50%' Largeur CSS
height string '180px' Hauteur CSS
color string — Couleur de fond
isLoading boolean — Affiche un loader à la place du body

Slots : header, body, footer Si body est vide, affiche automatiquement une icône "Aucune donnée".

<WidgetBase width="100%" height="300px" :is-loading="loading">
  <template #header>
    <h3>Statistiques du mois</h3>
  </template>
  <template #body>
    <p>42 contrats signés</p>
  </template>
  <template #footer>
    <ButtonBase type="secondary">Voir le détail</ButtonBase>
  </template>
</WidgetBase>

CalendarBase

Calendrier plein-écran (FullCalendar) avec vues jour/semaine/mois, événements et sélection de plage.

Props :

Prop Type Défaut Description
events CalendarEvent[] — Événements à afficher
initialView 'day'|'week'|'month' 'month' Vue initiale
btnToday boolean — Afficher bouton "Aujourd'hui"
btnViewOption boolean — Afficher les boutons de changement de vue

Événements :

  • onSelectDate(range: CalendarRange) — sélection d'une plage (clic + drag)
  • onClickEvent(event: CalendarEvent) — clic sur un événement
  • onChangeView(range: CalendarRange) — changement de période/vue
const events: CalendarEvent[] = [
  { id: '1', title: 'Réunion', start: '2024-04-15T09:00:00', end: '2024-04-15T10:00:00' }
]
<CalendarBase
  :events="events"
  initial-view="week"
  btn-today
  btn-view-option
  @on-select-date="range => createEvent(range)"
  @on-click-event="event => openEvent(event)"
/>

DatePicker

Sélecteur de date avec navigation mois/année. Généralement intégré via InputBase (type="date"). Peut aussi être utilisé seul.

Props :

Prop Type Défaut Description
modelValue Date — Date sélectionnée (v-model)
min Date — Date minimale
max Date — Date maximale

Événements : update:modelValue(date: Date)

<!-- Usage recommandé via InputBase -->
<InputBase v-model="birthdate" type="date" label="Date de naissance" />

<!-- Usage direct -->
<DatePicker v-model="selectedDate" :min="minDate" :max="maxDate" />

DayNavigator

Barre de navigation temporelle du planning : le jour courant (« Mercredi 3 juin 2026 ») entre deux boutons secondaires « Préc. » et « Suiv. ». Le composant n'avance pas la date : il émet previous / next et le parent met à jour date avec une nouvelle instance de Date (ou une chaîne ISO AAAA-MM-JJ). Date absente, invalide ou dans un autre format → aucun libellé. Le libellé a une largeur fixe (calée sur « Mercredi 1er septembre », chiffres en tabular-nums) : les boutons ne bougent pas d'un jour à l'autre. Groupe nommé (label), noms accessibles qui commencent par le texte visible, date annoncée par aria-live (une seule région de ce type par écran) ; en bout de plage, le focus passe sur le bouton opposé.

Props :

Prop Type Défaut Description
date Date | string — (requis) Jour affiché (Date locale ou ISO AAAA-MM-JJ), formaté en français, majuscule initiale et « 1er »
disabledPrevious boolean false Désactive « Préc. » (début de période navigable)
disabledNext boolean false Désactive « Suiv. » (fin de période navigable)
label string 'Navigation par jour' Nom du groupe pour les lecteurs d'écran

Événements : previous(), next() — non émis quand le bouton correspondant est désactivé.

<DayNavigator
  :date="currentDate"
  :disabled-previous="isFirstDay"
  :disabled-next="isLastDay"
  @previous="goToPreviousDay"
  @next="goToNextDay"
/>

FilterPanel

Panneau latéral de filtres du planning : titre « Filtres » et croix de fermeture, six filtres (SelectBase) — Secteur(s) client et Secteur(s) intervenant en multi-sélection, Gestionnaire, Prestation, Intervenant, Client à choix unique — deux options d'affichage (ToggleBase) Interventions annulées et Trajets, puis « Réinitialiser » / « Appliquer » collés en bas. Chaque changement émet update:modelValue aussitôt (mise à jour en direct du planning ; v-model obligatoire, le panneau est contrôlé) ; « Appliquer » ne fait que fermer et reste toujours actif ; croix, Échap (focus dans le panneau ou dans une liste ouverte, qui se ferme d'abord) et clic à l'extérieur ferment aussi, sans effacer les filtres ni bloquer l'action cliquée derrière. Un clic dans une liste, une infobulle, un calendrier ou une modale ne ferme pas ; closeOnOutsideClick: false désactive la fermeture au clic extérieur. « Réinitialiser » est la seule action qui efface. Les boutons du pied ne soumettent jamais un <form>. L'hôte affiche le panneau avec v-if (focus initial sur « Secteur(s) client ») et le masque sur close, puis rend le focus à son bouton « Filtrer », qui doit ouvrir (open = true), pas basculer. Nombre de filtres actifs : countActiveFilters(value). Données Ogust : modelValue / options absents, null ou partiels → vides (autres clés de l'hôte conservées) ; option d'affichage vraie pour true, 1, "true", "1" ; option sans libellé lisible (null, { id, name }) retirée de la liste et de la sélection, libellé numérique accepté. <aside role="complementary"> nommé par le titre, sans piège de focus ; filtres et interrupteurs utilisables au clavier, interrupteurs role="switch" nommés par leur libellé ; croix 32 px. Libellés traduisibles via labels.

Props :

Prop Type Défaut Description
modelValue FilterPanelValue filtres vides, options désactivées État des filtres (v-model) ; chaque filtre est un Option[], y compris à choix unique
options FilterPanelOptions {} Options de chaque liste déroulante, par clé de filtre
title string 'Filtres' Titre de l'en-tête, nom accessible du panneau
labels FilterPanelLabels libellés français Un libellé par filtre et option d'affichage, plus placeholder, close, reset, submit
closeOnOutsideClick boolean true Fermer au clic à l'extérieur

Événements : update:modelValue(value: FilterPanelValue) à chaque changement et sur « Réinitialiser » ; reset() ; close() (« Appliquer », croix, Échap, clic extérieur).

Utilitaires : countActiveFilters(value) — nombre de filtres ayant au moins une valeur + options d'affichage activées ; emptyFilterPanelValue() — valeur vide (celle de « Réinitialiser »).

<ButtonBase type="secondary" @click="filtersOpen = true">
  Filtrer ({{ countActiveFilters(filters) }})
</ButtonBase>
<FilterPanel
  v-if="filtersOpen"
  v-model="filters"
  :options="{ secteursClient, secteursIntervenant, gestionnaire, prestation, intervenant, client }"
  @close="filtersOpen = false"
/>

SvgIcon

Icône SVG depuis le sprite interne. 532 icônes disponibles.

Props :

Prop Type Défaut Description
iconName IconName requis Nom de l'icône
color string '#2C2274' Couleur primaire (fill)
colorSecondary string 'transparent' Couleur secondaire
colorHover string — Couleur au survol
colorSecondaryHover string — Couleur secondaire au survol
height string '20' Hauteur en px
width string '20' Largeur en px
accessibilityTitle string — <title> SVG pour accessibilité
classIcon string — Classe CSS
id string — Attribut id
<SvgIcon icon-name="user" color="#5B4DBE" width="24" height="24" />
<SvgIcon icon-name="check" color="#55BDBE" />

Pour obtenir la liste complète des icônes :

import { iconNames } from '@arche-mc2/vue-ui-lib'
// iconNames est un tableau de 532 strings

LoaderBase

Gif de chargement animé.

Props :

Prop Type Défaut
size number 50
<LoaderBase :size="30" />

TagBase

Badge coloré avec label.

Props :

Prop Type Défaut Description
label string — Texte du badge
backgroundColor 'blue'|'green'|'primary'|'secondary' requis Couleur de fond
<TagBase label="Actif" background-color="green" />
<TagBase background-color="secondary" />

ListWithSearch

Liste d'options avec recherche et sélection mono/multi. Composant interne de SelectBase, mais peut être utilisé seul.

Props :

Prop Type Défaut Description
modelValue Option[] requis Sélection courante (v-model)
options Option[] requis Options disponibles
multiple boolean — Multi-sélection
searchable boolean — Activer la recherche
stickyHeader boolean true Header (search + tout sélectionner) sticky
emptyMessage string 'Aucune valeur' Message si liste vide
disabled boolean — —

Événements : update:modelValue(value: Option[])


SelectionGroup

Affichage compact des valeurs sélectionnées sous forme de tags, avec gestion du débordement (tooltip "+N").

Props :

Prop Type Défaut Description
modelValue {value: any, label: string}[] requis Items sélectionnés (v-model)
clearable boolean — Bouton de suppression par item
disabled boolean — —
placeholder string — Texte si vide
tooltipPosition Position — Position du tooltip "+N"
tooltipStyle CSSProperties — Style custom du tooltip

Événements : update:modelValue, clearAll(previous: Option[]), clear(option: Option)


AvatarBase

Avatar utilisateur : photo, ou initiales en fallback si pas d'image.

Props :

Prop Type Défaut Description
src string — URL de l'image ; si absent, affiche les initiales
alt string '' Texte alternatif de l'image
initials string '?' 1 ou 2 caractères affichés en fallback
size AvatarSize 'md' 'xs' 'sm' 'md' 'lg' 'xl'
shape AvatarShape 'circle' 'circle' 'square'
color AvatarColor 'primary' 'primary' 'secondary' 'green' 'blue' 'grey'
<AvatarBase initials="GV" size="md" color="primary" />
<AvatarBase src="/photos/user.jpg" alt="Jean Dupont" size="lg" />
<AvatarBase initials="AB" shape="square" color="secondary" />

HistoryItem

Ligne d'historique d'une fiche. Affiche une action (Modification, Création ou Suppression) avec badge de type, horodatage et auteur. Cliquable : dépliée, elle révèle un panneau détaillant les champs concernés. Compose HistoryBadge, AvatarBase et DiffValue. Le rendu des valeurs dépend du type : modification (ancienne barrée → nouvelle ; ancienne vide = ajout, rendu nouvelle seule ; nouvelle vide = vidage, rendu suppression), création (nouvelle seule), suppression (ancienne barrée → « Supprimé »).

Props :

Prop Type Défaut Description
type HistoryItemType 'modification' Type d'action ; pilote le badge et le rendu des valeurs
open boolean false Panneau de détail déplié (v-model:open)
date string '' Horodatage affiché
author string '' Nom de l'auteur
initials string '?' Initiales de l'auteur (avatar)
fields HistoryItemField[] [] Champs détaillés affichés quand open

Le bloc avatar + nom est masqué quand aucun auteur n'est connu (author vide et initials vide ou '?') : le chevron reste aligné à droite. Utile pour les actions automatiques ou les logs sans utilisateur.

Événements : update:open(value: boolean) · toggle(value: boolean)

<HistoryItem
  type="modification"
  v-model:open="open"
  date="02/05/2026 14:08"
  author="Gilles Vasse"
  initials="GV"
  :fields="[{ label: 'Prénom', oldValue: 'Jean', newValue: 'Jean-Pierre' }]"
/>

DiffValue

Rendu d'un diff de valeur selon le type d'action : modification (ancienne barrée → nouvelle), création (nouvelle seule), suppression (ancienne barrée → « Supprimé »). Deux cas particuliers de modification, symétriques : oldValue vide = ajout d'information, rendu comme une création (nouvelle valeur seule, sans pastille barrée vide ni flèche) ; newValue vide = vidage d'information, rendu comme une suppression (ancienne barrée → « Supprimé », sans pastille verte vide). Utilisé par HistoryItem, utilisable seul.

Props :

Prop Type Défaut Description
kind DiffValueKind 'modification' Pilote le rendu (couple, nouvelle seule, suppression)
oldValue string '' Ancienne valeur (modification, suppression). Vide sur une modification = ajout : nouvelle valeur seule
newValue string '' Nouvelle valeur (modification, création). Vide sur une modification = vidage : rendu « suppression »
<DiffValue kind="modification" old-value="Jean" new-value="Jean-Pierre" />
<DiffValue kind="modification" new-value="jean@exemple.fr" /> <!-- ajout : rendu « création » -->
<DiffValue kind="modification" old-value="06 12 34 56 78" /> <!-- vidage : rendu « suppression » -->
<DiffValue kind="creation" new-value="jean@exemple.fr" />
<DiffValue kind="suppression" old-value="06 12 34 56 78" />

HistoryBadge

Badge coloré du type d'action d'historique (libellé automatique : Modification / Création / Suppression).

Props :

Prop Type Défaut Description
type HistoryBadgeType requis 'modification' 'creation' 'suppression'
<HistoryBadge type="creation" />

HistoryFilter

Bouton de filtre d'historique (libellé automatique : Tout / Modification / Création / Suppression). Exclusif au sein d'un groupe : l'état actif est porté par le parent.

Props :

Prop Type Défaut Description
type HistoryFilterType requis 'all' 'modification' 'creation' 'suppression'
active boolean — État sélectionné (piloté par le parent)

Événements : click

<HistoryFilter type="all" :active="filter === 'all'" @click="filter = 'all'" />

AppointmentPopup

Popup d'information (role="tooltip") affiché au survol d'un rendez-vous attribué du planning : horaire + durée, type d'activité (couleur par activité, ligne masquable), statut d'intervention (pastille décorative + libellé), récurrence et besoin de clés (icônes repeat / keychain). Non interactif ; le placement (à droite du rendez-vous, sinon à gauche, sans flèche) est géré par le parent. Largeur max 240 px : au-delà, le texte passe à la ligne, jamais de troncature. Le statut est rendu par TagStatus en body/sm ; AppointmentPopupStatus est un alias de TagStatusType. Le type trajet n'a pas de libellé : la ligne d'activité est masquée. Une valeur de status ou d'activity hors liste ne casse pas le rendu : la ligne concernée est masquée (sauf activityLabel fourni, affiché sans couleur d'activité).

Props :

Prop Type Défaut Description
schedule string requis Ligne horaire complète, ex. 04:00 - 06:00 (120min)
activity AppointmentPopupActivity — Famille d'activité (mêmes valeurs qu'InterventionCard) : pilote la couleur du libellé (trajet = pas de ligne)
activityLabel string — Libellé affiché (nom réel de la prestation) ; à défaut, libellé générique de la famille
showActivityType boolean true Affiche la ligne d'activité (propriété Figma « Afficher le type »)
status AppointmentPopupStatus requis 'cancelled' 'unassigned' 'completed' 'toDo'
recurrence string requis Libellé de récurrence, ex. Hebdomadaire
keys string requis Libellé du besoin de clés, ex. Pas de clés nécessaires
<AppointmentPopup
  schedule="04:00 - 06:00 (120min)"
  activity="aideADomicile"
  activity-label="Aide à domicile"
  status="toDo"
  recurrence="Hebdomadaire"
  keys="Pas de clés nécessaires"
/>

TagStatus

Étiquette de statut d'intervention : pastille colorée décorative (6 px, aria-hidden) + libellé, sans fond ni bordure. Le statut fixe le libellé (Annulé / Non affecté / Réalisé / À réaliser), la couleur du texte (text/*) et celle de la pastille (primitive). Libellé tronqué avec ellipse s'il manque de place ; une valeur absente ou hors liste ne rend rien (jamais de statut par défaut). Texte body/xs (10/14) par défaut, surchargeable par l'hôte sans prop : dans la lib .mon-hote .tag-status { @include text-body-sm; } (Appointment popup) ; côté application, les mixins n'étant pas publiés, .mon-hote .tag-status { font-size: 12px; line-height: 18px; }.

Props :

Prop Type Défaut Description
status TagStatusType — 'cancelled' 'unassigned' 'completed' 'toDo' ; sans valeur, rien n'est rendu
<TagStatus status="toDo" />

InterventionCard

Carte d'un créneau d'intervention dans le planning, rendue en <button type="button"> (focusable, click natif, focus ring background/border/focus). Fond, bordure, pastille et couleur du libellé dépendent de l'activité ; largeur fluide (fixée par le conteneur). trajet n'affiche que la durée et l'icône itinéraire. replace (créneau à attribuer) est monochrome, en pointillé, sans statut ni icônes téléphone / répétition, avec l'icône alert-triangle si hasAttention ; lui seul connaît les états hover, selected (bordure pleine 1,5 px, aria-pressed) et dragging (opacité 30 %), et un texte masqué y annonce « Créneau à attribuer ». La sélection pilotée par l'hôte passe par selected (aria-pressed). Les icônes portent un texte masqué, les pastilles sont décoratives. Le statut est rendu par TagStatus. Données non typées : une activité inconnue donne une carte neutre, un statut inconnu pas d'étiquette, "false" en chaîne n'allume pas d'icône.

Props :

Prop Type Défaut Description
activity InterventionCardActivity 'jardinage' 'jardinage' 'bricolage' 'menage' 'aideADomicile' 'gardeEnfants' 'trajet' 'replace'
state InterventionCardState 'default' 'default' 'hover' 'selected' 'dragging' (effet sur replace uniquement)
selected boolean — Sélection pilotée par l'hôte : aria-pressed ; bordure Selected sur replace, y compris pendant hover / dragging
clientName string '' Nom du client (tronqué)
activityLabel string '' Libellé d'activité affiché (tronqué) ; à défaut, libellé générique de l'activité
time string '' Plage horaire, ex. 07:00 - 09:00
status TagStatusType — Statut d'intervention ; sans valeur, pas d'étiquette. Ignoré sur replace et trajet
duration string '' Durée affichée par trajet, ex. 1h
hasTransmission boolean false Icône téléphone (télétransmission effectuée) ; ignorée sur replace / trajet
hasRepetition boolean false Icône répétition (RDV récurrent) ; ignorée sur replace / trajet
hasAttention boolean false Icône attention (RDV urgent) ; replace uniquement

Événements : click (natif)

<InterventionCard
  activity="gardeEnfants"
  client-name="Mme. Simon"
  activity-label="Garde d'enfants"
  time="07:00 - 09:00"
  status="unassigned"
  has-transmission
/>

TripPopup

Popup d'information (role="tooltip") affiché au survol et au focus d'un trajet du planning : type de trajet + icône du moyen de transport (walk / bike / car / bus, 16 px, icon/primary), durée, distance et indemnisation (texte libre, toujours en text/accent/teal). Non interactif ; l'affichage et le placement relèvent du déclencheur, qui doit être focusable et porter aria-describedby vers l'id du popup (attribut id transmis à la racine). Largeur au contenu, max 240 px : au-delà, le texte passe à la ligne, jamais de troncature. duration et distance reçoivent la ligne entière (libellé + valeur, traduits par l'appelant). Le moyen de transport est annoncé par un texte masqué (« En voiture », « En transport en commun »…). transport accepte aussi les codes Ogust (calculdistance.class.php::getAllowedVehicle) : V → car, B → bike, C → bus (transport en commun : tram, métro, RER…), P → walk, casse ignorée. Données non typées : un transport absent ou inconnu n'affiche pas d'icône, une ligne vide (ou faite d'espaces) n'est pas rendue, et sans aucune donnée le popup n'est pas rendu. Socle commun avec AppointmentPopup (mixin popup-surface).

Props :

Prop Type Défaut Description
type string requis Type de trajet, ex. Trajet inter-vacation
duration string requis Ligne durée complète, ex. Durée (h:mn) : 1:00
distance string requis Ligne distance complète, ex. Distance (km) : 72
compensation string requis Indemnisation en texte libre, ex. Indemnisé - inter-vacation
transport TripPopupTransport | TripPopupOgustTransport — 'walk' 'bike' 'car' 'bus' (transport en commun), ou code Ogust 'V' 'B' 'C' 'P' ; sans valeur reconnue, pas d'icône
<TripPopup
  id="trip-42-popup"
  type="Trajet inter-vacation"
  duration="Durée (h:mn) : 1:00"
  distance="Distance (km) : 72"
  compensation="Indemnisé - inter-vacation"
  transport="car"
/>

HoursCounterPopup

Popup d'information (role="tooltip") affiché au survol et au focus du compteur d'heures d'un intervenant dans le planning : cinq lignes libellé fixe + valeur — méthode de suivi (en text/subtle, valeur collée au libellé), heures planifiées, objectifs d'heures, écart et heures perdues (en text/strong, libellé et valeur en deux colonnes égales, valeurs alignées). Chaque prop ne porte que la valeur ; les libellés français sont fixes dans le composant (« Méthode de suivi : », « Objectifs d’heures : »…) et remplaçables par des libellés traduits via labels (libellé complet, ponctuation comprise ; absent ou vide → libellé français). Le formatage des nombres (séparateur décimal, unité, signe) est à la charge de l'appelant : la chaîne reçue est affichée telle quelle, l'écart négatif n'est pas coloré. Non interactif ; l'affichage et le placement relèvent du déclencheur, qui doit être focusable et porter aria-describedby vers l'id du popup (attribut id transmis à la racine). Largeur au contenu (y compris en position absolue), max 240 px : au-delà, le texte passe à la ligne (ligne 1 comprise), jamais de troncature. Données non typées : une valeur absente, null, faite d'espaces ou non affichable (booléen, NaN, objet) masque sa ligne (le nombre 0 reste affiché), et sans aucune valeur le popup n'est pas rendu — l'appelant retire alors aria-describedby du déclencheur. Socle commun avec AppointmentPopup et TripPopup (mixin popup-surface).

Props :

Prop Type Défaut Description
trackingMethod string | number — Méthode de suivi, ex. Modulation
plannedHours string | number — Heures planifiées, ex. 28.75
targetHours string | number — Objectifs d'heures, ex. 75
hoursDifference string | number — Écart, ex. -25
lostHours string | number — Heures perdues, ex. 21.25
labels HoursCounterPopupLabels — Libellés traduits par ligne, ex. { plannedHours: "Planned hours:" }
<HoursCounterPopup
  id="worker-12-hours-popup"
  tracking-method="Modulation"
  planned-hours="28.75"
  target-hours="75"
  hours-difference="-25"
  lost-hours="21.25"
  :labels="{ plannedHours: 'Planned hours:' }"
/>

HomeStep

Carte d'étape du planning, non interactive : l'intervenant part de son domicile pour effectuer le rendez-vous (« Domicile - Départ ») ou rentre chez lui après (« Domicile - Retour »). Icône maison décorative (20 px, icon/subtle, aria-hidden) puis libellé body/sm sur une ligne : « Domicile - » en text/strong, le sens en text/subtle. Fond background/subtle, bordure background/border/subtle. Largeur fluide (fixée par le conteneur), 40 px de haut ; s'il manque de place, « Domicile - » est tronqué avec une ellipse et le sens reste visible. Libellés français par défaut : Ogust passe labels traduits. Données non typées : direction est obligatoire et accepte aussi les libellés français « Départ » / « Retour » (casse, espaces et accents ignorés) ; absent, null, vide ou inconnu, rien n'est rendu (jamais un sens deviné).

Props :

Prop Type Défaut Description
direction HomeStepDirection | null obligatoire 'departure' « Départ », 'return' « Retour » : second segment du libellé ; sans sens valide, rien n'est rendu
labels HomeStepLabels libellés français place (« Domicile »), departure, return : libellés traduits ; un libellé absent ou vide garde le français
<HomeStep direction="return" />

CompatibilityPopup

Popup d'information (role="tooltip") affiché au survol et au focus clavier du score de compatibilité d'un intervenant (matching intervenant / intervention). En-tête : badge du score global (ScoreBadge) et titre « Score de compatibilité » (text/strong, body/sm, tronqué s'il dépasse) ; puis un séparateur et une CriterionRow par critère. Le score global et les critères sont fournis par l'algorithme de matching : le composant ne déduit pas l'un de l'autre. Niveau du badge déduit du score (≥ 75 success, ≥ 50 warning, sinon error) ou forcé par level ; niveau de chaque critère fourni, jamais recalculé par seuils : il ne se déduit pas de X/Y (10/15 peut être une alerte), il est donc annoncé en texte masqué (« 10/15, à surveiller. »), traduisible via criterionLabels. Non interactif ; l'affichage et le placement relèvent du déclencheur, qui doit être focusable, ouvrir le popup au survol et au focus (fermer au mouseleave / blur) et porter aria-describedby vers l'id du popup (attribut id transmis à la racine). Placement : à droite du score, aligné en haut, décalé de 10 px, à gauche si la place manque, sans flèche. Largeur fixe de 254 px (règle DS n°10, contrairement aux autres popups). Données non typées : value / max acceptés en chaîne décimale ("7,5"), affichés tels que reçus (chaîne formatée par l'appelant conservée ; nombre arrondi à 2 décimales, avec un point : passer une chaîne pour un séparateur localisé) ; critère sans libellé, avec un nombre illisible ou négatif, ou un niveau hors liste → ligne non rendue ; criteria doit être un tableau (une chaîne JSON est à parser par l'hôte), sinon aucune ligne ; score invalide (non décimal, hors 0–100) → pas de badge ; sans score valide ni critère valide, le popup n'est pas rendu ; sans critère, pas de séparateur. Titre par défaut et qualifications en français : Ogust passe title, scoreLabels et criterionLabels traduits. Socle commun avec les autres popups (mixin popup-surface).

Props :

Prop Type Défaut Description
score number | string — Score global sur 100, affiché dans le badge (arrondi)
level ScoreBadgeLevel déduit du score Force le niveau du badge
criteria CompatibilityPopupCriterion[] — { label, value, max, level } par critère, dans l'ordre d'affichage
title string Score de compatibilité Titre traduit ; absent ou vide → titre français
scoreLabels ScoreBadgeLabels libellés français Texte masqué du badge traduit (context vide par défaut, ou null : le titre le porte)
criterionLabels CriterionRowLabels « bon », « à surveiller », « insuffisant » Qualification lue du niveau de chaque critère, traduite
<CompatibilityPopup
  id="worker-12-compatibility"
  :score="88"
  :criteria="[
    { label: 'Compatibilité bénéficiaire', value: 25, max: 25, level: 'success' },
    { label: 'Équilibre charge de travail', value: 10, max: 15, level: 'warning' },
  ]"
/>

CriterionRow

Ligne de critère du CompatibilityPopup : point coloré décoratif (aria-hidden), libellé (text/strong, body/sm, retour à la ligne), score X/Y (label/sm, text/success · text/warning · text/danger) et barre de 4 px (piste status/*/subtle, remplissage status/*/default) de largeur value / max, bornée à 100 % (max à 0 → barre vide ; à 0 seule la piste reste). Barre visuelle seulement (aria-hidden) : la valeur est lue dans X/Y. Le niveau est fourni par l'algorithme (casse ignorée) et annoncé en texte masqué après le score (« 10/15, à surveiller. »), traduisible via labels ; libellé vide, nombre illisible ou négatif, ou niveau hors liste → rien n'est rendu.

Props :

Prop Type Défaut Description
label string | number — Libellé du critère
value number | string — Points obtenus (chaîne décimale acceptée, virgule comprise)
max number | string — Points maximum
level CriterionRowLevel — 'success' 'warning' 'error'
labels CriterionRowLabels « bon », « à surveiller », « insuffisant » Qualification lue du niveau, traduite
<CriterionRow label="Disponibilité des clés" :value="2" :max="4" level="error" />

ScoringPanel

Panneau de paramétrage du scoring d'affectation (matching intervenant / intervention) : en-tête (titre emphasis/lg, sous-titre text/subtle, bouton de fermeture icône seule 24 px dans une zone de 32 px, aria-label traduisible), une ligne par critère (SliderBase 0–50 pas 1 : libellé, curseur natif réglable au clavier, valeur « {n} pts » en affichage seul, unités traduisibles), puis un pied ButtonBase « Rétablir par défauts » (secondary, icône reset) / « Appliquer » (primary) ancré en bas. Chaque pondération va de 0 à 50 points, indépendamment des autres (aucune contrainte de somme) ; centre du pouce = valeur / 50 de la piste = fin du remplissage. La valeur suit le curseur à la souris comme au clavier (flèches) : le composant garde une copie locale et émet update:modelValue à chaque mouvement (v-model). update:modelValue et apply renvoient les critères reçus, seuls ceux réglés par l'utilisateur prenant leur nouvelle valeur (entière) ; reset n'a pas de valeur : les pondérations par défaut ne sont pas définies dans Figma, l'hôte les fournit en réaffectant modelValue, puis les curseurs reprennent les valeurs reçues (même tableau qu'au départ compris). La croix (close) n'annule rien : pour un brouillon annulable, lier v-model à une copie de travail et n'enregistrer que sur apply. Largeur 345 px, hauteur portée par l'hôte : la liste défile si elle dépasse, l'en-tête et le pied restent visibles. Données non typées : modelValue doit être un tableau (une chaîne JSON est à parser par l'hôte), value accepté en chaîne décimale et arrondi à l'entier ; critère sans libellé, ou valeur illisible ou hors 0–50 → ligne non rendue (et renvoyée inchangée dans les événements) ; textes absents ou vides → libellés français. Les boutons du pied ne soumettent jamais un <form> englobant.

Props :

Prop Type Défaut Description
modelValue ScoringPanelCriterion[] — { key, label, value } par critère, dans l'ordre d'affichage (v-model)
title string Paramétrage du scoring Titre de l'en-tête
subtitle string Ajustez l’importance du scoring Sous-titre
resetLabel string Rétablir par défauts Libellé du bouton secondaire
submitLabel string Appliquer Libellé du bouton primaire
closeLabel string Fermer Nom accessible du bouton de fermeture
unitLabel string pts Unité affichée après la valeur
unitSpokenLabel string points Unité lue par le lecteur d'écran

Événements : update:modelValue (critères, à chaque mouvement d'un curseur), apply (critères aux valeurs courantes), reset (sans valeur), close (sans annulation)

<ScoringPanel
  v-model="criteria"
  @apply="saveWeights"
  @reset="criteria = defaultCriteria()"
  @close="panelOpen = false"
/>

ScoreBadge

Pastille ronde de 44 × 44 px affichant le score global de compatibilité (matching intervenant / intervention) en pourcentage, fond status/*/subtle et texte text/* (emphasis/sm) selon le niveau. Le score, calculé par l'algorithme de matching, est arrondi à l'entier ; le niveau est déduit du score arrondi (≥ 75 success, ≥ 50 warning, sinon error — seuils valables pour le score global uniquement, pas pour les lignes de critère) et peut être forcé par level (couleur et qualification lue). Score attendu sur 100 (pas un ratio 0–1). Données non typées : score accepté en chaîne décimale ("88", "74,5") ; absent, vide, non décimal ("1e2", "0x32", "88%") ou hors 0–100 (testé avant l'arrondi) → rien n'est rendu ; level hors liste ignoré, casse ignorée. Le niveau est annoncé en texte masqué (« 88% de compatibilité, score élevé. »), traduisible via labels ; context: "" retire « de compatibilité » quand le parent porte déjà ce titre.

Props :

Prop Type Défaut Description
score number | string — Score 0–100, arrondi à l'entier ; absent ou invalide → rien n'est rendu
level ScoreBadgeLevel déduit du score 'success' 'warning' 'error' : force la couleur et la qualification lue
labels ScoreBadgeLabels libellés français context, success, warning, error : texte masqué traduit
<ScoreBadge :score="88" />

StatCard

Carte de statistique du planning, non interactive (pas de rôle, pas de focus) : libellé (label/sm, text/subtle), valeur mise en avant (emphasis/md, text/strong) et plage (body/xs, text/primary), fond background/subtle, bordure 0,5 px background/border/default. Largeur 100% de la cellule de l'hôte (154 × 80 px nominal, 197 × 72 px dans la grille 2 colonnes du WorkerDayPanel), hauteur au contenu. Le libellé et la valeur passent à la ligne ; la plage reste sur une ligne, tronquée par une ellipse. Les textes sont affichés tels que fournis (pas de changement de casse). Données non typées : une ligne vide, null, faite d'espaces, booléenne ou NaN n'est pas rendue (un nombre 0 l'est) ; sans aucune donnée, la carte n'est pas rendue.

Props :

Prop Type Défaut Description
label string — Libellé de l'indicateur (ligne 1)
value string | number — Valeur mise en avant (ligne 2) : durée, nombre d'interventions, de trajets…
range string — Plage ou complément (ligne 3), tronqué par une ellipse
<StatCard label="Amplitude" value="8h" range="00:00 - 18:00" />

WorkerDayPanel

Panneau de détail affiché au clic sur la tournée d'un intervenant dans le planning (<aside> nommé par le nom de l'intervenant, sans nom s'il est absent). En-tête : AvatarBase lg primary décoratif (aria-hidden, rendu seulement avec des initiales ou une photo), nom (emphasis/lg, text/primary, une ligne tronquée), compteur formaté par l'hôte (emphasis/md, text/subtle), bouton de fermeture icône seule (croix 24 px icon/primary dans une zone de 32 px, aria-label « Fermer » traduisible, focus visible). Puis une StatCard par élément de stats en grille de 2 colonnes (gap 10 px), la carte de la tournée fournie par l'hôte dans le slot map (393 px de haut, coins radius/sm ; sans slot, rien n'est rendu : la lib n'intègre ni image ni marqueur) et le « Parcours du jour » (WorkerDayJourney). Fond background/default, ombre shadow/sm, padding et espacements spacing/3. Largeur 443 px (bornée à 100 %), hauteur portée par l'hôte : l'en-tête, la synthèse et la carte restent fixes, seule la liste du parcours défile. Croix et Échap (si le focus est dans le panneau ou nulle part, sans intercepter l'événement, comme FilterPanel) émettent close : l'hôte masque le panneau et rend le focus à la tournée cliquée. Aucune valeur de la maquette en défaut. Données non typées : stats / journey non tableau → rien ; carte de synthèse sans donnée écartée ; nom, initiales, compteur null ou vides → non rendus.

Props :

Prop Type Défaut Description
workerName string | null obligatoire Nom de l'intervenant, titre du panneau
initials string — Initiales de l'avatar, fournies par l'hôte (jamais déduites du nom)
avatarSrc string — Photo de l'intervenant (à la place des initiales)
interventionsLabel string | number — Compteur formaté (« 2 interventions »), pluriel et traduction par l'hôte
stats WorkerDayPanelStat[] — { label, value, range } par carte de synthèse, dans l'ordre
journey WorkerDayJourneyStep[] — Étapes du parcours, dans l'ordre (voir WorkerDayJourney)
labels WorkerDayPanelLabels libellés français close (« Fermer »), journeyTitle (« Parcours du jour »)
homeStepLabels HomeStepLabels libellés français Libellés traduits des étapes domicile

Événements : close (clic sur la croix ou Échap), intervention-click (WorkerDayJourneyInterventionStep : clic sur une carte d'intervention du parcours)

Slots : map (carte de la tournée)

<WorkerDayPanel
  worker-name="Daniel LOURSE"
  initials="DL"
  interventions-label="2 interventions"
  :stats="[{ label: 'Amplitude', value: '8h', range: '00:00 - 18:00' }]"
  :journey="[
    { type: 'home', direction: 'departure' },
    { type: 'trip', label: '15 min - 8.3 km' },
    { type: 'intervention', id: 101, activity: 'jardinage', clientName: 'Mme. Simon', time: '07:00 - 09:00', status: 'completed' },
    { type: 'home', direction: 'return' },
  ]"
  @close="panelOpen = false"
  @intervention-click="openIntervention($event.id)"
>
  <template #map><TourMap :worker-id="12" /></template>
</WorkerDayPanel>

WorkerDayJourney

« Parcours du jour » du WorkerDayPanel (section nommée par son titre body/md, text/subtle), puis une liste ordonnée <ol> des étapes, espacées de spacing/2 : HomeStep pour une étape domicile, texte centré non cliquable (body/sm, text/subtle, sans soulignement) pour un trajet, InterventionCard pleine largeur pour une intervention (icônes téléphone / répétition selon les booléens de chaque intervention). Prend la hauteur restante de son conteneur flex : le titre reste visible, la liste défile. Une carte d'intervention est un bouton : son clic émet intervention-click avec l'étape reçue. Données non typées : liste non tableau ou vide → rien n'est rendu ; type d'étape inconnu (casse ignorée), trajet sans libellé ou domicile sans sens valide (même règle que HomeStep) → étape non rendue, et sans aucune étape valide la section n'est pas rendue ; intervention sans activité, ou d'activité « trajet », → carte neutre (jamais « Jardinage » par défaut) ; clientName, activityLabel, time vides ou faits d'espaces → absents.

Props :

Prop Type Défaut Description
steps WorkerDayJourneyStep[] — Étapes dans l'ordre du parcours
title string Parcours du jour Titre de la section
homeStepLabels HomeStepLabels libellés français Libellés traduits des étapes domicile

Événements : intervention-click (WorkerDayJourneyInterventionStep)

<WorkerDayJourney :steps="journey" @intervention-click="openIntervention($event.id)" />

Alert

Bandeau d'alerte inline qui informe ou alerte l'utilisateur dans une page : pastille d'icône colorée 28 px (décorative, aria-hidden), titre (emphasis/lg, text/success|danger|info|warning), description (body/md, text/primary) et croix de fermeture (icône close 20 px en icon/subtle, zone cliquable 32 px, aria-label traduisible), sur fond status/*/subtle, rayon radius/md. Statuts : success (glyphe check), error (x), info et warning (alert-circle) ; role="status" pour success et info, role="alert" pour error et warning. Avec cancelable et le statut success uniquement, une action texte « Annuler » (emphasis/md, soulignée au survol, zone cliquable 32 px) s'affiche sur sa propre ligne, alignée à droite. Les deux boutons ont un contour de focus background/border/focus et ne soumettent jamais un <form> englobant (type="button"). L'alerte ne se masque pas elle-même : elle émet close / cancel, le parent la retire (et rétablit l'état précédent pour cancel) puis replace le focus. Largeur fluide (celle du conteneur), textes qui passent à la ligne sans troncature. Données non typées : statut sans tenir compte de la casse, code Ogust danger (classes alert-danger, flash addFlash('danger')) rendu comme error, absent ou hors liste → rendu neutre info ; titre ou description vide, null ou fait d'espaces → ligne non rendue, et sans aucun des deux rien n'est visible mais le conteneur reste dans le DOM (la région live role="status" / "alert" doit exister avant son contenu pour qu'un lecteur d'écran annonce une alerte qui apparaît) ; `cancelable:

Version History

Version Released License
1.2.69 Proprietary
1.2.68 Proprietary
1.2.67 Proprietary
1.2.66 Proprietary
1.2.65 Proprietary