@arche-mc2/vue-ui-lib
| Install | |
|---|---|
npm install @arche-mc2/vue-ui-lib |
|
| Latest Version: | 1.2.69 |
| Vue: | 3 |
| License: | Proprietary |
| Last Updated: | Oct 22, 2026 |
| Links: | npm |
@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
dateintègre un masquedd/mm/yyyyet 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 ligneupdateCheckAll(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 celluleitem['onClick_<key>']→ rend la cellule cliquable (lien<a>)item.actions→ tableauFlyoutMenuItem[]pour le menu d'actions rapidesitem.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énementonChangeView(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 (
authorvide etinitialsvide 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 | |
| 1.2.64 | Proprietary | |
| 1.2.63 | Proprietary | |
| 1.2.62 | Proprietary | |
| 1.2.61 | Proprietary | |
| 1.2.60 | Proprietary | |
| 1.2.59 | Proprietary | |
| 1.2.58 | Proprietary | |
| 1.2.57 | Proprietary | |
| 1.2.56 | Proprietary | |
| 1.2.55 | Proprietary | |
| 1.2.54 | Proprietary | |
| 1.2.53 | Proprietary | |
| 1.2.52 | Proprietary | |
| 1.2.51 | Proprietary | |
| 1.2.50 | Proprietary | |
| 1.2.49 | Proprietary | |
| 1.2.48 | Proprietary | |
| 1.2.47 | Proprietary | |
| 1.2.46 | Proprietary | |
| 1.2.45 | Proprietary | |
| 1.2.44 | Proprietary | |
| 1.2.43 | Proprietary | |
| 1.2.40 | Proprietary | |
| 1.2.39 | Proprietary | |
| 1.2.38 | Proprietary |
Showing the latest 30 of 96. See every release on npm