feat: Ajout des composants modal, accordeon, datetime avec selecteur d'heure à la molette (#56)
Release / release (push) Successful in 2m38s

| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

---------

Co-authored-by: THOLOT DECHENE Matthieu <matthieu@yuno.malio.fr>
Co-authored-by: matthieu <matthieu@yuno.malio.fr>
Reviewed-on: #56
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #56.
This commit is contained in:
2026-05-27 12:11:51 +00:00
committed by Autin
parent 7d7b2fb720
commit acd531f69e
36 changed files with 6581 additions and 30 deletions
+160 -1
View File
@@ -563,11 +563,40 @@ Sélecteur d'heure.
---
## MalioTimePicker
Sélecteur d'heure à **molettes style iOS** (champ + popover). Deux colonnes infinies (heures `0023`, minutes `0059`, pas de 1) avec une bande de sélection centrale ; la valeur centrée est sélectionnée. Défilement, clic sur une valeur (recentrage) ou flèches clavier (`role="spinbutton"`). Pour une saisie clavier directe au format texte, voir plutôt `MalioTime`.
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `id` | `string` | auto | Identifiant HTML |
| `name` | `string` | `''` | Attribut name |
| `label` | `string` | `''` | Label flottant |
| `modelValue` | `string \| null` | `undefined` | Heure au format `"HH:MM"` (v-model) |
| `placeholder` | `string` | `'HH:MM'` | Placeholder |
| `required` | `boolean` | `false` | Champ requis |
| `disabled` | `boolean` | `false` | Désactive le champ |
| `readonly` | `boolean` | `false` | Lecture seule |
| `clearable` | `boolean` | `true` | Affiche la croix d'effacement |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: string | null)`
```vue
<MalioTimePicker v-model="heure" label="Heure" />
<MalioTimePicker v-model="heure" label="Départ" hint="Format HH:MM" />
```
---
## MalioDateTime
Champ unique combinant **date et heure** dans un popover (grille de calendrier + sélecteur d'heure sous la grille).
> ⚠️ **Version intérimaire** : le sélecteur d'heure est un `<input type="time">` natif, en attendant la maquette d'un sélecteur d'heure dédié. Le bloc heure est isolé pour être remplacé sans impact sur le reste.
> Depuis MUI-39, le réglage de l'heure utilise le sélecteur à molettes (cf. `MalioTimePicker`), qui remplace l'ancien `<input type="time">` natif intérimaire.
La valeur est une chaîne **ISO naïve sans fuseau** au format `"YYYY-MM-DDTHH:MM:00"` (heure murale locale). Symfony (`DateTimeNormalizer`) parse ce format et applique son fuseau configuré côté back — pas de gestion de fuseau côté front.
@@ -694,6 +723,54 @@ const tabs = computed(() => [
---
## MalioAccordion
Accordéon compositionnel : `<MalioAccordion>` enveloppe des `<MalioAccordionItem>`. Plusieurs panneaux ouverts (`multiple`, défaut) ou un seul (`single`). Pensé pour les filtres en drawer et les FAQ.
### MalioAccordion
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `mode` | `'single' \| 'multiple'` | `'multiple'` | Un seul ou plusieurs panneaux ouverts |
| `modelValue` | `string \| string[]` | `undefined` | Clés ouvertes (v-model). `string[]` en `multiple`, `string` en `single` |
| `id` | `string` | auto | Préfixe des IDs d'accessibilité |
| `groupClass` | `string` | `''` | Classes du conteneur (twMerge) |
**Events :** `update:modelValue(value: string | string[])`
### MalioAccordionItem
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `title` | `string` | — | Texte de l'en-tête |
| `value` | `string` | auto | Clé unique de la section |
| `defaultOpen` | `boolean` | `false` | Ouvert au montage (mode non contrôlé) |
| `disabled` | `boolean` | `false` | En-tête non cliquable |
| `headerClass` | `string` | `''` | Override classes en-tête (twMerge) |
| `panelClass` | `string` | `''` | Override classes panneau (twMerge) |
**Slot :** par défaut = contenu du panneau.
```vue
<!-- Filtres : plusieurs sections ouvertes -->
<MalioAccordion v-model="ouverts">
<MalioAccordionItem title="Prix" value="prix">
<MalioInputAmount v-model="prix" />
</MalioAccordionItem>
<MalioAccordionItem title="Catégorie" value="cat">
<MalioCheckbox v-model="cats" />
</MalioAccordionItem>
</MalioAccordion>
<!-- FAQ : une seule section ouverte -->
<MalioAccordion mode="single">
<MalioAccordionItem title="Question 1" value="q1">Réponse 1</MalioAccordionItem>
<MalioAccordionItem title="Question 2" value="q2">Réponse 2</MalioAccordionItem>
</MalioAccordion>
```
---
## MalioSidebar
Barre latérale de navigation rétractable.
@@ -779,6 +856,58 @@ Panneau latéral (drawer) qui s'ouvre depuis la droite ou la gauche avec backdro
---
## MalioModal
Boîte de dialogue modale centrée avec backdrop semi-transparent. Gère l'accessibilité (focus-trap, restitution du focus, `Échap`), le verrouillage du scroll de la page et un empilement correct de plusieurs modals. Structure : header fixe, body scrollable (`max-h-[85vh]`), footer fixe.
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `id` | `string` | auto | Identifiant HTML |
| `modelValue` | `boolean` | `undefined` | État ouvert/fermé (v-model) |
| `showClose` | `boolean` | `true` | Afficher le bouton de fermeture (croix) |
| `dismissable` | `boolean` | `true` | Fermer au clic sur le backdrop |
| `closeOnEscape` | `boolean` | `true` | Fermer avec la touche `Échap` |
| `ariaLabel` | `string` | `''` | Nom accessible de secours quand le slot `#header` est absent |
| `modalClass` | `string` | `''` | Classes CSS panneau, ex. largeur `max-w-lg` (twMerge) |
| `overlayClass` | `string` | `''` | Classes CSS backdrop (twMerge) |
| `headerClass` | `string` | `''` | Classes CSS barre header (twMerge) |
| `bodyClass` | `string` | `''` | Classes CSS zone scrollable (twMerge) |
| `footerClass` | `string` | `''` | Classes CSS footer fixe (twMerge) |
**Events :** `update:modelValue(value: boolean)`, `close()`
**Slots :**
- `header` — en-tête (titre, etc.). S'il est absent et que `showClose` est `true`, seule la croix est affichée.
- `default` — contenu (zone scrollable).
- `footer` — actions (boutons). Rendu en bas, fixe, séparé par une bordure. N'apparaît que si le slot est fourni.
```vue
<MalioModal v-model="isOpen">
<template #header>
<h2 class="text-[24px] font-bold">Détails</h2>
</template>
<p>Contenu de la modal</p>
</MalioModal>
<!-- Largeur custom + footer d'actions -->
<MalioModal v-model="isOpen" modal-class="max-w-lg">
<template #header><h2>Nouveau contact</h2></template>
<MalioInputText label="Nom" />
<template #footer>
<MalioButton label="Annuler" variant="secondary" button-class="flex-1" @click="isOpen = false" />
<MalioButton label="Enregistrer" button-class="flex-1" @click="isOpen = false" />
</template>
</MalioModal>
<!-- Non fermable au backdrop / Échap (croix uniquement) -->
<MalioModal v-model="isOpen" :dismissable="false" :close-on-escape="false">
<template #header><h2>Action requise</h2></template>
<p>Fermeture via la croix uniquement</p>
</MalioModal>
```
---
## MalioDataTable
Tableau de données presentational avec pagination, filtres par slots et lignes cliquables.
@@ -832,3 +961,33 @@ Tableau de données presentational avec pagination, filtres par slots et lignes
v-model:per-page="perPage"
/>
```
---
## MalioSiteSelector
Sélecteur de site sous forme de tuiles segmentées (`role="radiogroup"`). Chaque site occupe une tuile de largeur égale ; la tuile active s'affiche pleine opacité dans sa couleur (`site.color`), les autres sont atténuées. Pattern contrôlé (`v-model`) ou non contrôlé (premier site sélectionné par défaut).
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `sites` | `{ id: string, name: string, color: string }[]` | **requis** | Liste des sites (la `color` colore la tuile active) |
| `modelValue` | `string` | `undefined` | `id` du site sélectionné (v-model) |
| `id` | `string` | auto | Identifiant HTML du conteneur |
| `groupClass` | `string` | `''` | Classes CSS du conteneur (twMerge) |
| `tileClass` | `string` | `''` | Classes CSS de chaque tuile (twMerge) |
| `labelClass` | `string` | `''` | Classes CSS du label de tuile (twMerge) |
**Events :**
- `update:modelValue(value: string)``id` du site sélectionné (v-model)
- `change(site: Site)` — émis avec l'objet site complet sélectionné
```vue
<MalioSiteSelector
v-model="siteId"
:sites="[
{ id: 'paris', name: 'Paris', color: '#2563eb' },
{ id: 'lyon', name: 'Lyon', color: '#16a34a' },
]"
@change="onSiteChange"
/>
```