[Nom du Composant]
Type de ressource : Composant Astro (UI atomique / Ălot interactif)
Fichier source :src/components/[ui|interactive]/[NomComposant].astro
Statut : [Actif / Déprécié / En développement]
1. Vue dâensemble
Section titled â1. Vue dâensembleâ1.1. Description
Section titled â1.1. Descriptionâ[Description concise du rĂŽle de ce composant dans lâinterface utilisateur]
1.2. Objectif
Section titled â1.2. Objectifâ- [Objectif principal : ex. afficher un bouton dâaction rĂ©utilisable]
- [BĂ©nĂ©fice pour lâUX ou lâarchitecture]
1.3. Caractéristiques
Section titled â1.3. CaractĂ©ristiquesâ| PropriĂ©tĂ© | Valeur |
|---|---|
| Type | [UI atomique / Ălot interactif] |
| Hydratation | [Aucune / client:load / client:visible / client:idle] |
| Framework JS | [Aucun / React / Vue / Svelte / Web Component] |
| Accessibilité | [WCAG AA conforme / Partiellement conforme / Non testé] |
| Responsive | [Mobile-first / Desktop-first] |
2. Architecture et structure
Section titled â2. Architecture et structureâ2.1. Emplacement dans lâarborescence
Section titled â2.1. Emplacement dans lâarborescenceâsrc/components/âââ ui/ # Composants atomiques (HTML + CSS purs)â âââ Button.astroâ âââ Badge.astroâ âââ [NomComposant].astroâââ interactive/ # Ălots dynamiques (React/Vue/Svelte) âââ MobileNav.tsx âââ Carousel.tsx âââ [NomComposant].tsx2.2. Composants dĂ©pendants
Section titled â2.2. Composants dĂ©pendantsâ| Composant parent | Fichier | Relation |
|---|---|---|
| [Nom du parent] | src/components/[chemin] |
[Composition / Wrapper] |
2.3. Composants enfants utilisés
Section titled â2.3. Composants enfants utilisĂ©sâ| Composant enfant | Fichier | RĂŽle |
|---|---|---|
| [Nom de lâenfant] | src/components/[chemin] |
[Description] |
3. Implémentation
Section titled â3. ImplĂ©mentationâ3.1. Variante : Composant UI atomique (HTML + CSS purs)
Section titled â3.1. Variante : Composant UI atomique (HTML + CSS purs)â---interface Props { label: string; variant?: 'primary' | 'secondary' | 'outline'; size?: 'sm' | 'md' | 'lg'; disabled?: boolean; href?: string; onClick?: () => void;}
const { label, variant = 'primary', size = 'md', disabled = false, href, onClick,} = Astro.props;
const baseClasses = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';
const variantClasses = { primary: 'bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500', secondary: 'bg-gray-600 text-white hover:bg-gray-700 focus:ring-gray-500', outline: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50 focus:ring-blue-500',};
const sizeClasses = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-base', lg: 'px-6 py-3 text-lg',};
const classes = `${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`;---
{href ? ( <a href={href} class={classes} aria-disabled={disabled} > {label} </a>) : ( <button class={classes} disabled={disabled} onClick={onClick} > {label} </button>)}3.2. Variante : Ălot interactif (React)
Section titled â3.2. Variante : Ălot interactif (React)âimport { useState } from 'react';
interface Props { items: Array<{ id: string; title: string; content: string; }>; autoPlay?: boolean; interval?: number;}
export default function Carousel({ items, autoPlay = true, interval = 5000 }: Props) { const [currentIndex, setCurrentIndex] = useState(0);
const nextSlide = () => { setCurrentIndex((prev) => (prev + 1) % items.length); };
const prevSlide = () => { setCurrentIndex((prev) => (prev - 1 + items.length) % items.length); };
// Auto-play useState(() => { if (autoPlay) { const timer = setInterval(nextSlide, interval); return () => clearInterval(timer); } }, [autoPlay, interval]);
return ( <div className="carousel" role="region" aria-label="Carrousel" aria-roledescription="carousel"> <div className="carousel-track"> {items.map((item, index) => ( <div key={item.id} className={`carousel-slide ${index === currentIndex ? 'active' : ''}`} role="group" aria-roledescription="slide" aria-label={`${index + 1} sur ${items.length}`} aria-hidden={index !== currentIndex} > <h3>{item.title}</h3> <p>{item.content}</p> </div> ))} </div>
<button onClick={prevSlide} aria-label="Diapositive prĂ©cĂ©dente" className="carousel-prev" > â </button>
<button onClick={nextSlide} aria-label="Diapositive suivante" className="carousel-next" > â </button>
<div className="carousel-indicators"> {items.map((_, index) => ( <button key={index} onClick={() => setCurrentIndex(index)} className={`indicator ${index === currentIndex ? 'active' : ''}`} aria-label={`Aller Ă la diapositive ${index + 1}`} aria-current={index === currentIndex} /> ))} </div> </div> );}3.3. Utilisation dans une page
Section titled â3.3. Utilisation dans une pageâ---import Button from '../components/ui/Button.astro';import Carousel from '../components/interactive/Carousel';
const items = [ { id: '1', title: 'Témoignage 1', content: 'Contenu...' }, { id: '2', title: 'Témoignage 2', content: 'Contenu...' },];---
<!-- Composant UI (pas d'hydratation) --><Button label="En savoir plus" variant="primary" href="/about" />
<!-- Ălot interactif (hydratation diffĂ©rĂ©e) --><Carousel client:visible items={items} autoPlay={true} interval={5000} />4. Props et interface
Section titled â4. Props et interfaceâ4.1. Props obligatoires
Section titled â4.1. Props obligatoiresâ| Prop | Type | Description | Exemple |
|---|---|---|---|
label |
string |
Texte affiché dans le bouton | "En savoir plus" |
4.2. Props optionnelles
Section titled â4.2. Props optionnellesâ| Prop | Type | Description | Valeur par dĂ©faut |
|---|---|---|---|
variant |
'primary' | 'secondary' | 'outline' |
Style visuel du bouton | 'primary' |
size |
'sm' | 'md' | 'lg' |
Taille du bouton | 'md' |
disabled |
boolean |
Ătat dĂ©sactivĂ© | false |
href |
string |
URL de redirection (rend le composant en <a>) |
undefined |
onClick |
() => void |
Callback au clic | undefined |
4.3. Slots (si applicable)
Section titled â4.3. Slots (si applicable)â| Slot | Description | Obligatoire |
|---|---|---|
default |
Contenu personnalisé (remplace label) |
â |
icon |
IcĂŽne Ă afficher avant le label | â |
5. StratĂ©gie dâhydratation
Section titled â5. StratĂ©gie dâhydratationâ5.1. Politique dâhydratation
Section titled â5.1. Politique dâhydratationâ| Type de composant | StratĂ©gie | Rationale |
|---|---|---|
| Composants UI atomiques | Aucune | HTML + CSS purs, pas dâinteraction |
| Navigation mobile | client:load |
Critique pour lâUX immĂ©diate |
| Carrousel témoignages | client:visible |
Chargement différé (plus bas dans la page) |
| Formulaire de contact | client:load |
Interaction immédiate requise |
| Graphiques / Charts | client:visible |
Chargement différé |
5.2. Directives Astro utilisées
Section titled â5.2. Directives Astro utilisĂ©esâ<!-- Aucune hydratation (HTML pur) --><Button label="Cliquez ici" />
<!-- Hydratation immédiate --><MobileNav client:load items={navItems} />
<!-- Hydratation au scroll (viewport) --><Carousel client:visible items={testimonials} />
<!-- Hydratation au repos (idle) --><Analytics client:idle />5.3. Impact sur les performances
Section titled â5.3. Impact sur les performancesâ| MĂ©trique | Sans hydratation | Avec client:load |
Avec client:visible |
|---|---|---|---|
| HTML size | +2 KB | +2 KB | +2 KB |
| JS size | 0 KB | +15 KB | +15 KB (chargé plus tard) |
| TTI (Time to Interactive) | Immédiat | +50ms | +200ms (aprÚs scroll) |
| INP | N/A | Impacté | Impacté |
6. Styles et design system
Section titled â6. Styles et design systemâ6.1. Utilisation des design tokens
Section titled â6.1. Utilisation des design tokensâ/* Le composant utilise les design tokens dĂ©finis dans tokens.css */.button { background-color: var(--color-primary, #3b82f6); color: var(--color-text-inverse, #ffffff); padding: var(--spacing-md, 1rem) var(--spacing-lg, 1.5rem); border-radius: var(--radius-md, 0.5rem); font-family: var(--font-family-base, system-ui); font-size: var(--font-size-base, 1rem); font-weight: var(--font-weight-medium, 500); transition: background-color var(--transition-fast, 150ms) ease;}
.button:hover { background-color: var(--color-primary-dark, #2563eb);}
.button:focus-visible { outline: 2px solid var(--color-focus, #3b82f6); outline-offset: 2px;}6.2. Responsive design
Section titled â6.2. Responsive designâ/* Mobile-first approach */.button { width: 100%; padding: var(--spacing-sm, 0.75rem) var(--spacing-md, 1rem); font-size: var(--font-size-sm, 0.875rem);}
/* Tablet et desktop */@media (min-width: 768px) { .button { width: auto; padding: var(--spacing-md, 1rem) var(--spacing-lg, 1.5rem); font-size: var(--font-size-base, 1rem); }}6.3. Mode sombre (si applicable)
Section titled â6.3. Mode sombre (si applicable)â/* Support automatique via prefers-color-scheme */@media (prefers-color-scheme: dark) { .button { background-color: var(--color-primary-dark, #2563eb); }}
/* Ou via classe manuelle */[data-theme="dark"] .button { background-color: var(--color-primary-dark, #2563eb);}7. Accessibilité (a11y)
Section titled â7. AccessibilitĂ© (a11y)â7.1. ConformitĂ© WCAG 2.1 AA
Section titled â7.1. ConformitĂ© WCAG 2.1 AAâ| CritĂšre | ImplĂ©mentation | Statut |
|---|---|---|
| 1.1.1 Non-text Content | Attribut alt obligatoire pour les images |
â |
| 1.3.1 Info and Relationships | Structure HTML sémantique (<button>, <a>) |
â |
| 1.4.3 Contrast (Minimum) | Contraste texte/fond â„ 4.5:1 | â |
| 1.4.11 Non-text Contrast | Contraste Ă©lĂ©ments interactifs â„ 3:1 | â |
| 2.1.1 Keyboard | Navigation clavier complĂšte (Tab, Enter, Space) | â |
| 2.1.2 No Keyboard Trap | Pas de piĂšge au clavier | â |
| 2.4.7 Focus Visible | Focus visible sur tous les Ă©lĂ©ments interactifs | â |
| 4.1.2 Name, Role, Value | Attributs ARIA appropriés (aria-label, aria-expanded) |
â |
7.2. Attributs ARIA utilisés
Section titled â7.2. Attributs ARIA utilisĂ©sâ<!-- Bouton --><button aria-label="Fermer la modale" aria-expanded="false" aria-controls="modal-content"> Ă</button>
<!-- Carrousel --><div role="region" aria-label="Carrousel de témoignages" aria-roledescription="carousel"> <div role="group" aria-roledescription="slide" aria-label="1 sur 5" aria-hidden="false" > <!-- Contenu --> </div></div>
<!-- Navigation --><nav aria-label="Navigation principale"> <ul role="menubar"> <li role="none"> <a role="menuitem" href="/">Accueil</a> </li> </ul></nav>7.3. Navigation clavier
Section titled â7.3. Navigation clavierâ| Touche | Action |
|---|---|
Tab |
Navigation vers lâĂ©lĂ©ment suivant |
Shift + Tab |
Navigation vers lâĂ©lĂ©ment prĂ©cĂ©dent |
Enter / Space |
Activation du bouton ou du lien |
Escape |
Fermeture de la modale ou du menu |
FlĂšches |
Navigation dans les menus / carrousels |
7.4. Tests dâaccessibilitĂ©
Section titled â7.4. Tests dâaccessibilitĂ©â# Test automatique avec axe-corenpx axe http://localhost:4321/
# Test avec Lighthousenpx lighthouse http://localhost:4321/ --view
# Test manuel# 1. Navigation complÚte au clavier (Tab, Shift+Tab)# 2. Vérification du focus visible# 3. Test avec un lecteur d'écran (VoiceOver, NVDA)# 4. Vérification du contraste avec WebAIM Contrast Checker8. Performance et optimisation
Section titled â8. Performance et optimisationâ8.1. Optimisations appliquĂ©es
Section titled â8.1. Optimisations appliquĂ©esâ- â HTML statique par dĂ©faut (pas de JavaScript sauf si nĂ©cessaire)
- â CSS scoped (pas de fuite de styles)
- â Images optimisĂ©es (WebP/AVIF via Cloudflare)
- â Pas de JavaScript bloquant sur le chemin critique
- â
Lazy loading des composants interactifs (
client:visible)
8.2. Core Web Vitals
Section titled â8.2. Core Web Vitalsâ| MĂ©trique | Objectif | StratĂ©gie |
|---|---|---|
| LCP | < 2.5s | Images optimisées, pas de JS bloquant |
| INP | < 200ms | JavaScript minimal, ßlots ciblés |
| CLS | < 0.1 | Dimensions explicites, pas de layout shift |
8.3. Taille du composant
Section titled â8.3. Taille du composantâ| Type | HTML | CSS | JS (hydratĂ©) | Total |
|---|---|---|---|---|
| UI atomique | 2 KB | 1 KB | 0 KB | 3 KB |
| Ălot interactif | 2 KB | 1 KB | 15 KB | 18 KB |
9. Débogage et troubleshooting
Section titled â9. DĂ©bogage et troubleshootingâ9.1. ProblĂšmes courants
Section titled â9.1. ProblĂšmes courantsâ| SymptĂŽme | Cause probable | Solution |
|---|---|---|
| Composant non visible | Import incorrect | VĂ©rifier le chemin dâimport |
| Styles cassés | Conflit CSS | Vérifier les spécificités et le scope |
| Hydratation ne fonctionne pas | Directive manquante | Ajouter client:load ou client:visible |
| Accessibilité dégradée | Structure HTML incorrecte | Valider avec axe-core |
| Performance dégradée | JavaScript inutile | Vérifier les hydratations |
| Focus invisible | CSS outline: none |
Retirer ou remplacer par focus-visible |
9.2. Tests manuels
Section titled â9.2. Tests manuelsâ# Test localnpm run dev
# Vérification de l'accessibiliténpx axe http://localhost:4321/
# Vérification des performancesnpx lighthouse http://localhost:4321/
# Test responsive# Utiliser les DevTools du navigateur (mode responsive)
# Test des interactions# Vérifier tous les états (hover, focus, active, disabled)9.3. Logs et monitoring
Section titled â9.3. Logs et monitoringâ# Logs de dĂ©veloppementnpm run dev
# Vérification des typesnpx astro check
# Analyse du bundlenpm run build -- --analyze10. Bonnes pratiques
Section titled â10. Bonnes pratiquesâ10.1. Architecture
Section titled â10.1. Architectureâ- â SĂ©parer les composants UI (atomiques) des composants interactifs (Ăźlots)
- â Utiliser les design tokens pour tous les styles (couleurs, spacing, typographie)
- â Typer les props avec TypeScript
- â Valider les props obligatoires
- â Utiliser des valeurs par dĂ©faut pour les props optionnelles
10.2. Accessibilité
Section titled â10.2. AccessibilitĂ©â- â
Toujours utiliser des éléments HTML sémantiques (
<button>,<a>,<nav>) - â Fournir des attributs ARIA appropriĂ©s
- â Assurer une navigation clavier complĂšte
- â VĂ©rifier le contraste (WCAG AA minimum)
- â Tester avec un lecteur dâĂ©cran
10.3. Performance
Section titled â10.3. Performanceâ- â Ăviter lâhydratation sauf si interaction requise
- â
Utiliser
client:visiblepour les composants bas de page - â Optimiser les images (WebP/AVIF, dimensions explicites)
- â Ăviter le JavaScript bloquant sur le chemin critique
- â Mesurer les Core Web Vitals rĂ©guliĂšrement
10.4. Maintenance
Section titled â10.4. Maintenanceâ- â Documenter les props et slots dans ce fichier
- â CrĂ©er des exemples dâutilisation
- â Tester lâaccessibilitĂ© rĂ©guliĂšrement
- â VĂ©rifier les performances avec Lighthouse
- â Mettre Ă jour les composants lors des changements de design
11. Ăvolutions et roadmap
Section titled â11. Ăvolutions et roadmapâ11.1. AmĂ©liorations planifiĂ©es
Section titled â11.1. AmĂ©liorations planifiĂ©esâ- [Ăvolution 1 : ex. Support du mode sombre]
- [Ăvolution 2 : ex. Ajout de variantes de taille]
- [Ăvolution 3 : ex. IntĂ©gration dâanimations]
11.2. Limitations connues
Section titled â11.2. Limitations connuesâ- â Les composants UI ne peuvent pas avoir dâĂ©tat (pas de JavaScript)
- â Les Ăźlots interactifs augmentent la taille du bundle JS
- â Lâhydratation
client:visiblenĂ©cessite lâIntersection Observer API
12. Ressources liées
Section titled â12. Ressources liĂ©esâ- Documentation Astro : Components
- Documentation Astro : Islands Architecture
- Documentation Astro : Client Directives
- DAT L2 : §4 - StratĂ©gie dâHydratation & Gestion du JavaScript
- DAT L2 : §11 - Accessibilité
- DAT L2 : §12 - Design System
- Composants associés :
src/components/ui/[ComposantParent].astrosrc/components/interactive/[ComposantEnfant].tsx
- Design tokens :
src/styles/tokens.css
13. Historique des modifications
Section titled â13. Historique des modificationsâ| Date | Version | Description | Auteur |
|---|---|---|---|
| YYYY-MM-DD | 1.0 | Création initiale | [Nom] |
| YYYY-MM-DD | 1.1 | [Modification] | [Nom] |
---
**Points clés de ce template :**- Couvre les deux types de composants (UI atomique et ßlot interactif)- Détaille la stratégie d'hydratation (critique pour les performances)- Inclut la conformité WCAG 2.1 AA (accessibilité)- Fournit l'intégration avec le design system (tokens CSS)- Sépare clairement les props, les slots, et les exemples d'utilisation- Inclut les bonnes pratiques de performance et de maintenance- Documente l'impact sur les Core Web Vitals