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 HTML | Clé dans slots |
|---|---|
data-site-name | slots.siteName |
data-logo-src | slots.logoSrc |
data-image-alt | slots.imageAlt |
data-copyright | slots.copyright |
L'ancienne syntaxe data-slot-* reste compatible.
API JavaScript
| Fonction | Description |
|---|---|
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 :
| Slot | Méthode | Description |
|---|---|---|
siteName | Attribut | Nom du site (texte logo si pas d'image). Défaut : Logo |
logoSrc | Attribut | URL de l'image logo (vide = texte siteName) |
logoLink | Attribut | Lien du logo. Défaut : / |
nav | Template | Liens de navigation (HTML) |
cta | Template | Bouton d'action (optionnel) |
search | Template | Active 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 :
| Slot | Méthode | Description |
|---|---|---|
copyright | Attribut | Texte copyright. Défaut : © YYYY |
content | Template | Contenu du footer (liens, nav, etc.) |
<div data-component="footer"
data-copyright="© 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
| Slot | Type | Description |
|---|---|---|
image | URL | Image de la card (optionnel) |
imageAlt | Texte | Alt de l'image |
title | HTML | Titre de la card |
text | HTML | Contenu texte |
footer | HTML | Pied 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.jsavant les scripts de composants