diff --git a/docs/frontend/COMPONENT_BEST_PRACTICES.md b/docs/frontend/COMPONENT_BEST_PRACTICES.md new file mode 100644 index 0000000..3b600a7 --- /dev/null +++ b/docs/frontend/COMPONENT_BEST_PRACTICES.md @@ -0,0 +1,614 @@ +# 🎨 Guide des Bonnes Pratiques - Composants Frontend + +> **Guide**: Design System Notytex +> **Audience**: Développeurs Frontend & UI/UX Designers +> **Version**: 1.0 +> **Mise à jour**: 7 août 2025 + +## 🎯 **Philosophie du Design System** + +Notytex adopte une approche **moderne, cohérente et accessible** pour ses composants frontend. Chaque composant doit être **réutilisable**, **maintenable** et **évolutif**. + +### 🏗️ **Principes Fondamentaux** +- **🔄 Réutilisabilité** : Un composant = plusieurs contextes +- **🎨 Cohérence** : Design tokens centralisés +- **📱 Responsive-first** : Mobile d'abord +- **♿ Accessibilité** : WCAG 2.1 AA minimum +- **⚡ Performance** : Optimisation native + +--- + +## 📁 **Architecture des Composants** + +### **Structure de Répertoires** +``` +templates/components/ +├── common/ +│ ├── macros.html # Macros réutilisables +│ └── base_components.html # Composants de base +├── assessment/ +│ └── assessment_card.html # Cartes d'évaluation +├── class/ +│ └── class_card.html # Cartes de classe +├── forms/ +│ ├── form_inputs.html # Champs de formulaire +│ └── form_validation.html # Validation UI +└── ui/ + ├── buttons.html # Système de boutons + ├── modals.html # Modales + └── notifications.html # Toasts/Alerts +``` + +### **Convention de Nommage** +``` +Type_Domain_Component.html +│ │ │ +│ │ └─ Nom spécifique (card, button, modal...) +│ └──────── Domaine métier (assessment, class, user...) +└───────────── Type (component, macro, layout...) +``` + +**📝 Exemples:** +- `assessment_card.html` ✅ +- `class_list_item.html` ✅ +- `user_profile_widget.html` ✅ +- `genericCard.html` ❌ (PascalCase) +- `card.html` ❌ (trop générique) + +--- + +## 🎨 **Design Tokens & Cohérence** + +### **Palette de Couleurs Système** +```scss +// Couleurs Primaires +$blue: from-blue-500 to-blue-600 // Actions principales +$green: from-green-500 to-green-600 // Succès, validation +$purple: from-purple-500 to-purple-600 // Évaluations, analytique +$orange: from-orange-500 to-orange-600 // Avertissement, en cours +$red: from-red-500 to-red-600 // Erreur, critique +$pink: from-pink-500 to-pink-600 // Spécial, mise en avant + +// Couleurs Neutres +$gray-50: #f9fafb // Fond très clair +$gray-100: #f3f4f6 // Fond clair +$gray-600: #4b5563 // Texte secondaire +$gray-900: #111827 // Texte principal +``` + +### **Typography Scale** +```scss +// Hiérarchie Textuelle +.text-4xl { font-size: 2.25rem } // Titres Hero +.text-3xl { font-size: 1.875rem } // Titres principaux +.text-2xl { font-size: 1.5rem } // Titres sections +.text-xl { font-size: 1.25rem } // Sous-titres +.text-lg { font-size: 1.125rem } // Texte large +.text-base { font-size: 1rem } // Texte standard +.text-sm { font-size: 0.875rem } // Texte petit +.text-xs { font-size: 0.75rem } // Métadonnées +``` + +### **Spacing System** +```scss +// Système d'espacement (Tailwind) +space-1: 0.25rem // 4px +space-2: 0.5rem // 8px +space-3: 0.75rem // 12px +space-4: 1rem // 16px +space-6: 1.5rem // 24px +space-8: 2rem // 32px +space-12: 3rem // 48px +``` + +--- + +## 🧩 **Anatomie d'un Composant** + +### **Template Structure** +```jinja2 +{# 1. Commentaire de description #} +{# Composant pour [FONCTION] dans [CONTEXTE] #} + +{# 2. Import des dépendances #} +{% from 'components/common/macros.html' import helper_macro %} + +{# 3. Définition du macro principal #} +{% macro component_name(required_param, optional_param=default) %} + +{# 4. Logique de configuration #} +{% set config = { + 'variant': optional_param, + 'classes': 'base-classes ' + (additional_classes if condition else '') +} %} + +{# 5. Structure HTML avec données dynamiques #} +
+ + {% if caller %} + {{ caller() }} + {% else %} + + {% endif %} +
+ +{# 6. Fin du macro #} +{% endmacro %} +``` + +### **Exemple Concret : Button Component** +```jinja2 +{# Composant bouton avec variants et états #} + +{% macro button( + text, + url=None, + type="primary", + size="md", + icon=None, + disabled=False, + classes="" +) %} + +{# Configuration des variants #} +{% set variants = { + 'primary': 'bg-gradient-to-r from-blue-500 to-blue-600 text-white', + 'secondary': 'bg-gray-50 text-gray-700 border border-gray-300', + 'danger': 'bg-gradient-to-r from-red-500 to-red-600 text-white' +} %} + +{% set sizes = { + 'sm': 'px-3 py-2 text-sm', + 'md': 'px-4 py-2 text-base', + 'lg': 'px-6 py-3 text-lg' +} %} + +{# Classes finales #} +{% set button_classes = [ + 'inline-flex items-center justify-center', + 'rounded-xl font-semibold transition-all duration-300', + 'hover:shadow-lg transform hover:scale-105', + variants[type], + sizes[size], + 'opacity-50 cursor-not-allowed' if disabled else '', + classes +]|join(' ') %} + +{# Rendu conditionnel (lien vs bouton) #} +{% if url and not disabled %} + +{% else %} + {% endif %} + +{% endmacro %} +``` + +--- + +## 🎛️ **API des Composants** + +### **Paramètres Standards** +Chaque composant doit exposer une API cohérente : + +```jinja2 +{% macro component_name( + # === OBLIGATOIRES === + data, # Données principales + title, # Titre/Label + + # === OPTIONNELS === + variant="default", # Type/Style (primary, secondary, danger...) + size="md", # Taille (sm, md, lg, xl) + classes="", # Classes CSS additionnelles + + # === COMPORTEMENT === + clickable=True, # Interactif ou non + disabled=False, # État désactivé + loading=False, # État de chargement + + # === CONTENU === + icon=None, # Icône SVG + badge=None, # Badge/Compteur + actions=[], # Liste d'actions + + # === TECHNIQUE === + id=None, # ID HTML personnalisé + attrs={} # Attributs HTML additionnels +) %} +``` + +### **Exemple d'Utilisation** +```jinja2 +{# Usage simple #} +{{ button("Sauvegarder") }} + +{# Usage avancé #} +{{ button( + text="Créer évaluation", + url=url_for('assessments.new'), + type="primary", + size="lg", + icon='...', + classes="w-full md:w-auto" +) }} +``` + +--- + +## 🔄 **États et Variants** + +### **États Standardisés** +Tous les composants interactifs doivent gérer ces états : + +```scss +// États de base +.default // État normal +.hover // Survol +.active // Actif/Pressé +.focus // Focus clavier +.disabled // Désactivé + +// États applicatifs +.loading // Chargement en cours +.success // Succès/Validation +.error // Erreur +.warning // Avertissement +``` + +### **Variants de Style** +```scss +// Variants visuels +.primary // Action principale (bleu) +.secondary // Action secondaire (gris) +.success // Succès (vert) +.warning // Attention (orange) +.danger // Danger (rouge) +.ghost // Transparent +.outline // Contour seulement +``` + +### **Exemple : Card States** +```jinja2 +{# États d'une carte #} +{% set card_states = { + 'default': 'bg-white shadow-lg hover:shadow-xl', + 'active': 'bg-blue-50 border-2 border-blue-200 shadow-xl', + 'disabled': 'bg-gray-50 opacity-50 cursor-not-allowed', + 'loading': 'bg-gray-50 animate-pulse' +} %} + +
+ {% if state == 'loading' %} +
+
+
+
+
+
+ {% else %} + + {% endif %} +
+``` + +--- + +## 📱 **Responsive Design** + +### **Breakpoints Standard** +```scss +// Mobile First approach +sm: 640px // Téléphone large / Tablette portrait +md: 768px // Tablette +lg: 1024px // Desktop +xl: 1280px // Large desktop +2xl: 1536px // Ultra wide +``` + +### **Grilles Responsives** +```jinja2 +{# Grille adaptative standard #} +
+ {% for item in items %} + {{ item_card(item) }} + {% endfor %} +
+ +{# Navigation responsive #} + +``` + +### **Typography Responsive** +```scss +// Échelle typographique adaptative +.hero-title { + @apply text-2xl md:text-4xl lg:text-5xl; +} + +.section-title { + @apply text-lg md:text-xl lg:text-2xl; +} + +.body-text { + @apply text-sm md:text-base; +} +``` + +--- + +## ♿ **Accessibilité** + +### **Checklist Obligatoire** +- [ ] **Contraste** ≥ 4.5:1 pour texte normal +- [ ] **Contraste** ≥ 3:1 pour texte large +- [ ] **Navigation clavier** complète +- [ ] **ARIA labels** sur éléments interactifs +- [ ] **Focus indicators** visibles +- [ ] **Screen reader** compatible + +### **Implémentation** +```jinja2 +{# Bouton accessible #} + + +{# Card interactive accessible #} +
+ +
+``` + +### **ARIA Patterns** +```html + +