- Integrated Unsplash API for image search functionality with environment configuration - Added new Nimbus Editor page component with navigation from sidebar and mobile drawer - Enhanced TOC with highlight animation for editor heading navigation - Improved CDK overlay z-index hierarchy for proper menu layering - Removed obsolete logging validation script
6.7 KiB
6.7 KiB
Guide de migration - Toolbar fixe → Toolbar inline
📌 Résumé des changements
Avant (Toolbar fixe)
┌─────────────────────────────────────────┐
│ [Titre du document] │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ Start writing... [🤖][☑][1.][•][⊞]│ │ ← Barre fixe
│ └─────────────────────────────────────┘ │
│ │
│ Bloc 1: Paragraphe │
│ Bloc 2: Table │
│ Bloc 3: Image │
└─────────────────────────────────────────┘
Après (Toolbar inline)
┌─────────────────────────────────────────┐
│ [Titre du document] │
│ │
│ ⋮⋮ Start writing... [🤖][☑][1.][⊞][⬇] │ ← Inline dans le bloc
│ │
│ ⋮⋮ Bloc 1: Paragraphe [icônes...] │ ← Chaque bloc a sa toolbar
│ ⋮⋮ Bloc 2: Table [icônes...] │
│ ⋮⋮ Bloc 3: Image [icônes...] │
└─────────────────────────────────────────┘
🔄 Composants modifiés
1. EditorShellComponent
Supprimé:
// ❌ ANCIEN - Toolbar fixe au niveau shell
<div class="mb-4">
<app-editor-toolbar (action)="onToolbarAction($event)" />
</div>
Résultat: Plus de toolbar globale, chaque bloc gère la sienne.
2. ParagraphBlockComponent
Avant:
<div
contenteditable="true"
placeholder="Start writing or type '/', '@'"
></div>
Après:
<div (mouseenter)="isHovered.set(true)" (mouseleave)="isHovered.set(false)">
<app-block-inline-toolbar
[isFocused]="isFocused"
[isHovered]="isHovered"
(action)="onToolbarAction($event)"
>
<div
contenteditable="true"
(focus)="isFocused.set(true)"
(blur)="isFocused.set(false)"
></div>
</app-block-inline-toolbar>
</div>
Changements:
- ✅ Wrapper avec gestion hover/focus
- ✅ Intégration
BlockInlineToolbarComponent - ✅ Signals pour états visuels
- ✅ Détection "/" pour menu
3. BlockMenuComponent
Avant:
// Position fixe centrée
style="top: 20%; left: 50%; transform: translateX(-50%)"
width: 680px
height: 600px
Après:
// Position contextuelle près du curseur
[style.top.px]="menuPosition().top"
[style.left.px]="menuPosition().left"
width: 420px
height: 500px
Changements:
- ✅ Taille réduite (420×500 vs 680×600)
- ✅ Position dynamique basée sur bloc actif
- ✅ Design compact (spacing réduit)
- ✅ Headers sticky optimisés
📝 Checklist de migration pour autres blocs
Pour migrer un autre type de bloc (heading, list, table, etc.):
✅ Étape 1: Imports
import { signal } from '@angular/core';
import { BlockInlineToolbarComponent } from '../block-inline-toolbar.component';
import { PaletteService } from '../../../services/palette.service';
@Component({
imports: [..., BlockInlineToolbarComponent],
})
✅ Étape 2: Ajouter les signals
export class YourBlockComponent {
isFocused = signal(false);
isHovered = signal(false);
private paletteService = inject(PaletteService);
}
✅ Étape 3: Wrapper le template
<div
(mouseenter)="isHovered.set(true)"
(mouseleave)="isHovered.set(false)"
>
<app-block-inline-toolbar
[isFocused]="isFocused"
[isHovered]="isHovered"
(action)="onToolbarAction($event)"
>
<!-- Votre contenu existant -->
</app-block-inline-toolbar>
</div>
✅ Étape 4: Gérer focus/blur
<!-- Dans votre élément éditable -->
<div
contenteditable="true"
(focus)="isFocused.set(true)"
(blur)="isFocused.set(false)"
>
✅ Étape 5: Implémenter onToolbarAction
onToolbarAction(action: string): void {
if (action === 'more' || action === 'menu') {
this.paletteService.open();
} else {
// Logique spécifique au bloc
this.handleQuickAction(action);
}
}
🎯 Nouveaux comportements
Détection du "/"
onKeyDown(event: KeyboardEvent): void {
if (event.key === '/') {
const text = (event.target as HTMLElement).textContent || '';
if (text.length === 0 || text.endsWith(' ')) {
event.preventDefault();
this.paletteService.open(); // Ouvre le menu
}
}
}
États visuels
| État | Drag handle | Icônes | Background |
|---|---|---|---|
| Défaut | Caché | Cachées | Transparent |
| Hover | Visible | Semi-visibles | bg-neutral-800/30 |
| Focus | Visible | Visibles | Transparent |
🐛 Points d'attention
1. Z-index et layering
- Drag handle:
absolute -left-8(en dehors du flux) - Menu:
z-[9999](au dessus de tout) - Sticky headers:
z-10(dans le menu)
2. Responsive
Le drag handle peut déborder sur mobile. Considérer:
@media (max-width: 640px) {
.drag-handle {
position: relative;
left: 0;
}
}
3. Performance
Les signals sont efficients, mais éviter:
// ❌ MAUVAIS - Recalcul à chaque render
[isFocused]="someComplexComputation()"
// ✅ BON - Signal mis à jour explicitement
[isFocused]="isFocused"
📊 Comparaison des fichiers
| Fichier | Avant | Après | Statut |
|---|---|---|---|
editor-toolbar.component.ts |
Toolbar globale | N/A | ⚠️ Peut être supprimé |
block-inline-toolbar.component.ts |
N/A | Toolbar par bloc | ✅ Nouveau |
paragraph-block.component.ts |
Simple contenteditable | Wrapper + toolbar | ✅ Migré |
block-menu.component.ts |
Position fixe centrée | Position contextuelle | ✅ Optimisé |
editor-shell.component.ts |
Contient toolbar | Seulement blocks | ✅ Simplifié |
🔮 Prochaines étapes
- Migrer les autres blocs (heading, list, table, etc.)
- Implémenter le drag & drop via le drag handle
- Menu bloc contextuel (clic sur ⋮⋮)
- Toolbar flottante pour formatage texte (Bold, Italic, etc.)
- Tests E2E pour valider les interactions
Note: L'ancien EditorToolbarComponent peut être conservé temporairement pour référence, mais n'est plus utilisé dans le shell.