diff --git a/.claude/skills/creating-malio-component/SKILL.md b/.claude/skills/creating-malio-component/SKILL.md
index ea139f1..1e6695d 100644
--- a/.claude/skills/creating-malio-component/SKILL.md
+++ b/.claude/skills/creating-malio-component/SKILL.md
@@ -7,7 +7,7 @@ description: Use when creating a new UI component in the @malio/layer-ui Nuxt la
## Overview
-Step-by-step process for creating a component in `@malio/layer-ui`. Each component requires 5 deliverables : le `.vue`, les tests, la page playground, la story Histoire, et la mise à jour du CHANGELOG.
+Step-by-step process for creating a component in `@malio/layer-ui`. Each component requires 6 deliverables : le `.vue`, les tests, la page playground, la story Histoire, la mise à jour du CHANGELOG, et la mise à jour du `COMPONENTS.md`.
## When to Use
@@ -27,6 +27,7 @@ digraph create_component {
"Tests OK?" -> "3. Créer les tests .test.ts" [label="non, corriger"];
"5. Créer la page playground" -> "6. Créer la story Histoire";
"6. Créer la story Histoire" -> "7. Mettre à jour CHANGELOG.md";
+ "7. Mettre à jour CHANGELOG.md" -> "8. Mettre à jour COMPONENTS.md";
}
```
@@ -176,6 +177,37 @@ Pour extraire le numéro de ticket depuis la branche courante :
git branch --show-current | grep -oP '(MUI-\d+|\d{3,})' | head -1
```
+### 8. Mettre à jour COMPONENTS.md
+
+**Fichier :** `COMPONENTS.md` à la racine du projet.
+
+Ce fichier sert de documentation de référence pour les projets qui consomment `@malio/layer-ui`. Il est lu par Claude dans les projets consommateurs pour connaître les composants disponibles et leurs props.
+
+**Ajouter une section pour le nouveau composant** en suivant le format existant :
+
+```markdown
+## MalioNomComposant
+
+Description courte du composant.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| ... | ... | ... | ... |
+
+**Events :** `update:modelValue(value: string)`
+
+\`\`\`vue
+
+\`\`\`
+```
+
+**Checklist :**
+- Toutes les props documentées avec type, défaut et description
+- Events listés
+- Slots listés si applicable
+- 2-5 exemples d'utilisation couvrant les cas courants (simple, avec options, disabled, erreur)
+- Section placée par ordre logique (inputs ensemble, boutons ensemble, etc.)
+
## Common Mistakes
Cette section est alimentée au fur et à mesure des retours utilisateur et des problèmes rencontrés. **Si un retour ou un bug est identifié lors de la création d'un composant, ajouter une ligne dans ce tableau.**
@@ -188,3 +220,4 @@ Cette section est alimentée au fur et à mesure des retours utilisateur et des
| Padding input pas ajusté avec icône | Ajouter `!pr-10` (ou équivalent) quand une icône est présente à droite |
| Story sans initial state | Toujours initialiser les `ref` avec des valeurs pour que les variantes soient visibles dès le chargement |
| CHANGELOG oublié | Toujours ajouter la ligne dans `### Added` avant de commit |
+| COMPONENTS.md pas mis à jour | Ajouter la doc du composant dans `COMPONENTS.md` — c'est la référence pour les projets consommateurs |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 309707e..c5b539c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ Liste des évolutions de la librairie Malio layer UI
* [#MUI-20] Création d'un composant sidebar
* [#MUI-23] Revoir la config couleur tailwind
* [#MUI-10] Création d'un composant bouton
+* [#MUI-2] Faire un MCP pour la librairie de composant
### Changed
diff --git a/COMPONENTS.md b/COMPONENTS.md
new file mode 100644
index 0000000..c103142
--- /dev/null
+++ b/COMPONENTS.md
@@ -0,0 +1,357 @@
+# @malio/layer-ui — Composants
+
+Tous les composants sont auto-importés avec le préfixe `Malio`. Utiliser `v-model` pour le binding bidirectionnel sur les composants de formulaire.
+
+---
+
+## MalioInputText
+
+Champ texte avec label, icône optionnelle et support de masque de saisie.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `id` | `string` | auto | Identifiant HTML |
+| `label` | `string` | `''` | Label du champ |
+| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
+| `disabled` | `boolean` | `false` | Désactive le champ |
+| `readonly` | `boolean` | `false` | Lecture seule |
+| `required` | `boolean` | `false` | Champ requis |
+| `hint` | `string` | `''` | Message d'aide |
+| `error` | `string` | `''` | Message d'erreur |
+| `success` | `string` | `''` | Message de succès |
+| `iconName` | `string` | `''` | Icône Iconify (ex: `mdi:magnify`) |
+| `iconPosition` | `'left' \| 'right'` | `'right'` | Position de l'icône |
+| `iconSize` | `string \| number` | `24` | Taille icône |
+| `iconColor` | `string` | `'text-m-muted'` | Classe couleur icône |
+| `mask` | `string \| MaskInputOptions` | — | Masque de saisie (maska) |
+| `maxLength` | `number \| string` | — | Longueur max |
+| `minLength` | `number \| string` | — | Longueur min |
+| `inputClass` | `string` | `''` | Classes CSS input |
+| `labelClass` | `string` | `''` | Classes CSS label |
+| `groupClass` | `string` | `''` | Classes CSS conteneur |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+
+
+
+
+```
+
+---
+
+## MalioInputPassword
+
+Champ mot de passe avec toggle visibilité.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
+| `label` | `string` | `''` | Label |
+| `displayIcon` | `boolean` | `true` | Afficher l'icône toggle |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `readonly` | `boolean` | `false` | Lecture seule |
+| `hint` | `string` | `''` | Message d'aide |
+| `error` | `string` | `''` | Message d'erreur |
+| `success` | `string` | `''` | Message de succès |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+
+```
+
+---
+
+## MalioInputAmount
+
+Champ montant avec icône devise (euro par défaut).
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
+| `label` | `string` | `''` | Label |
+| `iconName` | `string` | `'mdi:currency-eur'` | Icône devise |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+
+```
+
+---
+
+## MalioInputNumber
+
+Champ numérique avec boutons +/-.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
+| `label` | `string` | `''` | Label |
+| `min` | `number \| string` | — | Valeur minimum |
+| `max` | `number \| string` | — | Valeur maximum |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+```
+
+---
+
+## MalioInputTextArea
+
+Zone de texte multiligne avec compteur et redimensionnement.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Valeur (v-model) |
+| `label` | `string` | `''` | Label |
+| `size` | `number \| string` | `2` | Nombre de lignes |
+| `resize` | `'none' \| 'both' \| 'horizontal' \| 'vertical'` | `'both'` | Mode redimensionnement |
+| `maxLength` | `number` | `800` | Longueur max |
+| `showCounter` | `boolean` | `false` | Afficher le compteur |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+
+```
+
+---
+
+## MalioInputUpload
+
+Champ d'upload de fichier.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Nom du fichier (v-model) |
+| `label` | `string` | `''` | Label |
+| `accept` | `string` | `''` | Types de fichiers acceptés |
+| `displayIcon` | `boolean` | `true` | Afficher l'icône |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string)`, `file-selected(file: File)`
+
+```vue
+
+```
+
+---
+
+## MalioSelect
+
+Liste déroulante.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| number \| null` | **requis** | Valeur sélectionnée (v-model) |
+| `options` | `{ value: string \| number, text: string }[]` | `[]` | Options disponibles |
+| `emptyOptionLabel` | `string` | `''` | Placeholder option vide |
+| `label` | `string` | `''` | Label |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string | number | null)`
+**Slots :** `icon` (icône dropdown custom)
+
+```vue
+
+
+```
+
+---
+
+## MalioSelectCheckbox
+
+Liste déroulante multi-sélection avec checkboxes.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `(string \| number)[]` | **requis** | 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é |
+
+**Events :** `update:modelValue(value: (string | number)[])`
+
+```vue
+
+
+```
+
+---
+
+## MalioCheckbox
+
+Case à cocher.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `boolean \| null` | `undefined` | Valeur (v-model) |
+| `label` | `string` | `''` | Label |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `readonly` | `boolean` | `false` | Lecture seule |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: boolean)`
+
+```vue
+
+
+```
+
+---
+
+## MalioRadioButton
+
+Bouton radio (à utiliser en groupe avec le même `name`).
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| number \| boolean \| null` | `undefined` | Valeur du groupe (v-model) |
+| `value` | `string \| number \| boolean \| null` | `undefined` | Valeur de cette option |
+| `label` | `string` | `''` | Label |
+| `name` | `string` | `''` | Nom du groupe radio |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `readonly` | `boolean` | `false` | Lecture seule |
+
+**Events :** `update:modelValue(value: string | number | boolean | null)`
+
+```vue
+
+
+```
+
+---
+
+## MalioTime
+
+Sélecteur d'heure.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string \| null` | `undefined` | Heure au format HH:mm (v-model) |
+| `label` | `string` | `''` | Label |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `readonly` | `boolean` | `false` | Lecture seule |
+| `error` | `string` | `''` | Message d'erreur |
+
+**Events :** `update:modelValue(value: string)`
+
+```vue
+
+
+```
+
+---
+
+## MalioButton
+
+Bouton d'action avec 4 variantes visuelles et icône optionnelle.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `label` | `string` | `''` | Texte du bouton (ou slot par défaut) |
+| `variant` | `'primary' \| 'secondary' \| 'tertiary' \| 'danger'` | `'primary'` | Variante visuelle |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `buttonClass` | `string` | `''` | Classes CSS additionnelles (twMerge) |
+| `iconName` | `string` | `''` | Icône Iconify |
+| `iconPosition` | `'left' \| 'right'` | `'right'` | Position icône |
+| `iconSize` | `string \| number` | `16` | Taille icône |
+
+**Events :** `click(e: MouseEvent)`
+**Slots :** `default` (contenu du bouton, remplace `label`)
+
+```vue
+
+
+
+
+
+```
+
+---
+
+## MalioButtonIcon
+
+Bouton icône seul (sans texte).
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `icon` | `string` | **requis** | Icône Iconify |
+| `ariaLabel` | `string` | **requis** | Label accessible |
+| `variant` | `'filled' \| 'ghost'` | `'filled'` | Variante visuelle |
+| `disabled` | `boolean` | `false` | Désactivé |
+| `buttonClass` | `string` | `''` | Classes CSS additionnelles |
+| `iconSize` | `string \| number` | `24` | Taille icône |
+
+**Events :** `click(e: MouseEvent)`
+
+```vue
+
+
+```
+
+---
+
+## MalioTabList
+
+Navigation par onglets avec contenu dynamique.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `string` | `undefined` | Onglet actif (v-model) |
+| `tabs` | `{ key: string, label: string, icon?: string }[]` | **requis** | Liste des onglets |
+
+**Events :** `update:modelValue(value: string)`
+**Slots :** Un slot nommé par `tab.key` pour le contenu de chaque onglet
+
+```vue
+
+ Contenu infos
+ Contenu docs
+
+```
+
+---
+
+## MalioSidebar
+
+Barre latérale de navigation rétractable.
+
+| Prop | Type | Défaut | Description |
+|------|------|--------|-------------|
+| `modelValue` | `boolean` | `undefined` | État ouvert/fermé (v-model) |
+| `sections` | `SidebarSection[]` | **requis** | Sections de navigation |
+| `sidebarClass` | `string` | `''` | Classes CSS sidebar |
+| `toggleClass` | `string` | `''` | Classes CSS bouton toggle |
+
+**Type SidebarSection :** `{ title?: string, items: { label: string, icon?: string, to?: string, href?: string, active?: boolean }[] }`
+
+**Events :** `update:modelValue(value: boolean)`
+**Slots :** `logo` (sidebar ouverte), `logo-collapsed` (sidebar fermée)
+
+```vue
+
+
+
+
+```