
# Composants réutilisables

Le même motif d'interface apparaît généralement sur plusieurs pages — un badge de fonctionnalité, un en-tête de section, un bloc d'appel à l'action. Copier son arbre de composants dans chaque page oblige à répercuter chaque changement futur dans chaque copie.

`app.components` est une bibliothèque de modèles nommés. Définissez le motif une seule fois, avec des espaces réservés `$variable` là où le contenu diffère :

```yaml
components:
  - name: section-header
    type: container
    props: { className: 'text-center mb-12' }
    children:
      - { type: text, props: { level: h2 }, content: '$title' }
      - { type: text, props: { level: p }, content: '$subtitle' }
```

Instanciez-le ensuite depuis n'importe quelle page avec `$ref`, en passant les valeurs :

```yaml
pages:
  - name: Home
    path: /
    components:
      - $ref: section-header
        vars:
          title: Own your software
          subtitle: One config file. A complete app.
```

## Propriétés d'un modèle

| Propriété  | Description                                                                                |
| ---------- | ------------------------------------------------------------------------------------------ |
| `name`     | Identifiant kebab-case unique utilisé par `$ref`. Doit commencer par une lettre minuscule. |
| `type`     | Le type de composant que le modèle rend — n'importe quel type utilisable par une page.     |
| `props`    | Propriétés du composant. Les valeurs peuvent contenir des espaces réservés `$variable`.    |
| `content`  | Contenu textuel. Peut contenir des espaces réservés `$variable`.                           |
| `children` | Composants enfants imbriqués, qui peuvent eux-mêmes porter des espaces réservés.           |

## Variables

Un espace réservé est un `$` suivi d'un nom alphanumérique (`$title`, `$iconName`). À l'instanciation, `vars` fournit les valeurs :

| Règle                 | Détail                                                                                         |
| --------------------- | ---------------------------------------------------------------------------------------------- |
| Format des clés       | Commence par une lettre, uniquement alphanumérique — `$titleColor`, pas `$title-color`.        |
| Types de valeurs      | Chaîne, nombre ou booléen.                                                                     |
| Où elles se résolvent | Dans les valeurs de `props`, dans `content`, et à n'importe quelle profondeur dans `children`. |

Le même modèle avec des `vars` différentes produit des instances différentes :

```yaml
components:
  - name: icon-badge
    type: badge
    props: { color: '$color' }
    children:
      - { type: icon, props: { name: '$icon' } }
      - { type: text, content: '$label' }

pages:
  - name: Features
    path: /features
    components:
      - $ref: icon-badge
        vars: { color: orange, icon: users, label: 'Team ready' }
      - $ref: icon-badge
        vars: { color: green, icon: lock, label: 'Self-hosted' }
```

## Validation

Les noms de composants doivent être uniques dans toute la bibliothèque — un doublon rendrait un `$ref` ambigu, et il est rejeté au décodage de la configuration.

:::callout
**Modèles vs composants de page.** `app.components` contient les motifs que vous instanciez. Tout ce qui ne sert qu'une seule fois a sa place en ligne, dans la page qui l'utilise — un modèle référencé depuis un seul endroit ajoute de l'indirection sans supprimer la moindre duplication.
:::

## Pages connexes

- [Présentation des pages](/fr/docs/pages-overview) — l'arbre de composants dans lequel s'insère un modèle.
- [Composants de mise en page](/fr/docs/layout-components) — les types structurels que les modèles enveloppent le plus souvent.
- [Fichiers de configuration](/fr/docs/configuration-files) — répartir une grande bibliothèque sur plusieurs fichiers.
- [Langues](/fr/docs/languages) — les jetons de traduction `$t:`, qui se composent avec les variables de modèle.
