ObsiViewer/docs/NIMBUS_INLINE_EDITING_MODE.md
Bruno Charest ee3085ce38 feat: add Nimbus Editor with Unsplash integration
- 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
2025-11-11 11:38:27 -05:00

313 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Mode d'édition inline Nimbus - Documentation technique
## 📋 Vue d'ensemble
Le mode d'édition Nimbus suit le concept WYSIWYG par blocs, inspiré de Notion, avec une **toolbar inline intégrée dans chaque bloc** plutôt qu'une barre fixe.
## 🎯 Concepts clés
### 1. Toolbar inline par bloc
Chaque bloc affiche sa propre toolbar au survol ou au focus:
- **Position**: Intégrée directement dans la ligne du bloc
- **Visibilité**: Apparaît au hover ou focus
- **Drag handle**: `⋮⋮` à gauche pour déplacer/ouvrir menu contextuel
### 2. Déclenchement du menu contextuel
Le menu "Add Block" s'ouvre de **3 façons**:
1. **Caractère "/"** - Frappe au début ou après espace
2. **Icône "⬇️"** - Clic sur bouton "More items"
3. **Drag handle** - Clic sur `⋮⋮` à gauche du bloc
### 3. États visuels
```
┌─────────────────────────────────────────────────────────┐
│ État par défaut (non focus, non hover) │
│ - Placeholder gris visible │
│ - Icônes cachées (opacity: 0) │
│ - Drag handle caché │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ État hover (souris au dessus) │
│ - Background subtil (bg-neutral-800/30) │
│ - Icônes semi-visibles (opacity: 70%) │
│ - Drag handle visible │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ État focus (édition active) │
│ - Placeholder masqué │
│ - Icônes complètement visibles (opacity: 100%) │
│ - Drag handle visible │
│ - Curseur visible │
└─────────────────────────────────────────────────────────┘
```
## 🏗️ Architecture des composants
### BlockInlineToolbarComponent
**Fichier**: `src/app/editor/components/block/block-inline-toolbar.component.ts`
**Responsabilités**:
- Afficher le drag handle (⋮⋮) avec tooltip
- Afficher les icônes rapides (AI, checkbox, lists, table, etc.)
- Gérer les états hover/focus
- Émettre les actions vers le bloc parent
**Structure**:
```html
<div class="group/block">
<!-- Drag handle (absolute left) -->
<div class="absolute -left-8">⋮⋮</div>
<!-- Input wrapper -->
<div class="flex-1 px-3 py-2">
<ng-content /> <!-- Contenu éditable -->
<!-- Quick icons (conditional opacity) -->
<div class="flex gap-0.5">
<button>AI</button>
<button></button>
<button></button>
<!-- ... -->
<button>⬇️ More</button>
</div>
</div>
</div>
```
**Inputs**:
- `isFocused: Signal<boolean>` - État focus du bloc
- `isHovered: Signal<boolean>` - État hover du bloc
- `placeholder: string` - Texte du placeholder
**Outputs**:
- `action: EventEmitter<string>` - Action déclenchée (use-ai, table, more, etc.)
### ParagraphBlockComponent (mis à jour)
**Fichier**: `src/app/editor/components/block/blocks/paragraph-block.component.ts`
**Nouvelles fonctionnalités**:
1. Intégration de `BlockInlineToolbarComponent`
2. Gestion des états `isFocused` et `isHovered` via signals
3. Détection du "/" pour ouvrir le menu
4. Gestion des actions de toolbar
**Template structure**:
```html
<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>
```
### BlockMenuComponent (optimisé)
**Fichier**: `src/app/editor/components/palette/block-menu.component.ts`
**Changements**:
- **Taille réduite**: 420px × 500px (vs 680px × 600px)
- **Position contextuelle**: S'ouvre près du bloc actif/curseur
- **Design compact**: Spacing réduit, textes plus petits
- **Sticky headers**: Restent visibles au scroll
**Positionnement**:
```typescript
menuPosition = computed(() => {
const activeBlock = document.querySelector('[contenteditable]:focus');
if (activeBlock) {
const rect = activeBlock.getBoundingClientRect();
return {
top: rect.top + 30, // 30px sous le curseur
left: rect.left // Aligné à gauche
};
}
return { top: 100, left: 50 }; // Fallback
});
```
## 🎨 Design tokens
### Toolbar inline
```css
/* Drag handle */
-left-8 /* Position absolue gauche */
opacity-0 /* Caché par défaut */
group-hover/block:opacity-100 /* Visible au hover */
/* Container */
px-3 py-2 /* Padding interne */
hover:bg-neutral-800/30 /* Background au hover */
rounded-lg /* Coins arrondis */
/* Icônes */
w-4 h-4 /* Taille icônes */
text-gray-400 /* Couleur par défaut */
hover:text-gray-200 /* Couleur au hover */
```
### Menu contextuel
```css
/* Panel */
bg-neutral-800/98 /* Background semi-transparent */
backdrop-blur-md /* Effet flou */
w-[420px] /* Largeur fixe */
max-h-[500px] /* Hauteur max */
rounded-lg /* Coins arrondis */
border-neutral-700 /* Bordure */
/* Section header (sticky) */
sticky top-0 /* Reste en haut au scroll */
bg-neutral-800/95 /* Background avec transparence */
backdrop-blur-md /* Flou de fond */
text-[10px] /* Texte très petit */
uppercase tracking-wider /* Majuscules espacées */
/* Item */
px-2 py-1.5 /* Padding compact */
hover:bg-neutral-700/80 /* Background hover */
text-sm /* Texte petit */
```
## 🔧 Intégration dans d'autres blocs
Pour ajouter la toolbar inline à un autre type de bloc:
### 1. Importer le composant
```typescript
import { BlockInlineToolbarComponent } from '../block-inline-toolbar.component';
import { signal } from '@angular/core';
@Component({
imports: [BlockInlineToolbarComponent],
// ...
})
```
### 2. Ajouter les signals
```typescript
isFocused = signal(false);
isHovered = signal(false);
```
### 3. Wrapper le contenu
```html
<div
(mouseenter)="isHovered.set(true)"
(mouseleave)="isHovered.set(false)"
>
<app-block-inline-toolbar
[isFocused]="isFocused"
[isHovered]="isHovered"
(action)="onToolbarAction($event)"
>
<!-- Votre contenu éditable ici -->
</app-block-inline-toolbar>
</div>
```
### 4. Gérer les événements
```typescript
onToolbarAction(action: string): void {
if (action === 'more' || action === 'menu') {
this.paletteService.open();
} else {
// Logique spécifique
}
}
```
## 📱 Responsive
### Desktop
- Drag handle à `-left-8` (32px à gauche)
- Toutes les icônes visibles
- Menu 420px de large
### Tablet
- Drag handle visible au tap
- Menu 90% de la largeur viewport
- Icônes réduites
### Mobile
- Drag handle toujours visible
- Menu plein écran
- Toolbar simplifiée (icônes essentielles seulement)
## ⌨️ Raccourcis clavier
### Dans un bloc
| Touche | Action |
|--------|--------|
| `/` | Ouvrir le menu contextuel |
| `@` | Mention (futur) |
| `Enter` | Nouveau bloc paragraphe |
| `Backspace` (bloc vide) | Supprimer le bloc |
| `↑` / `↓` | Naviguer entre blocs |
### Dans le menu
| Touche | Action |
|--------|--------|
| `↑` / `↓` | Naviguer dans les items |
| `Enter` | Sélectionner l'item |
| `Esc` | Fermer le menu |
| Lettres | Rechercher |
## 🚀 Améliorations futures
1. **Drag & drop** - Utiliser le drag handle pour réordonner
2. **Menu bloc contextuel** - Options spécifiques (dupliquer, supprimer, transformer)
3. **Formatage texte** - Bold, italic, couleur via toolbar flottante sur sélection
4. **Slash commands avancés** - `/table 3x3`, `/heading 2`, etc.
5. **Templates inline** - Insertion rapide de structures prédéfinies
6. **Collaboration** - Curseurs multiples et édition temps réel
## 📐 Schéma de flux
```
Utilisateur clique dans un bloc
isFocused.set(true)
Toolbar inline devient visible (opacity: 100%)
Utilisateur tape "/"
PaletteService.open()
BlockMenuComponent s'affiche près du curseur
Utilisateur sélectionne un item
Nouveau bloc inséré après le bloc actuel
Focus sur le nouveau bloc
```
---
**Version**: 2.0
**Date**: 7 novembre 2025
**Auteur**: Nimbus Team