Composants / Slots

Système de composants réutilisables en pur JS. Chaque composant est une fonction qui reçoit des slots (contenus injectables) et retourne du HTML.

Principe

Un composant est défini dans un fichier JS via registerComponent(). Il est ensuite utilisé dans le HTML via l'attribut data-component. Les contenus sont injectés via des slots.

// 1. Définir le composant (components/mon-composant.js)
registerComponent('monComposant', function (slots) {
  return '<div class="mon-composant">'
    + '<h3>' + (slots.title || 'Titre par défaut') + '</h3>'
    + '<p>' + (slots.text || '') + '</p>'
    + '</div>';
});

// 2. Utiliser dans le HTML
// <div data-component="monComposant">
//   <template data-slot="title">Mon titre</template>
//   <template data-slot="text">Du contenu <strong>HTML</strong></template>
// </div>

Injection de slots

Deux méthodes pour passer du contenu à un composant :

Méthode 1 : <template data-slot>

Pour du contenu riche (HTML, liens, boutons, images). Le contenu HTML du <template> est injecté tel quel.

<div data-component="card">
  <template data-slot="title">Mon titre</template>
  <template data-slot="text">Du <strong>HTML</strong> riche</template>
  <template data-slot="footer">
    <a href="#" class="btn btn--primary">Action</a>
  </template>
</div>

Méthode 2 : attributs data-*

Pour des valeurs simples (texte, URLs). Les tirets sont convertis en camelCase. Tous les attributs data-* (sauf data-component) sont disponibles dans slots.

<!-- data-site-name → slots.siteName -->
<!-- data-logo-src  → slots.logoSrc  -->
<div data-component="header"
     data-site-name="MonSite"
     data-logo-src="logo.png"
     data-logo-link="/index.html">
</div>
Attribut HTMLClé dans slots
data-site-nameslots.siteName
data-logo-srcslots.logoSrc
data-image-altslots.imageAlt
data-copyrightslots.copyright

L'ancienne syntaxe data-slot-* reste compatible.

API JavaScript

FonctionDescription
registerComponent(name, fn)Enregistre un composant. fn(slots) reçoit un objet et retourne du HTML.
renderComponents(root)Rend les [data-component] dans root (défaut : document.body). Appelé auto au DOMContentLoaded.

Vous pouvez appeler renderComponents(el) manuellement après avoir injecté du HTML dynamique contenant des data-component.

Composants inclus

Header

Fichier : components/header.js

Le header est configuré entièrement par attributs et slots :

SlotMéthodeDescription
siteNameAttributNom du site (texte logo si pas d'image). Défaut : Logo
logoSrcAttributURL de l'image logo (vide = texte siteName)
logoLinkAttributLien du logo. Défaut : /
navTemplateLiens de navigation (HTML)
ctaTemplateBouton d'action (optionnel)
searchTemplateActive le bouton de recherche (déclarer vide)
<!-- Header minimal -->
<div data-component="header"
     data-site-name="MonSite"
     data-logo-link="/index.html">
  <template data-slot="nav">
    <a href="/index.html">Accueil</a>
    <a href="/contact.html">Contact</a>
  </template>
</div>

<!-- Header complet (logo image + CTA + recherche) -->
<div data-component="header"
     data-site-name="MonSite"
     data-logo-src="/assets/logo.svg"
     data-logo-link="/index.html">
  <template data-slot="nav">
    <a href="/index.html">Accueil</a>
    <a href="/docs/index.html">Documentation</a>
  </template>
  <template data-slot="cta">
    <button class="btn btn--primary">Contact</button>
  </template>
  <template data-slot="search"></template>
</div>

Footer

Fichier : components/footer.js

Le footer est configuré par attributs et slots :

SlotMéthodeDescription
copyrightAttributTexte copyright. Défaut : &copy; YYYY
contentTemplateContenu du footer (liens, nav, etc.)
<div data-component="footer"
     data-copyright="&copy; 2026 MonSite">
  <template data-slot="content">
    <nav class="footer__links">
      <a href="/mentions-legales.html">Mentions legales</a>
      <a href="/confidentialite.html">Confidentialite</a>
    </nav>
  </template>
</div>

Card

Fichier : components/card.js

SlotTypeDescription
imageURLImage de la card (optionnel)
imageAltTexteAlt de l'image
titleHTMLTitre de la card
textHTMLContenu texte
footerHTMLPied de card (boutons, liens, etc.)
<div data-component="card">
  <template data-slot="image">photo.jpg</template>
  <template data-slot="title">Titre</template>
  <template data-slot="text">Description de la card.</template>
  <template data-slot="footer">
    <a href="#" class="btn btn--primary">En savoir plus</a>
  </template>
</div>

Créer un composant custom

Créez un fichier dans components/, enregistrez-le, puis incluez le script dans vos pages.

// components/testimonial.js
registerComponent('testimonial', function (slots) {
  return '<blockquote class="testimonial">'
    + '<p class="testimonial__text">"' + (slots.quote || '') + '"</p>'
    + '<footer class="testimonial__author">'
    +   (slots.avatar ? '<img src="' + slots.avatar + '" alt="">' : '')
    +   '<cite>' + (slots.name || 'Anonyme') + '</cite>'
    + '</footer>'
    + '</blockquote>';
});
<!-- Dans le HTML -->
<script src="components/testimonial.js"></script>

<div data-component="testimonial">
  <template data-slot="quote">Un produit incroyable !</template>
  <template data-slot="name">Marie Dupont</template>
  <template data-slot="avatar">img/marie.jpg</template>
</div>

Bonnes pratiques

  • Toujours prévoir des valeurs par défaut : slots.title || 'Défaut'
  • Rendre les slots optionnels : slots.footer ? '...' : ''
  • Nommer les composants en camelCase : registerComponent('heroSection', ...)
  • Convention BEM pour les classes CSS du composant
  • Un composant peut contenir d'autres data-component (rendu récursif automatique)
  • Charger core/js/components.js avant les scripts de composants