fix: readonly component style + TabList + required component (#61)
Release / release (push) Successful in 1m24s

| 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: #61
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #61.
This commit is contained in:
2026-06-04 06:45:24 +00:00
committed by Autin
parent b55050b2ad
commit 9ff3e83c03
58 changed files with 3192 additions and 167 deletions
+52 -10
View File
@@ -2,6 +2,8 @@
Tous les composants sont auto-importés avec le préfixe `Malio`. Utiliser `v-model` pour le binding bidirectionnel sur les composants de formulaire.
> **Champ obligatoire :** sur les composants de formulaire, la prop `required` ajoute un astérisque rouge dans le label. C'est un repère visuel ; la sémantique « obligatoire » est portée par l'attribut natif `required` ou `aria-required`.
---
## MalioInputText
@@ -15,10 +17,11 @@ Champ texte avec label, icône optionnelle et support de masque de saisie.
| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
| `disabled` | `boolean` | `false` | Désactive le champ |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `iconName` | `string` | `''` | Icône Iconify (ex: `mdi:magnify`) |
| `iconPosition` | `'left' \| 'right'` | `'right'` | Position de l'icône |
| `iconSize` | `string \| number` | `24` | Taille icône |
@@ -53,9 +56,11 @@ Champ mot de passe avec toggle visibilité.
| `displayIcon` | `boolean` | `true` | Afficher l'icône toggle |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: string)`
@@ -79,10 +84,12 @@ Champ email (`type="email"` + `inputmode="email"`) avec icône `mdi:email-outlin
| `autocomplete` | `string` | `'off'` | Autocomplétion (passer `'email'` pour suggérer l'email utilisateur) |
| `disabled` | `boolean` | `false` | Désactive le champ |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `lowercase` | `boolean` | `false` | Normalise la saisie en minuscules à la frappe |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `iconName` | `string` | `'mdi:email-outline'` | Icône Iconify (chaîne vide pour masquer) |
| `iconPosition` | `'left' \| 'right'` | `'right'` | Position de l'icône |
| `iconSize` | `string \| number` | `24` | Taille icône |
@@ -91,6 +98,8 @@ Champ email (`type="email"` + `inputmode="email"`) avec icône `mdi:email-outlin
| `labelClass` | `string` | `''` | Classes CSS label |
| `groupClass` | `string` | `''` | Classes CSS conteneur |
> **Sanitisation à la saisie :** tous les espaces sont supprimés automatiquement au fil de la frappe (sans masque). Avec `lowercase=true`, la valeur est également convertie en minuscules à la frappe. La validation du format (ex. présence d'un `@`) reste à la charge du parent via la prop `error` ou la couche de validation.
**Events :** `update:modelValue(value: string)`
```vue
@@ -115,10 +124,11 @@ Champ téléphone (`type="tel"` + `inputmode="tel"`) avec icône `mdi:phone-outl
| `autocomplete` | `string` | `'off'` | Autocomplétion (passer `'tel'` pour suggérer un numéro enregistré) |
| `disabled` | `boolean` | `false` | Désactive le champ et le bouton + |
| `readonly` | `boolean` | `false` | Lecture seule (désactive aussi le bouton +) |
| `required` | `boolean` | `false` | Champ requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `iconName` | `string` | `'mdi:phone-outline'` | Icône Iconify (chaîne vide pour masquer) |
| `iconPosition` | `'left' \| 'right'` | `'left'` | Position de l'icône |
| `iconSize` | `string \| number` | `24` | Taille icône |
@@ -169,10 +179,11 @@ Champ de saisie assistée (typeahead / combobox) : l'utilisateur tape pour filtr
| `minSearchText` | `string` | `'Tapez pour rechercher'` | Texte affiché tant que `minSearchLength` n'est pas atteint |
| `disabled` | `boolean` | `false` | Désactive le champ et empêche l'ouverture |
| `readonly` | `boolean` | `false` | Lecture seule (n'ouvre pas le dropdown) |
| `required` | `boolean` | `false` | Champ requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur (prioritaire) |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` | `string` | `''` | Classes CSS input |
| `labelClass` | `string` | `''` | Classes CSS label |
| `groupClass` | `string` | `''` | Classes CSS conteneur |
@@ -231,7 +242,9 @@ Champ montant avec icône devise (euro par défaut).
| `label` | `string` | `''` | Label |
| `iconName` | `string` | `'mdi:currency-eur'` | Icône devise |
| `disabled` | `boolean` | `false` | Désactivé |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: string)`
@@ -253,7 +266,9 @@ Champ numérique avec boutons +/-.
| `min` | `number \| string` | — | Valeur minimum |
| `max` | `number \| string` | — | Valeur maximum |
| `disabled` | `boolean` | `false` | Désactivé |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: string)`
@@ -276,7 +291,9 @@ Zone de texte multiligne avec compteur et redimensionnement.
| `maxLength` | `number` | `800` | Longueur max |
| `showCounter` | `boolean` | `false` | Afficher le compteur |
| `disabled` | `boolean` | `false` | Désactivé |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `groupClass` | `string` | `''` | Classes CSS sur la div conteneur (utile pour `row-span-*`, `col-span-*`, etc.) |
**Events :** `update:modelValue(value: string)`
@@ -304,9 +321,11 @@ Zone de texte multiligne avec compteur et redimensionnement.
| `editable` | `boolean` | `true` | `false` → mode affichage seul (toolbar masquée) |
| `disabled` | `boolean` | `false` | Désactive l'édition et la toolbar |
| `readonly` | `boolean` | `false` | Lecture seule (toolbar visible mais désactivée) |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `outputFormat` | `'markdown' \| 'html'` | `'html'` | Format émis dans `update:modelValue` |
| `groupClass` | `string` | `''` | Classes CSS conteneur (twMerge) |
| `labelClass` | `string` | `''` | Classes CSS label (twMerge) |
@@ -334,7 +353,10 @@ Champ d'upload de fichier.
| `accept` | `string` | `''` | Types de fichiers acceptés |
| `displayIcon` | `boolean` | `true` | Afficher l'icône |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Champ en lecture seule (bordure noire, pas de focus bleu/grossissement, label/icône gris→noir selon rempli). |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: string)`, `file-selected(file: File)`
@@ -357,7 +379,10 @@ Liste déroulante.
| `hint` | `string` | `''` | Message d'aide |
| `error` | `string` | `''` | Message d'erreur |
| `success` | `string` | `''` | Message de succès |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Champ en lecture seule (bordure noire, pas de focus bleu/grossissement, label/icône gris→noir selon rempli). |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `groupClass` | `string` | `''` | Classes CSS conteneur (twMerge) |
| `rounded` | `string` | `'rounded-md'` | Classe border-radius |
| `textField` | `string` | `'text-lg'` | Classe taille texte bouton |
@@ -382,13 +407,16 @@ Liste déroulante multi-sélection avec checkboxes.
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| `modelValue` | `(string \| number)[]` | **requis** | Valeurs sélectionnées (v-model) |
| `modelValue` | `(string \| number)[]` | `[]` | Valeurs sélectionnées (v-model) |
| `options` | `{ value: string \| number, text: string }[]` | `[]` | Options |
| `displayTag` | `boolean` | `false` | Afficher les tags sélectionnés |
| `displaySelectAll` | `boolean` | `false` | Afficher "Tout sélectionner" |
| `selectAllLabel` | `string` | `'Tout sélectionner'` | Texte du sélecteur global |
| `label` | `string` | `''` | Label |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Champ en lecture seule (bordure noire, pas de focus bleu/grossissement, label/icône gris→noir selon rempli). |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `noOptionsText` | `string` | `'Aucune option disponible'` | Message affiché dans la dropdown quand `options` est vide |
**Events :** `update:modelValue(value: (string | number)[])`
@@ -410,7 +438,9 @@ Case à cocher.
| `label` | `string` | `''` | Label |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: boolean)`
@@ -433,6 +463,7 @@ Bouton radio (à utiliser en groupe avec le même `name`).
| `name` | `string` | `''` | Nom du groupe radio |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
**Events :** `update:modelValue(value: string | number | boolean | null)`
@@ -456,7 +487,7 @@ La valeur est une chaîne ISO `"YYYY-MM-DD"`. Cliquer un jour émet la date et f
| `name` | `string` | `''` | Attribut name |
| `label` | `string` | `''` | Label flottant |
| `placeholder` | `string` | `'JJ/MM/AAAA'` | Placeholder |
| `required` | `boolean` | `false` | Requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `hint` | `string` | `''` | Texte d'aide |
@@ -465,6 +496,7 @@ La valeur est une chaîne ISO `"YYYY-MM-DD"`. Cliquer un jour émet la date et f
| `min` | `string` | `undefined` | Date min `"YYYY-MM-DD"` (jours antérieurs désactivés) |
| `max` | `string` | `undefined` | Date max `"YYYY-MM-DD"` (jours postérieurs désactivés) |
| `clearable` | `boolean` | `true` | Affiche la croix d'effacement |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: string | null)`
@@ -490,7 +522,7 @@ La valeur est un objet `{ start: string; end: string }` (dates ISO `"YYYY-MM-DD"
| `name` | `string` | `''` | Attribut name |
| `label` | `string` | `''` | Label flottant |
| `placeholder` | `string` | `'JJ/MM/AAAA'` | Placeholder |
| `required` | `boolean` | `false` | Requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `hint` | `string` | `''` | Texte d'aide |
@@ -499,6 +531,7 @@ La valeur est un objet `{ start: string; end: string }` (dates ISO `"YYYY-MM-DD"
| `min` | `string` | `undefined` | Date min `"YYYY-MM-DD"` |
| `max` | `string` | `undefined` | Date max `"YYYY-MM-DD"` |
| `clearable` | `boolean` | `true` | Affiche la croix d'effacement |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: { start: string; end: string } | null)`
@@ -523,7 +556,7 @@ La valeur est une chaîne au format **semaine ISO native** `"YYYY-Www"` (ex. `"2
| `name` | `string` | `''` | Attribut name |
| `label` | `string` | `''` | Label flottant |
| `placeholder` | `string` | `'JJ/MM/AAAA'` | Placeholder |
| `required` | `boolean` | `false` | Requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `hint` | `string` | `''` | Texte d'aide |
@@ -532,6 +565,7 @@ La valeur est une chaîne au format **semaine ISO native** `"YYYY-Www"` (ex. `"2
| `min` | `string` | `undefined` | Date min `"YYYY-MM-DD"` |
| `max` | `string` | `undefined` | Date max `"YYYY-MM-DD"` |
| `clearable` | `boolean` | `true` | Affiche la croix d'effacement |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: string | null)`
@@ -553,7 +587,9 @@ Sélecteur d'heure.
| `label` | `string` | `''` | Label |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `error` | `string` | `''` | Message d'erreur |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
**Events :** `update:modelValue(value: string)`
@@ -575,13 +611,14 @@ Sélecteur d'heure à **molettes style iOS** (champ + popover). Deux colonnes in
| `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 |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `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 |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: string | null)`
@@ -608,7 +645,7 @@ La valeur est une chaîne **ISO naïve sans fuseau** au format `"YYYY-MM-DDTHH:M
| `name` | `string` | `''` | Attribut name |
| `label` | `string` | `''` | Label flottant |
| `placeholder` | `string` | `'JJ/MM/AAAA HH:MM'` | Placeholder |
| `required` | `boolean` | `false` | Requis |
| `required` | `boolean` | `false` | Champ requis (astérisque rouge dans le label) |
| `disabled` | `boolean` | `false` | Désactivé |
| `readonly` | `boolean` | `false` | Lecture seule |
| `hint` | `string` | `''` | Texte d'aide |
@@ -617,6 +654,7 @@ La valeur est une chaîne **ISO naïve sans fuseau** au format `"YYYY-MM-DDTHH:M
| `min` | `string` | `undefined` | Borne min (datetime ou date ; borne la grille sur la partie date) |
| `max` | `string` | `undefined` | Borne max (idem) |
| `clearable` | `boolean` | `true` | Affiche la croix d'effacement |
| `reserveMessageSpace` | `boolean` | `true` | Réserve l'espace de la ligne message sous le champ (min-h) même sans message. `false` = la ligne ne prend de place que s'il y a un hint/error/success. |
| `inputClass` / `labelClass` / `groupClass` | `string` | `''` | Override des classes |
**Events :** `update:modelValue(value: string | null)`
@@ -690,6 +728,10 @@ Navigation par onglets avec contenu dynamique.
|------|------|--------|-------------|
| `modelValue` | `string` | `undefined` | Onglet actif (v-model) |
| `tabs` | `Tab[]` | **requis** | Liste des onglets (voir type ci-dessous) |
| `maxVisibleTabs` | `number` | `undefined` | Nombre max d'onglets affichés à la fois. Au-delà, un carrousel avec flèches gauche/droite apparaît (décalage 1 par 1). Non défini = tous les onglets. |
| `maxWidth` | `number` | `1100` | Largeur max (px) du bloc d'onglets en mode fenêtré. |
Quand `maxVisibleTabs` est défini et que le nombre d'onglets le dépasse, la barre passe en mode fenêtré : seuls `maxVisibleTabs` onglets sont visibles à la fois, encadrés par des flèches gauche/droite qui font défiler la fenêtre un onglet à la fois (largeur du bloc bornée par `maxWidth`).
Type `Tab` :