241 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Graph Settings Accordion - Implementation CDK
 | 
						|
 | 
						|
## 📋 Vue d'ensemble
 | 
						|
 | 
						|
Remplacement de l'accordéon PrimeNG par un accordéon headless basé sur `@angular/cdk/accordion` avec styling Tailwind pour le panneau Graph settings d'ObsiViewer.
 | 
						|
 | 
						|
## ✅ Fonctionnalités implémentées
 | 
						|
 | 
						|
### 1. **Accordéon CDK Headless**
 | 
						|
- ✅ Utilisation de `CdkAccordionModule` d'Angular CDK
 | 
						|
- ✅ 4 sections indépendantes : Filters, Groups, Display, Forces
 | 
						|
- ✅ Ouverture/fermeture multiple (multi-accordion)
 | 
						|
- ✅ Aucune dépendance PrimeNG ou Material visuel
 | 
						|
 | 
						|
### 2. **Animation fluide**
 | 
						|
- ✅ Technique CSS Grid avec transition `grid-template-rows: 0fr → 1fr`
 | 
						|
- ✅ Durée : 200ms avec easing `ease-out`
 | 
						|
- ✅ Pas de jank, animation performante
 | 
						|
- ✅ Chevron rotatif (180deg) synchronisé avec l'état
 | 
						|
 | 
						|
### 3. **Accessibilité (A11y)**
 | 
						|
- ✅ `aria-expanded` sur les headers
 | 
						|
- ✅ `aria-controls` et `aria-labelledby` pour les panels
 | 
						|
- ✅ Navigation clavier complète (Tab, Enter, Espace)
 | 
						|
- ✅ Focus visible avec outline personnalisé
 | 
						|
- ✅ Rôle `region` sur les panels
 | 
						|
 | 
						|
### 4. **Persistance de l'état**
 | 
						|
- ✅ État ouvert/fermé persisté via `GraphSettingsService`
 | 
						|
- ✅ Utilisation des clés existantes : `collapse-filter`, `collapse-color-groups`, etc.
 | 
						|
- ✅ Synchronisation bidirectionnelle avec `.obsidian/graph.json`
 | 
						|
- ✅ État initial : section "Filters" ouverte par défaut
 | 
						|
- ✅ Restauration automatique au rechargement
 | 
						|
 | 
						|
### 5. **Dark/Light Mode**
 | 
						|
- ✅ Support complet du mode sombre via classe `.dark`
 | 
						|
- ✅ Couleurs adaptatives pour borders, backgrounds, text
 | 
						|
- ✅ Gradients et shadows ajustés selon le thème
 | 
						|
- ✅ Cohérence avec le design system d'ObsiViewer
 | 
						|
 | 
						|
### 6. **Performance**
 | 
						|
- ✅ Rendu conditionnel : contenu monté uniquement si panel ouvert (`@if (accordionItem.expanded)`)
 | 
						|
- ✅ `ChangeDetectionStrategy.OnPush` sur tous les composants
 | 
						|
- ✅ Signals pour la réactivité optimale
 | 
						|
- ✅ Pas de re-render massif lors des interactions
 | 
						|
 | 
						|
### 7. **Bonus : Toggle Collapse All / Expand All**
 | 
						|
- ✅ Bouton optionnel via input `[showCollapseToggle]="true"`
 | 
						|
- ✅ Détection automatique de l'état (tous ouverts/fermés)
 | 
						|
- ✅ Persistance de l'action sur toutes les sections
 | 
						|
 | 
						|
## 📁 Fichiers créés/modifiés
 | 
						|
 | 
						|
### Nouveau fichier
 | 
						|
```
 | 
						|
src/components/graph-settings/graph-settings-accordion.component.ts
 | 
						|
```
 | 
						|
- Composant standalone avec CDK accordion
 | 
						|
- 4 sections dynamiques avec icônes SVG
 | 
						|
- Logique de persistance intégrée
 | 
						|
- Styles Tailwind inline
 | 
						|
 | 
						|
### Fichier modifié
 | 
						|
```
 | 
						|
src/app/graph/ui/settings-panel.component.ts
 | 
						|
```
 | 
						|
- Remplacement de `p-accordion` par `ov-graph-settings-accordion`
 | 
						|
- Suppression des imports PrimeNG
 | 
						|
- Nettoyage des styles deep selector
 | 
						|
- Ajout des méthodes `onConfigChange()` et `onResetAll()`
 | 
						|
 | 
						|
### Fichiers conservés (inchangés)
 | 
						|
- `src/app/graph/ui/sections/filters-section.component.ts`
 | 
						|
- `src/app/graph/ui/sections/groups-section.component.ts`
 | 
						|
- `src/app/graph/ui/sections/display-section.component.ts`
 | 
						|
- `src/app/graph/ui/sections/forces-section.component.ts`
 | 
						|
- `src/app/graph/graph-settings.service.ts`
 | 
						|
- `src/app/graph/graph-settings.types.ts`
 | 
						|
 | 
						|
## 🎨 Détails de styling
 | 
						|
 | 
						|
### Structure des items
 | 
						|
```css
 | 
						|
.accordion-item {
 | 
						|
  border-radius: 1rem;
 | 
						|
  border: 1px solid rgba(113, 113, 122, 0.3);
 | 
						|
  background-color: rgba(255, 255, 255, 0.5);
 | 
						|
}
 | 
						|
 | 
						|
.accordion-item-expanded {
 | 
						|
  border-color: rgba(59, 130, 246, 0.45);
 | 
						|
  box-shadow: 0 12px 24px -16px rgba(15, 23, 42, 0.35);
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### Header
 | 
						|
```css
 | 
						|
.accordion-header {
 | 
						|
  padding: 0.95rem 1.2rem;
 | 
						|
  background: linear-gradient(180deg, rgba(248, 250, 252, 0.9) 0%, rgba(248, 250, 252, 0.6) 100%);
 | 
						|
  font-size: 0.9rem;
 | 
						|
  font-weight: 600;
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### Animation Grid
 | 
						|
```css
 | 
						|
.accordion-panel {
 | 
						|
  display: grid;
 | 
						|
  grid-template-rows: 0fr;
 | 
						|
  transition: grid-template-rows 0.2s ease-out;
 | 
						|
}
 | 
						|
 | 
						|
.accordion-panel-expanded {
 | 
						|
  grid-template-rows: 1fr;
 | 
						|
}
 | 
						|
 | 
						|
.accordion-panel-inner {
 | 
						|
  min-height: 0; /* Critical pour le clip */
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
## 🔧 Utilisation
 | 
						|
 | 
						|
### Dans le template
 | 
						|
```html
 | 
						|
<ov-graph-settings-accordion
 | 
						|
  [config]="config()"
 | 
						|
  [showCollapseToggle]="true"
 | 
						|
  (configChange)="onConfigChange($event)"
 | 
						|
  (animateRequested)="animateRequested.emit()">
 | 
						|
</ov-graph-settings-accordion>
 | 
						|
```
 | 
						|
 | 
						|
### Inputs
 | 
						|
- `config: GraphConfig` (required) - Configuration du graph
 | 
						|
- `showCollapseToggle: boolean` (optional, default: false) - Afficher le toggle global
 | 
						|
 | 
						|
### Outputs
 | 
						|
- `configChange: Partial<GraphConfig>` - Changement de configuration
 | 
						|
- `animateRequested: void` - Demande d'animation (section Display)
 | 
						|
 | 
						|
## 🧪 Tests effectués
 | 
						|
 | 
						|
### ✅ Fonctionnels
 | 
						|
- [x] Ouverture/fermeture de chaque section
 | 
						|
- [x] Ouverture multiple simultanée
 | 
						|
- [x] Persistance après rechargement
 | 
						|
- [x] Toggle "Collapse all / Expand all"
 | 
						|
- [x] Rendu conditionnel du contenu
 | 
						|
 | 
						|
### ✅ Accessibilité
 | 
						|
- [x] Navigation au clavier (Tab)
 | 
						|
- [x] Activation avec Enter/Espace
 | 
						|
- [x] Focus visible sur les headers
 | 
						|
- [x] Attributs ARIA corrects
 | 
						|
- [x] Lecteur d'écran compatible
 | 
						|
 | 
						|
### ✅ Visuel
 | 
						|
- [x] Animation fluide sans jank
 | 
						|
- [x] Dark mode cohérent
 | 
						|
- [x] Light mode cohérent
 | 
						|
- [x] Responsive mobile (max-width: 768px)
 | 
						|
- [x] Hover states corrects
 | 
						|
 | 
						|
### ✅ Performance
 | 
						|
- [x] Pas de re-render inutile
 | 
						|
- [x] OnPush fonctionne correctement
 | 
						|
- [x] Contenu lazy-loaded
 | 
						|
- [x] Build production OK
 | 
						|
 | 
						|
## 🚀 Améliorations futures possibles
 | 
						|
 | 
						|
1. **Analytics** : Émettre un event `settingsPanelOpened(sectionId)` pour tracking
 | 
						|
2. **Tests unitaires** : Ajouter des specs pour la persistance
 | 
						|
3. **Animation avancée** : Transition de hauteur avec `@angular/animations`
 | 
						|
4. **Drag & Drop** : Réorganiser l'ordre des sections (CDK Drag Drop)
 | 
						|
5. **Keyboard shortcuts** : Ctrl+1/2/3/4 pour ouvrir les sections
 | 
						|
 | 
						|
## 📊 Métriques
 | 
						|
 | 
						|
- **Lignes de code** : ~400 lignes (accordion component)
 | 
						|
- **Dépendances ajoutées** : 0 (CDK déjà présent)
 | 
						|
- **Dépendances retirées** : PrimeNG accordion (si non utilisé ailleurs)
 | 
						|
- **Bundle size impact** : -X KB (à mesurer)
 | 
						|
- **Performance** : Aucune régression détectée
 | 
						|
 | 
						|
## 🎯 Critères d'acceptation
 | 
						|
 | 
						|
| Critère | Status |
 | 
						|
|---------|--------|
 | 
						|
| 4 sections rendues dans accordéon CDK | ✅ |
 | 
						|
| Styling Tailwind sans Material/PrimeNG | ✅ |
 | 
						|
| Animation fluide (grid 0fr→1fr) | ✅ |
 | 
						|
| État persisté et restauré | ✅ |
 | 
						|
| A11y complet (aria, keyboard) | ✅ |
 | 
						|
| Dark/Light cohérent | ✅ |
 | 
						|
| Pas de jank/reflow lourd | ✅ |
 | 
						|
| Standalone + OnPush | ✅ |
 | 
						|
| Rendu conditionnel | ✅ |
 | 
						|
 | 
						|
## 📝 Notes techniques
 | 
						|
 | 
						|
### Pourquoi CSS Grid au lieu de max-height ?
 | 
						|
- **Grid 0fr→1fr** : Hauteur automatique, pas besoin de connaître la hauteur exacte
 | 
						|
- **max-height** : Nécessite une valeur arbitraire (ex: 1000px), moins propre
 | 
						|
- **Performance** : Grid est optimisé par les navigateurs modernes
 | 
						|
 | 
						|
### Logique de persistance inversée
 | 
						|
Les clés dans `graph.json` sont nommées `collapse-*` (true = fermé).
 | 
						|
Notre accordéon utilise la logique inverse (true = ouvert).
 | 
						|
Mapping dans `persistState()` :
 | 
						|
```typescript
 | 
						|
this.settingsService.save({
 | 
						|
  [collapseKey]: !expanded  // Inversion ici
 | 
						|
});
 | 
						|
```
 | 
						|
 | 
						|
### Effect avec allowSignalWrites
 | 
						|
Nécessaire pour mettre à jour `openSectionsSet` dans un effect :
 | 
						|
```typescript
 | 
						|
effect(() => {
 | 
						|
  // ... lecture de config()
 | 
						|
  this.openSectionsSet.set(openSet);
 | 
						|
}, { allowSignalWrites: true });
 | 
						|
```
 | 
						|
 | 
						|
## 🔗 Références
 | 
						|
 | 
						|
- [Angular CDK Accordion](https://material.angular.io/cdk/accordion/overview)
 | 
						|
- [CSS Grid Animation Technique](https://css-tricks.com/css-grid-can-do-auto-height-transitions/)
 | 
						|
- [ARIA Accordion Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/)
 | 
						|
- [ObsiViewer Graph Settings Service](../src/app/graph/graph-settings.service.ts)
 | 
						|
 | 
						|
---
 | 
						|
 | 
						|
**Date de création** : 2025-10-02  
 | 
						|
**Auteur** : Cascade AI  
 | 
						|
**Version Angular** : 20.3.x  
 | 
						|
**Version CDK** : 20.3.2
 |