Calendar et pickers date-temps
Composition
La famille date-temps suit désormais une architecture composée. Les pickers ne réimplémentent pas les calendriers ou les calculs temporels.
API inspirée d'Ant Design
Les capacités retenues sont celles utiles aux applications SIA UI, avec des valeurs sérialisables plutôt que des objets Day.js.
- calendrier contrôlé ou non contrôlé;
- modes
monthetyear; validRangeetdisabledDate;cellRender,headerRenderetrenderExtraFooter;- numéros de semaine avec
showWeek; - sélection simple ou range;
- ouverture contrôlée des pickers;
- effacement, footer et action Aujourd'hui;
- pas temporels, secondes, format 12/24 heures et confirmation;
- ordre automatique des bornes temporelles.
Tons
Tous ces composants acceptent:
type ComponentTone =
| "neutral"
| "primary"
| "info"
| "success"
| "warning"
| "danger";Le ton pilote l'icône, le focus, la sélection, le range et les actions du panneau. Les variables globales restent personnalisables, notamment --sia-primary, --sia-info, --sia-success, --sia-warning et --sia-danger.
ComponentTone est maintenant le contrat unique de la librairie. Alert, Badge, Typography, AmountDisplay, Timeline, EventCalendar, les pickers et les valeurs par défaut du provider importent tous ce même type. Le Spinner l'étend uniquement avec la valeur technique current.
Icônes
Les icônes des contrôles ne dépendent plus du rendu natif du navigateur. La primitive icons fournit des SVG en currentColor, visibles dans les inputs, compatibles avec les tons et sans paquet externe obligatoire.
Valeurs
- date:
YYYY-MM-DD; - heure:
HH:mmouHH:mm:ss; - date range:
{ start, end }; - date-heure:
{ date, time }.
Ce format reste directement transportable dans un formulaire, une URL ou une API backend.
Le calendrier d'événements
Deux composants, l'un pour voir, l'autre pour gérer.
EventCalendar
| Vue | Ce qu'elle montre |
|---|---|
month | six semaines ; heure et titre de chaque rendez-vous, rubans pour les journées et les événements sur plusieurs jours, « +N autres » au-delà de maxEventsPerDay |
week, day | une grille horaire : chaque rendez-vous placé à son heure et sur sa durée, les chevauchements côte à côte, la ligne de l'heure actuelle, une rangée « journée » en haut ; ouverte à scrollToHour (8 h) |
agenda | la liste des jours qui ont des événements, lieu compris |
<EventCalendar
events={evenements} // { id, title, start, end?, allDay?, tone?, location?, description? }
onRangeChange={(periode) => charger(periode)} // la période visible, à chaque navigation
onDateClick={(jour, heure) => …} // l'heure : la demi-heure visée dans la grille
onEventClick={(evenement) => …}
variant="bordered" // bordered · minimal · soft
eventVariant="soft" // soft · solid · outline
density="comfortable" // comfortable · compact
/>Les dates sont des jours ISO (2026-09-30) ou des heures locales (2026-09-30T14:30), jamais des Date UTC : un événement du 30 à 23 h ne glisse pas au 1er selon le fuseau de qui le regarde. Le modèle — grille, période visible, placement horaire — vit dans @sia-ui/headless, sans rendu.
Sous 640 px de largeur du composant, la grille du mois passe en points de couleur et les événements du jour choisi s'affichent dessous : une case de 45 px ne se lit pas, une liste si. Le calendrier est assemblé avec les composants du système — Button, IconButton, RadioGroup en boutons pour les vues, Popover pour « +N autres », EmptyState, Spinner — dont les props passent par toolbarButtonProps, viewSwitchProps, popoverProps…
L'ancien format (date au lieu de start, defaultValue, defaultMonth) reste lu.
Langue et libellés
Les composants de ce guide — Calendar, les sélecteurs de date et d'heure, EventCalendar, EventManager, RelativeTime, DurationDisplay, AuditMeta, EntityMeta, ActivityLog — lisent leurs textes dans la locale SIA (voir Langues, libellés et réglages). Leur prop locale, quand elle existe, vaut par défaut la language de cette locale : noms des jours et des mois, dates relatives et nombres suivent la langue de l'application sans qu'on la répète à chaque composant.
| Groupe | Composants |
|---|---|
calendar | Calendar, MiniCalendar (flèches de mois et d'année) |
timePicker | TimePicker, TimeRangePicker |
dateTimePicker | DateTimePicker |
eventCalendar | EventCalendar — EventCalendarLabels en est l'alias |
eventManager | EventManager — EventManagerLabels en est l'alias, noms des couleurs compris |
durationDisplay | DurationDisplay (unités, au pluriel) |
auditMeta, entityMeta, activityLog | les métadonnées et le journal |
Les textes partagés (« Effacer », « Aujourd'hui », « Sélectionner une date », « Date de début »…) viennent du vocabulaire commun. Une prop (placeholder, startLabel, labels, toneOptions…) garde la main sur la locale.
« +N autres » d'EventCalendar n'est plus une fonction : ce sont deux textes, more_one et more_other, avec {count} — le format d'un fichier de traduction JSON.
EventManager
<EventManager
events={evenements}
onCreate={(brouillon) => api.post("/evenements", { body: brouillon })}
onUpdate={(evenement, brouillon) => api.patch(`/evenements/${evenement.id}`, { body: brouillon })}
onDelete={(evenement) => api.delete(`/evenements/${evenement.id}`)}
extraFields={[{ name: "salle", label: "Salle", type: "select", options: salles }]}
extraDefaults={{ salle: "" }}
/>- Un clic sur un jour ouvre la création à cette date — à la demi-heure visée dans la grille horaire. « Nouvel événement » dans la barre fait de même pour aujourd'hui.
- Un clic sur un événement ouvre sa fiche (
Descriptions, couleur enBadge), d'où l'on modifie ou supprime, avec confirmation. - Le formulaire suit la saisie : pas d'heures pour une journée entière ; la fin doit suivre le début.
- Le serveur a le dernier mot :
onCreateetonUpdatepeuvent rendre{ champ: message }ou lever — le formulaire reste ouvert, erreurs sous les champs.
Les données restent à l'appelant : les rappels reçoivent un brouillon prêt à envoyer ({ title, start, end, allDay, tone, location, description, … }), et le calendrier affiche ce qu'on lui repasse dans events.