559 lines
14 KiB
Markdown
559 lines
14 KiB
Markdown
# 🎨 Feature: Icon Packs - Système de personnalisation des icônes
|
||
|
||
## 📋 Vue d'ensemble
|
||
|
||
Le système Icon Packs permet aux utilisateurs de choisir entre différents styles d'icônes pour les boutons d'action de l'application (Ajouter, Supprimer, Éditer, Enregistrer, Upload, etc.).
|
||
|
||
### Problème résolu
|
||
|
||
Auparavant, l'application utilisait uniquement des emojis Unicode (🗑️, 💾, ✏️) pour les icônes. Ce système apporte :
|
||
- **Flexibilité** : Choix entre emojis, FontAwesome (solid/regular), et Icons8
|
||
- **Cohérence visuelle** : Icônes uniformes selon le pack choisi
|
||
- **Accessibilité** : Alternative aux emojis pour les utilisateurs qui préfèrent des icônes SVG
|
||
- **Personnalisation** : Adaptation au goût et aux préférences de chaque utilisateur
|
||
|
||
---
|
||
|
||
## 🎯 Fonctionnalités
|
||
|
||
### Packs d'icônes disponibles
|
||
|
||
1. **Emojis Unicode** (par défaut)
|
||
- Emojis colorés natifs
|
||
- Pas de dépendance externe
|
||
- Compatibilité universelle
|
||
- Exemples : ➕ ✏️ 🗑️ 💾 📤
|
||
|
||
2. **FontAwesome Solid**
|
||
- Icônes FontAwesome pleines (bold)
|
||
- Style moderne et professionnel
|
||
- Icônes SVG monochromes
|
||
- S'adaptent à la couleur du bouton
|
||
|
||
3. **FontAwesome Regular**
|
||
- Icônes FontAwesome fines (outline)
|
||
- Style minimaliste et élégant
|
||
- Variante légère de FontAwesome Solid
|
||
- Parfait pour un design épuré
|
||
|
||
4. **Icons8 PNG**
|
||
- Mix des icônes Icons8 existantes (PNG)
|
||
- Combine emojis et icônes PNG
|
||
- Utilise les icônes déjà présentes dans le projet
|
||
- Style coloré et moderne
|
||
|
||
### Icônes supportées
|
||
|
||
Le système gère les icônes suivantes :
|
||
- `add` - Ajouter
|
||
- `edit` - Éditer
|
||
- `delete` - Supprimer
|
||
- `save` - Enregistrer
|
||
- `upload` - Upload/Téléverser
|
||
- `download` - Télécharger
|
||
- `image` - Image
|
||
- `file` - Fichier
|
||
- `pdf` - PDF
|
||
- `link` - Lien/URL
|
||
- `refresh` - Rafraîchir
|
||
- `search` - Rechercher
|
||
- `settings` - Paramètres
|
||
- `close` - Fermer
|
||
- `check` - Valider
|
||
- `warning` - Avertissement
|
||
- `info` - Information
|
||
- `copy` - Copier
|
||
|
||
---
|
||
|
||
## 🏗️ Architecture
|
||
|
||
### Fichiers créés
|
||
|
||
```
|
||
frontend/
|
||
├── js/
|
||
│ └── icon-manager.js # Gestionnaire de packs d'icônes
|
||
├── css/
|
||
│ └── components.css # CSS pour .btn-icon (mis à jour)
|
||
└── icons/
|
||
└── svg/
|
||
└── fa/
|
||
├── solid/ # FontAwesome Solid SVG
|
||
└── regular/ # FontAwesome Regular SVG
|
||
```
|
||
|
||
### Structure du gestionnaire d'icônes
|
||
|
||
**`icon-manager.js`** - Module auto-initialisé (IIFE)
|
||
|
||
```javascript
|
||
const IconManager = {
|
||
packs: ICON_PACKS, // Configuration des packs
|
||
getCurrentPack(), // Récupère le pack actif
|
||
applyPack(packName), // Applique un nouveau pack
|
||
getIcon(iconName, fallback), // Récupère une icône
|
||
getAllPacks(), // Liste tous les packs
|
||
getPackInfo(packName), // Infos sur un pack
|
||
createButton(...), // Helper pour créer un bouton
|
||
updateAllButtons() // Met à jour les boutons existants
|
||
};
|
||
```
|
||
|
||
### Stockage
|
||
|
||
Le pack d'icônes choisi est stocké dans `localStorage` :
|
||
```javascript
|
||
localStorage.getItem('benchtools_icon_pack') // 'emoji', 'fontawesome-solid', etc.
|
||
```
|
||
|
||
---
|
||
|
||
## 💻 Utilisation
|
||
|
||
### Via l'interface Settings
|
||
|
||
1. Ouvrir **Settings** : [http://localhost:8087/settings.html](http://localhost:8087/settings.html)
|
||
2. Section **"Pack d'icônes"**
|
||
3. Sélectionner un pack dans la liste déroulante
|
||
4. Prévisualiser les icônes en temps réel
|
||
5. Cliquer sur **"Appliquer le pack d'icônes"**
|
||
6. La page se recharge et applique les nouvelles icônes
|
||
|
||
### Via JavaScript
|
||
|
||
#### Récupérer une icône
|
||
|
||
```javascript
|
||
// Récupérer l'icône "delete" selon le pack actif
|
||
const deleteIcon = window.IconManager.getIcon('delete');
|
||
|
||
// Avec fallback personnalisé
|
||
const saveIcon = window.IconManager.getIcon('save', '💾');
|
||
|
||
// Ou via la fonction helper dans utils.js
|
||
const addIcon = getIcon('add', '+');
|
||
```
|
||
|
||
#### Créer un bouton avec icône
|
||
|
||
```javascript
|
||
// Via IconManager
|
||
const btnHtml = window.IconManager.createButton('delete', 'Supprimer', 'btn btn-danger');
|
||
|
||
// Via helper function (utils.js)
|
||
const btnHtml = createIconButton('add', 'Ajouter', 'btn btn-primary', 'addItem()');
|
||
// Résultat: <button class="btn btn-primary" onclick="addItem()" data-icon="add">
|
||
// <span class="btn-icon-wrapper">[icône]</span> Ajouter
|
||
// </button>
|
||
```
|
||
|
||
#### Appliquer un pack programmatiquement
|
||
|
||
```javascript
|
||
// Changer le pack d'icônes
|
||
window.IconManager.applyPack('fontawesome-solid');
|
||
|
||
// Écouter les changements de pack
|
||
window.addEventListener('iconPackChanged', (event) => {
|
||
console.log('Nouveau pack:', event.detail.pack);
|
||
console.log('Nom:', event.detail.packName);
|
||
});
|
||
```
|
||
|
||
### Exemple dans le HTML
|
||
|
||
#### Avant (emojis en dur)
|
||
|
||
```html
|
||
<button class="btn btn-danger" onclick="deleteItem()">
|
||
🗑️ Supprimer
|
||
</button>
|
||
```
|
||
|
||
#### Après (système dynamique)
|
||
|
||
```html
|
||
<button class="btn btn-danger" onclick="deleteItem()" data-icon="delete">
|
||
<span class="btn-icon-wrapper"></span> Supprimer
|
||
</button>
|
||
|
||
<script>
|
||
// L'icône est injectée automatiquement au chargement
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const icon = window.IconManager.getIcon('delete');
|
||
document.querySelector('[data-icon="delete"] .btn-icon-wrapper').innerHTML = icon;
|
||
});
|
||
</script>
|
||
```
|
||
|
||
#### Meilleure approche (génération JavaScript)
|
||
|
||
```javascript
|
||
// Dans votre code de rendu
|
||
function renderDeleteButton() {
|
||
return createIconButton('delete', 'Supprimer', 'btn btn-danger', 'deleteItem()');
|
||
}
|
||
|
||
// Ou directement
|
||
container.innerHTML += createIconButton('add', 'Ajouter', 'btn btn-primary', 'addItem()');
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 Styling CSS
|
||
|
||
### Classes CSS pour les icônes
|
||
|
||
```css
|
||
/* Icône SVG dans un bouton */
|
||
.btn-icon {
|
||
width: var(--button-icon-size, 24px);
|
||
height: var(--button-icon-size, 24px);
|
||
vertical-align: middle;
|
||
filter: brightness(0) invert(1); /* Blanc par défaut */
|
||
}
|
||
|
||
/* Wrapper pour mise à jour dynamique */
|
||
.btn-icon-wrapper {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Adaptation selon le type de bouton */
|
||
.btn-primary .btn-icon { filter: brightness(0) invert(1); }
|
||
.btn-secondary .btn-icon { filter: brightness(0.8); }
|
||
.btn-danger .btn-icon { filter: brightness(0) invert(1); }
|
||
```
|
||
|
||
### Variables CSS
|
||
|
||
Les tailles d'icônes sont contrôlables via variables CSS :
|
||
|
||
```css
|
||
:root {
|
||
--section-icon-size: 32px; /* Icônes dans les titres */
|
||
--button-icon-size: 24px; /* Icônes dans les boutons */
|
||
}
|
||
```
|
||
|
||
Ces variables sont modifiables dans **Settings > Préférences d'affichage**.
|
||
|
||
---
|
||
|
||
## 📦 Configuration des packs
|
||
|
||
### Ajouter un nouveau pack
|
||
|
||
#### 1. Éditer `icon-manager.js`
|
||
|
||
```javascript
|
||
const ICON_PACKS = {
|
||
// ... packs existants
|
||
'mon-pack': {
|
||
name: 'Mon Pack Personnalisé',
|
||
description: 'Description de mon pack',
|
||
icons: {
|
||
'add': '➕', // ou <img src="...">
|
||
'edit': '✏️',
|
||
'delete': '🗑️',
|
||
'save': '💾',
|
||
// ... autres icônes
|
||
}
|
||
}
|
||
};
|
||
```
|
||
|
||
#### 2. Ajouter l'option dans `settings.html`
|
||
|
||
```html
|
||
<select id="iconPack" class="form-control">
|
||
<!-- ... options existantes -->
|
||
<option value="mon-pack">Mon Pack Personnalisé</option>
|
||
</select>
|
||
```
|
||
|
||
#### 3. (Optionnel) Ajouter des assets
|
||
|
||
Si vous utilisez des SVG/PNG personnalisés :
|
||
- Placer les fichiers dans `frontend/icons/custom/`
|
||
- Référencer avec le bon chemin dans la config
|
||
|
||
---
|
||
|
||
## 🔧 API du gestionnaire d'icônes
|
||
|
||
### `IconManager.getCurrentPack()`
|
||
|
||
Retourne le nom du pack actuellement actif.
|
||
|
||
```javascript
|
||
const currentPack = window.IconManager.getCurrentPack();
|
||
// Retourne: 'emoji' | 'fontawesome-solid' | 'fontawesome-regular' | 'icons8'
|
||
```
|
||
|
||
### `IconManager.applyPack(packName)`
|
||
|
||
Change le pack d'icônes et sauvegarde dans localStorage.
|
||
|
||
```javascript
|
||
window.IconManager.applyPack('fontawesome-solid');
|
||
// Retourne: true (succès) ou false (pack inconnu)
|
||
```
|
||
|
||
### `IconManager.getIcon(iconName, fallback)`
|
||
|
||
Récupère le HTML d'une icône selon le pack actif.
|
||
|
||
```javascript
|
||
const icon = window.IconManager.getIcon('delete', '🗑️');
|
||
// Retourne: '<img src="icons/svg/fa/solid/trash-can.svg" class="btn-icon" alt="Delete">'
|
||
// ou '🗑️' selon le pack
|
||
```
|
||
|
||
### `IconManager.getAllPacks()`
|
||
|
||
Liste tous les packs disponibles.
|
||
|
||
```javascript
|
||
const packs = window.IconManager.getAllPacks();
|
||
// Retourne: ['emoji', 'fontawesome-solid', 'fontawesome-regular', 'icons8']
|
||
```
|
||
|
||
### `IconManager.getPackInfo(packName)`
|
||
|
||
Récupère les informations d'un pack.
|
||
|
||
```javascript
|
||
const packInfo = window.IconManager.getPackInfo('fontawesome-solid');
|
||
// Retourne: { name: 'FontAwesome Solid', description: '...', icons: {...} }
|
||
```
|
||
|
||
### `IconManager.updateAllButtons()`
|
||
|
||
Met à jour dynamiquement toutes les icônes de la page.
|
||
|
||
```javascript
|
||
window.IconManager.updateAllButtons();
|
||
// Parcourt tous les [data-icon] et met à jour leur contenu
|
||
```
|
||
|
||
---
|
||
|
||
## 🧪 Tests
|
||
|
||
### Tester un pack d'icônes
|
||
|
||
1. Ouvrir la page **Settings**
|
||
2. Changer de pack dans la section "Pack d'icônes"
|
||
3. Observer l'aperçu en temps réel
|
||
4. Cliquer sur "Appliquer"
|
||
5. Vérifier que toutes les pages utilisent le nouveau pack
|
||
|
||
### Console de développement
|
||
|
||
```javascript
|
||
// Lister tous les packs
|
||
console.log(window.IconManager.getAllPacks());
|
||
|
||
// Tester chaque icône d'un pack
|
||
const pack = window.IconManager.getPackInfo('fontawesome-solid');
|
||
Object.keys(pack.icons).forEach(iconName => {
|
||
console.log(iconName, pack.icons[iconName]);
|
||
});
|
||
|
||
// Forcer un pack sans recharger
|
||
window.IconManager.applyPack('fontawesome-regular');
|
||
window.IconManager.updateAllButtons();
|
||
```
|
||
|
||
---
|
||
|
||
## 🐛 Dépannage
|
||
|
||
### Les icônes ne changent pas
|
||
|
||
**Solution** :
|
||
1. Vérifier que `icon-manager.js` est chargé dans la page
|
||
2. Ouvrir la console (F12) et vérifier les erreurs
|
||
3. Vérifier que les boutons ont l'attribut `data-icon`
|
||
4. Essayer de recharger la page avec Ctrl+F5
|
||
|
||
### Les icônes SVG n'apparaissent pas
|
||
|
||
**Solution** :
|
||
1. Vérifier que les fichiers SVG existent dans `frontend/icons/svg/fa/`
|
||
2. Vérifier les permissions des fichiers
|
||
3. Ouvrir la console réseau (F12 > Network) et chercher les erreurs 404
|
||
4. Vérifier le chemin dans `icon-manager.js`
|
||
|
||
### Les icônes sont trop grandes/petites
|
||
|
||
**Solution** :
|
||
1. Aller dans **Settings > Préférences d'affichage**
|
||
2. Ajuster "Taille des icônes de bouton"
|
||
3. Ou modifier manuellement la variable CSS :
|
||
```javascript
|
||
document.documentElement.style.setProperty('--button-icon-size', '20px');
|
||
```
|
||
|
||
### Le pack ne se sauvegarde pas
|
||
|
||
**Solution** :
|
||
1. Vérifier que localStorage est activé :
|
||
```javascript
|
||
console.log(localStorage.getItem('benchtools_icon_pack'));
|
||
```
|
||
2. Vider le cache du navigateur (Ctrl+Shift+Del)
|
||
3. Tester en navigation privée pour isoler le problème
|
||
|
||
---
|
||
|
||
## 📊 Comparaison des packs
|
||
|
||
| Pack | Type | Taille | Couleur | Avantages | Inconvénients |
|
||
|------|------|--------|---------|-----------|---------------|
|
||
| **Emojis Unicode** | Natif | Variable | Oui | Universel, pas de dépendance | Rendu variable selon OS |
|
||
| **FontAwesome Solid** | SVG | 24px | Mono | Professionnel, cohérent | Nécessite assets SVG |
|
||
| **FontAwesome Regular** | SVG | 24px | Mono | Élégant, minimaliste | Moins visible que Solid |
|
||
| **Icons8 PNG** | PNG | 48px | Oui | Coloré, moderne | Mix de styles |
|
||
|
||
---
|
||
|
||
## 🔮 Évolutions futures
|
||
|
||
### Fonctionnalités prévues
|
||
|
||
- [ ] **Import de packs personnalisés** : Permettre l'upload d'un fichier JSON définissant un pack
|
||
- [ ] **Éditeur visuel de pack** : Interface pour créer son propre pack
|
||
- [ ] **Thèmes d'icônes** : Packs adaptés automatiquement au thème actif
|
||
- [ ] **Icônes animées** : Support des GIF ou animations CSS
|
||
- [ ] **Marketplace de packs** : Partager et télécharger des packs créés par la communauté
|
||
|
||
### Améliorations techniques
|
||
|
||
- [ ] Lazy loading des icônes SVG
|
||
- [ ] Sprite SVG pour réduire les requêtes HTTP
|
||
- [ ] Support des web fonts (Font Awesome CDN)
|
||
- [ ] Cache des icônes dans IndexedDB
|
||
- [ ] Mode hors-ligne avec Service Worker
|
||
|
||
---
|
||
|
||
## 📚 Ressources
|
||
|
||
### Documentation connexe
|
||
|
||
- [FEATURE_THEME_SYSTEM.md](FEATURE_THEME_SYSTEM.md) - Système de thèmes
|
||
- [GUIDE_THEMES.md](GUIDE_THEMES.md) - Guide utilisateur des thèmes
|
||
- [frontend/css/themes/README.md](../frontend/css/themes/README.md) - Guide de création de thèmes
|
||
|
||
### Ressources externes
|
||
|
||
- [FontAwesome Icons](https://fontawesome.com/icons) - Catalogue complet FontAwesome
|
||
- [Icons8](https://icons8.com/) - Bibliothèque Icons8
|
||
- [Emojipedia](https://emojipedia.org/) - Référence Unicode emojis
|
||
|
||
---
|
||
|
||
## 📝 Exemple complet d'intégration
|
||
|
||
### Avant (ancien code)
|
||
|
||
```html
|
||
<button class="btn btn-primary" onclick="addItem()">➕ Ajouter</button>
|
||
<button class="btn btn-danger" onclick="deleteItem()">🗑️ Supprimer</button>
|
||
```
|
||
|
||
### Après (nouveau système)
|
||
|
||
#### HTML
|
||
|
||
```html
|
||
<div id="actionButtons"></div>
|
||
```
|
||
|
||
#### JavaScript
|
||
|
||
```javascript
|
||
// Fonction de rendu
|
||
function renderActionButtons() {
|
||
const container = document.getElementById('actionButtons');
|
||
|
||
const buttons = [
|
||
createIconButton('add', 'Ajouter', 'btn btn-primary', 'addItem()'),
|
||
createIconButton('delete', 'Supprimer', 'btn btn-danger', 'deleteItem()')
|
||
];
|
||
|
||
container.innerHTML = buttons.join(' ');
|
||
}
|
||
|
||
// Rendu initial
|
||
document.addEventListener('DOMContentLoaded', renderActionButtons);
|
||
|
||
// Re-rendu lors du changement de pack
|
||
window.addEventListener('iconPackChanged', renderActionButtons);
|
||
```
|
||
|
||
---
|
||
|
||
## 🎓 Bonnes pratiques
|
||
|
||
### 1. Toujours utiliser data-icon
|
||
|
||
```html
|
||
<!-- ✅ BON -->
|
||
<button class="btn" data-icon="delete" onclick="del()">
|
||
<span class="btn-icon-wrapper"></span> Supprimer
|
||
</button>
|
||
|
||
<!-- ❌ MAUVAIS -->
|
||
<button class="btn" onclick="del()">🗑️ Supprimer</button>
|
||
```
|
||
|
||
### 2. Préférer createIconButton()
|
||
|
||
```javascript
|
||
// ✅ BON - Génération via helper
|
||
const btn = createIconButton('save', 'Enregistrer', 'btn btn-primary', 'save()');
|
||
|
||
// ❌ MAUVAIS - HTML en dur
|
||
const btn = '<button class="btn btn-primary" onclick="save()">💾 Enregistrer</button>';
|
||
```
|
||
|
||
### 3. Écouter iconPackChanged pour les mises à jour
|
||
|
||
```javascript
|
||
// ✅ BON - Re-render automatique
|
||
window.addEventListener('iconPackChanged', () => {
|
||
renderMyComponent();
|
||
});
|
||
|
||
// ❌ MAUVAIS - Icônes statiques
|
||
// Pas de mise à jour après changement de pack
|
||
```
|
||
|
||
### 4. Fournir un fallback
|
||
|
||
```javascript
|
||
// ✅ BON
|
||
const icon = getIcon('custom-icon', '❓');
|
||
|
||
// ❌ RISQUÉ
|
||
const icon = getIcon('custom-icon');
|
||
// Retourne '?' si l'icône n'existe pas
|
||
```
|
||
|
||
---
|
||
|
||
## 📄 Licence
|
||
|
||
Ce système fait partie de Linux BenchTools et est distribué sous la même licence que le projet principal.
|
||
|
||
---
|
||
|
||
**Créé le** : 2026-01-11
|
||
**Auteur** : Linux BenchTools Team
|
||
**Version** : 1.0.0
|