feat: editor improvements and architectural grid prototype
Multiple feature additions and improvements across the application: - NextGen Editor: drag handles, smart paste, block actions - Structured views: Kanban and table layouts for notes - Architectural Grid: new brainstorming/agent interface prototype - Flashcards: SM-2 revision algorithm with AI generation - MCP server: robustness improvements - Graph/PDF chat: fix click propagation and copy behavior - Various UI/UX enhancements and bug fixes Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,3 +58,7 @@ development_status:
|
||||
4-5-eu-data-residency: backlog
|
||||
4-6-sso-saml-audit-logging: backlog
|
||||
epic-4-retrospective: optional
|
||||
epic-5: in-progress
|
||||
5-1-nextgen-editor: ready-for-dev
|
||||
|
||||
|
||||
|
||||
118
docs/story-nextgen-editor.md
Normal file
118
docs/story-nextgen-editor.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Story: Éditeur Next-Gen — Poignée Gutter & Base de Données Inline
|
||||
|
||||
> **Epic:** Éditeur de Notes et Saisie Intuitive (Next-Gen)
|
||||
> **Priority:** High
|
||||
> **Status:** ready-for-dev
|
||||
> **Depends on:** US-LIVING-BLOCKS (UniqueID et transclusion), US-STRUCTURED-VIEWS (NotebookSchema et propriétés)
|
||||
> **Blocks:** —
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
L'éditeur de notes actuel de Momento est construit sur [rich-text-editor.tsx](file:///home/devparsa/dev/Momento/memento-note/components/rich-text-editor.tsx) avec Tiptap/ProseMirror. Bien qu'il supporte des fonctionnalités avancées (Blocs Vivants, Résonance Sémantique), l'interaction utilisateur de saisie reste celle d'un traitement de texte classique (document linéaire à curseur unique).
|
||||
|
||||
Pour offrir une expérience de saisie supérieure à celle de Notion (plus performante, plus fluide à l'écriture) tout en conservant les avantages de la manipulation de blocs, nous implémentons une approche hybride :
|
||||
1. **Gutter & Drag Handle Flottant :** Au lieu d'avoir un composant React lourd pour chaque paragraphe (comme dans Notion), un unique bouton de poignée de glissement suit le curseur de la souris dans la marge de l'éditeur en ProseMirror pur, éliminant tout décalage à la saisie.
|
||||
2. **Transclusion au Collage :** Faciliter la création de Blocs Vivants en interceptant les liens de blocs copiés et en proposant de les coller en tant que transclusion synchrone.
|
||||
3. **Bloc Database Inline :** Porter le composant de base de données relationnelle du prototype [ModernBlockNoteEditor.tsx](file:///home/devparsa/dev/Momento/architectural-grid1/src/components/ModernBlockNoteEditor.tsx#L1711) pour permettre aux utilisateurs d'insérer des tableaux/fiches interactives avec Rollups dynamiques directement au sein de leurs notes.
|
||||
|
||||
---
|
||||
|
||||
## User Stories
|
||||
|
||||
### US-1: Poignée de Glissement Gutter Unique (Hover Drag Handle)
|
||||
**En tant que** rédacteur,
|
||||
**Je veux** voir apparaître une poignée de glissement discrète dans la marge gauche du bloc que je survole avec ma souris,
|
||||
**Afin de** pouvoir réordonner mes blocs par glisser-déposer de manière fluide.
|
||||
|
||||
#### Critères d'Acceptation :
|
||||
* **Étant donné** que j'ai une note ouverte dans l'éditeur de Momento
|
||||
* **Quand** je survole une ligne de texte (paragraphe, titre, liste, citation, etc.) avec mon curseur de souris
|
||||
* **Alors** une poignée de glissement (`::drag-handle` flottante) apparaît dans le gutter gauche à la hauteur exacte du bloc survolé
|
||||
* **Et** le bouton suit mes déplacements de souris d'un bloc à l'autre sans latence et sans dupliquer les nœuds DOM (une seule poignée réutilisée)
|
||||
* **Quand** je clique-glisse sur cette poignée
|
||||
* **Alors** le bloc ProseMirror entier sous-jacent est sélectionné visuellement et je peux le déplacer vers le haut ou vers le bas, avec un indicateur visuel de la ligne d'insertion
|
||||
* **Et** la poignée est masquée sur les terminaux mobiles / écrans tactiles pour éviter d'entraver l'ergonomie.
|
||||
|
||||
---
|
||||
|
||||
### US-2: Menu Action Rapide de Bloc
|
||||
**En tant que** créateur de contenu,
|
||||
**Je veux** pouvoir cliquer sur la poignée de bloc pour ouvrir un menu contextuel d'actions rapides,
|
||||
**Afin de** manipuler la structure de mes documents sans avoir à utiliser les sélections de texte complexes ou des raccourcis clavier obscurs.
|
||||
|
||||
#### Critères d'Acceptation :
|
||||
* **Étant donné** que la poignée de bloc est visible à côté d'un bloc
|
||||
* **Quand** je clique sur cette poignée
|
||||
* **Alors** un menu contextuel (dropdown à base de glassmorphism fluide) apparaît
|
||||
* **Et** il propose les options suivantes :
|
||||
* `Supprimer` -> Efface le bloc ProseMirror ciblé
|
||||
* `Dupliquer` -> Duplique le bloc ProseMirror immédiatement en dessous
|
||||
* `Transformer en` -> Sous-menu pour convertir en : Titre 1, Titre 2, Titre 3, Liste à puces, Liste numérotée, Liste de tâches, Citation, Bloc de code, ou Base de données
|
||||
* `Copier la référence` -> Génère/copie le lien unique du bloc (utilisant son `UniqueID` Tiptap) dans le presse-papier.
|
||||
|
||||
---
|
||||
|
||||
### US-3: Transclusion intelligente au Collage (Smart Paste)
|
||||
**En tant que** chercheur,
|
||||
**Je veux** pouvoir coller un lien de bloc copié et le transformer instantanément en bloc connecté synchrone,
|
||||
**Afin de** lier et synchroniser des informations à travers différentes notes sans effort manuel.
|
||||
|
||||
#### Critères d'Acceptation :
|
||||
* **Étant donné** que j'ai copié la référence d'un bloc (contenant l'ID de la note source et le `blockId` unique du paragraphe)
|
||||
* **Quand** je colle (Ctrl+V ou Cmd+V) ce lien dans un paragraphe vide d'une autre note
|
||||
* **Alors** un petit menu interactif en ligne s'affiche : *"Coller en tant que Bloc Connecté (Live)"* ou *"Coller en tant que texte / lien simple"*
|
||||
* **Quand** je sélectionne *"Bloc Connecté"*,
|
||||
* **Alors** le bloc ProseMirror est remplacé par un nœud de type `liveBlock` (provenant de notre [LiveBlockExtension](file:///home/devparsa/dev/Momento/memento-note/components/tiptap-live-block-extension.tsx#L159)) synchronisant le contenu en temps réel.
|
||||
|
||||
---
|
||||
|
||||
### US-4: Bloc de Base de Données Relationnelle Inline
|
||||
**En tant que** chef de projet ou gestionnaire de données,
|
||||
**Je veux** pouvoir insérer une base de données relationnelle interactive directement au milieu de mon texte, basculer ses vues et suivre des rollups,
|
||||
**Afin de** structurer mes informations complexes sans quitter le flux de ma note (comme simulé dans le prototype).
|
||||
|
||||
#### Critères d'Acceptation :
|
||||
* **Étant donné** que j'utilise l'éditeur de Momento
|
||||
* **Quand** je saisis `/database` ou sélectionne "Base de données" dans le menu d'insertion
|
||||
* **Alors** un bloc `databaseBlock` est inséré sous forme d'un React NodeView
|
||||
* **Et** il propose par défaut un modèle relationnel "Auteurs & Œuvres" (avec des données simulées ou liées au carnet actuel)
|
||||
* **Quand** je clique sur le sélecteur de vue en haut à droite du bloc
|
||||
* **Alors** je peux basculer entre la vue **Tableau** (grille avec colonnes de propriétés) et la vue **Fiches** (cartes illustrées de couvertures, tags et auteurs)
|
||||
* **Et** la colonne **Rollup Count** de la vue Tableau recalcule dynamiquement le nombre de livres liés à chaque auteur au fur et à mesure que j'ajoute ou supprime des fiches
|
||||
* **Et** un formulaire d'insertion rapide en bas du bloc me permet d'ajouter des livres ou des auteurs à ce modèle relationnel local.
|
||||
|
||||
---
|
||||
|
||||
## Spécifications Techniques d'Implémentation
|
||||
|
||||
### 1. Structure du Nœud de Base de Données Tiptap (`DatabaseBlock`)
|
||||
Créer une extension Tiptap personnalisée `DatabaseBlockExtension` dans `/components/tiptap-database-block-extension.tsx` qui :
|
||||
- Gère un groupe `block`, se comporte comme un atome (non modifiable directement en texte brut).
|
||||
- Conserve les attributs : `dbId` (string), `dbView` ('table' | 'card'), `dbAuthors` (array) et `dbBooks` (array) représentant le schéma et les valeurs.
|
||||
- Utilise un `ReactNodeViewRenderer` pour monter notre composant d'édition de base de données relationnelle en React pur.
|
||||
|
||||
### 2. Le Plugin Drag Handle & Gutter en ProseMirror
|
||||
Développer un plugin custom dans `/components/tiptap-drag-handle-plugin.ts` :
|
||||
* Attacher un écouteur d'événements `mouseover` et `mousemove` sur l'éditeur ProseMirror.
|
||||
* Utiliser `view.posAtCoords` pour localiser le nœud ProseMirror survolé.
|
||||
* Récupérer son DOM parent et calculer sa hauteur et son décalage vertical.
|
||||
* Repositionner l'élément HTML de la poignée en modifiant ses styles CSS `top` et `left` (le bouton est monté au niveau de l'éditeur parent en absolute, évitant d'être injecté dans le texte éditable).
|
||||
* Gérer le glissement avec l'API HTML5 Drag and Drop couplée aux transactions de ProseMirror (`tr.replaceWith` ou `MoverBlock`).
|
||||
|
||||
### 3. Fichiers à modifier / créer :
|
||||
* `[NEW]` `memento-note/components/tiptap-drag-handle-plugin.ts` — Plugin de poignée Gutter
|
||||
* `[NEW]` `memento-note/components/tiptap-database-block-extension.tsx` — Nœud et composant DatabaseBlockEditor
|
||||
* `[MODIFY]` `memento-note/components/rich-text-editor.tsx` — Intégration du Drag Handle, de la DatabaseBlockExtension et de l'interception du presse-papier dans `editorProps.handlePaste`
|
||||
* `[MODIFY]` `memento-note/app/globals.css` — Ajout des classes CSS pour l'alignement précis du gutter, de la poignée, et du bloc de base de données (glassmorphic dropdowns et fiches).
|
||||
|
||||
---
|
||||
|
||||
## Plan de Vérification
|
||||
|
||||
### Tests Manuels :
|
||||
1. **Vérification Gutter :** Survoler des textes longs et vérifier que la poignée se positionne correctement à gauche. Glisser un paragraphe sur un autre et valider le réordonnancement.
|
||||
2. **Vérification Menu :** Cliquer sur la poignée, dupliquer le bloc, supprimer le bloc, et le transformer en d'autres types.
|
||||
3. **Vérification Paste :** Copier une référence de bloc, la coller, et vérifier que la transclusion est proposée et s'insère sous forme de `LiveBlock`.
|
||||
4. **Vérification Base de Données Inline :** Insérer le bloc base de données, ajouter un auteur, ajouter un livre avec cet auteur, vérifier le bon calcul du rollup, et basculer en vue Fiches pour vérifier l'affichage des couvertures.
|
||||
@@ -1,7 +1,7 @@
|
||||
# User Stories — Momento Next Phase
|
||||
|
||||
> Basé sur l'analyse du prototype `architectural-grid/` et du code production `memento-note/`.
|
||||
> Dernière mise à jour : 2026-05-24
|
||||
> Dernière mise à jour : 2026-05-25 (US-NEXTGEN-EDITOR réorganisé, 4 nouvelles stories éditeur ajoutées)
|
||||
|
||||
---
|
||||
|
||||
@@ -16,25 +16,44 @@
|
||||
| **US-INFO-RÉSEAU** | Panneau Info + Réseau Local | ✅ **LIVRÉ** | `note-network-tab.tsx`, `sync-note-links.ts`, migration `NoteLink`, picker `[[` |
|
||||
| **US-CLIPPER** | Web Clipper | ✅ **LIVRÉ** | `extension/`, `/api/clip/*`, migration `sourceUrl`, badge panneau Info |
|
||||
| **US-GRAPH** | Graphe de Connaissance Global enrichi | ✅ **LIVRÉ** | `note-graph-view.tsx` — filtres liens, seuil sémantique, focus voisinage, couleurs carnets, double-clic ouverture |
|
||||
| **US-INSIGHTS** | Clusters Sémantiques + Bridge Notes | 🚧 **EN COURS** | clusters en base mais page masquait les résultats périmés — correction affichage |
|
||||
| **US-TEMPORAL** | Prédictions d'accès temporelles | ⏳ À faire | — |
|
||||
| **US-INSIGHTS** | Clusters Sémantiques + Bridge Notes | ✅ **LIVRÉ** | `app/(main)/insights/page.tsx`, `network-graph.tsx`, `/api/clusters`, `/api/bridge-notes/*`, état dégradé si clusters périmés |
|
||||
| **US-TEMPORAL** | Prédictions d'accès temporelles | ⏸️ **REPORTÉ** | Remplacé par rappels + révision SM-2 + Memory Echo ; heuristique faible, migration NoteAccessLog non prioritaire |
|
||||
| **US-FLASHCARDS** | Révision IA — Répétition espacée SM-2 | ✅ **LIVRÉ** | `/revision`, `/api/flashcards/*`, SM-2, génération IA depuis l'éditeur |
|
||||
| **US-STRUCTURED-VIEWS** | Vues Structurées (Tableau/Kanban/Galerie) | ✅ **LIVRÉ** | `/api/notebooks/[id]/schema`, `/api/notes/[id]/properties`, vues structurées + panneau propriétés éditeur |
|
||||
| **US-NEXTGEN-EDITOR** | Éditeur Next-Gen : Drag Handle + Menu Bloc + DB Inline + Smart Paste | 🚧 **PLANIFIÉ** | Voir `docs/story-nextgen-editor.md` |
|
||||
| **US-EDITOR-PERF** | Performance de frappe TipTap (quick wins) | 🚧 **PLANIFIÉ** | — |
|
||||
| **US-EDITOR-UX** | Micro-interactions saisie (slash menu, sélection multi-blocs, paste étendu, placeholders) | ⏳ **À FAIRE** | — |
|
||||
| **US-EDITOR-MOBILE** | Expérience tactile & toolbar mobile adaptée | ⏳ **À FAIRE** | — |
|
||||
| **US-EDITOR-MARKDOWN** | Rendu WYSIWYG Markdown fidèle (round-trip byte-for-byte) | ⏳ **À FAIRE** | — |
|
||||
|
||||
---
|
||||
|
||||
## Ordre d'implémentation (dépendances)
|
||||
|
||||
```
|
||||
US-LIVING-BLOCKS ← dépend de : TipTap UniqueID (fondation)
|
||||
US-MEMORY-ECHO ← dépend de : pgvector existant (aucune migration)
|
||||
US-INFO-RÉSEAU ← dépend de : wikilinks + backlinks existants
|
||||
US-CLIPPER ← dépend de : migration Note.sourceUrl
|
||||
US-GRAPH ← dépend de : /api/graph existant
|
||||
US-INSIGHTS ← dépend de : Memory Echo + clusters
|
||||
US-TEMPORAL ← dépend de : migration NoteAccessLog
|
||||
US-FLASHCARDS ← dépend de : migration FlashcardDeck + Flashcard
|
||||
US-STRUCTURED-VIEWS ← dépend de : migration NotebookSchema + NotebookProperty
|
||||
Quick wins (en premier, ~2h) :
|
||||
US-EDITOR-PERF <- depend de : rien (modifs config TipTap)
|
||||
|
||||
Editeur Next-Gen (bloc principal) :
|
||||
US-NEXTGEN-EDITOR <- depend de : US-LIVING-BLOCKS, US-STRUCTURED-VIEWS
|
||||
US-EDITOR-UX <- depend de : US-NEXTGEN-EDITOR (drag handle + menu bloc en place)
|
||||
US-EDITOR-MOBILE <- depend de : US-NEXTGEN-EDITOR (drag handle existant)
|
||||
|
||||
Plus tard :
|
||||
US-EDITOR-MARKDOWN <- depend de : rien (evaluation Milkdown, low priority)
|
||||
|
||||
Stories livrees :
|
||||
US-LIVING-BLOCKS <- depend de : TipTap UniqueID (fondation)
|
||||
US-MEMORY-ECHO <- depend de : pgvector existant
|
||||
US-INFO-RESEAU <- depend de : wikilinks + backlinks
|
||||
US-CLIPPER <- depend de : migration Note.sourceUrl
|
||||
US-GRAPH <- depend de : /api/graph existant
|
||||
US-INSIGHTS <- depend de : Memory Echo + clusters
|
||||
US-FLASHCARDS <- depend de : migration FlashcardDeck + Flashcard
|
||||
US-STRUCTURED-VIEWS <- depend de : migration NotebookSchema + NotebookProperty
|
||||
|
||||
Reportees :
|
||||
US-TEMPORAL <- depend de : migration NoteAccessLog (REPORTE)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -539,6 +558,8 @@ model FlashcardReview {
|
||||
|
||||
## US-TEMPORAL — Prédictions d'Accès Temporelles
|
||||
|
||||
> **Statut : ⏸️ REPORTÉ (2026-05-24)** — Chevauche rappels, révision SM-2 et Memory Echo ; faible signal sans volume d'ouvertures ; pas prioritaire pour éviter la surcharge produit. Spec conservée pour réévaluation ultérieure éventuelle.
|
||||
|
||||
**Contexte :**
|
||||
`TemporalView.tsx` (169L) prédit quelles notes l'utilisateur voudra relire, basé sur des patterns d'accès. Rien n'existe en prod. Feature légère à fort impact perçu.
|
||||
|
||||
@@ -569,3 +590,231 @@ model NoteAccessLog {
|
||||
- Liste des 3 meilleures prédictions
|
||||
- Badge `cyclique` / `tendance` selon le type
|
||||
- Clic → ouvre la note
|
||||
|
||||
---
|
||||
|
||||
## US-NEXTGEN-EDITOR — Éditeur Next-Gen : Drag Handle + Menu Bloc + DB Inline + Smart Paste
|
||||
|
||||
> **Status :** PLANIFIÉ
|
||||
> **Depends on :** US-LIVING-BLOCKS (UniqueID et transclusion), US-STRUCTURED-VIEWS (NotebookSchema et propriétés)
|
||||
> **Spec détaillée :** `docs/story-nextgen-editor.md` (4 sous-stories : US-1 Drag Handle, US-2 Menu Action Bloc, US-3 Smart Paste, US-4 Database Inline)
|
||||
|
||||
**Contexte :**
|
||||
L'éditeur actuel est un document linéaire classique. Pour rivaliser avec Notion tout en étant plus performant, on implémente une approche hybride : un unique bouton de poignée en ProseMirror pur (pas de composant React lourd par paragraphe), un menu contextuel de bloc, une transclusion au collage, et un bloc database inline.
|
||||
|
||||
**4 sous-stories** (détail dans `docs/story-nextgen-editor.md`) :
|
||||
|
||||
### US-1 : Poignée de Glissement Gutter Unique (Hover Drag Handle)
|
||||
- Bouton flottant unique dans la marge gauche, suit le curseur de bloc en bloc
|
||||
- Un seul élément DOM repositionné (pas de duplication)
|
||||
- Drag & drop de blocs avec indicateur de ligne d'insertion
|
||||
- Masqué sur mobile/tactile
|
||||
|
||||
### US-2 : Menu Action Rapide de Bloc
|
||||
- Clic sur la poignée -> dropdown glassmorphism
|
||||
- Actions : Supprimer, Dupliquer, Transformer en (H1/H2/H3/liste/todo/citation/code/database), Copier la référence
|
||||
- Utilise le `UniqueID` TipTap pour les références stables
|
||||
|
||||
### US-3 : Transclusion intelligente au Collage (Smart Paste)
|
||||
- Collage d'un lien de bloc -> menu inline : "Bloc Connecté (Live)" ou "Texte simple"
|
||||
- Insère un nœud `liveBlock` synchronisé via Redis Pub/Sub
|
||||
|
||||
### US-4 : Bloc de Base de Données Relationnelle Inline
|
||||
- Slash `/database` -> insère un React NodeView
|
||||
- Vues Tableau / Fiches avec Rollup dynamique
|
||||
- Modèle relationnel local (auteurs/livres par défaut, ou lié au carnet)
|
||||
|
||||
### Fichiers
|
||||
- `[NEW]` `tiptap-drag-handle-plugin.ts` — Plugin ProseMirror pur
|
||||
- `[NEW]` `tiptap-database-block-extension.tsx` — NodeView React
|
||||
- `[MODIFY]` `rich-text-editor.tsx` — Intégration drag handle + DB + paste intercept
|
||||
- `[MODIFY]` `globals.css` — Gutter, poignée, glassmorphic dropdowns
|
||||
|
||||
---
|
||||
|
||||
## US-EDITOR-PERF — Performance de Frappe TipTap (Quick Wins)
|
||||
|
||||
> **Status :** PLANIFIÉ
|
||||
> **Depends on :** rien (modifications config TipTap, ~2h)
|
||||
> **Priorité :** HAUTE — impact immédiat sur le ressenti de saisie
|
||||
> **Source recherche :** TipTap 2.5 (mai 2026), TipTap docs performance, PR #7828
|
||||
|
||||
**Contexte :**
|
||||
Actuellement `rich-text-editor.tsx` utilise `immediatelyRender: false` mais pas `shouldRerenderOnTransaction` ni `useEditorState`. TipTap re-render le composant React à chaque transaction (frappe, déplacement curseur, sélection) — ce qui ajoute de la latence. Obsidian atteint <16ms de latence (local-first), Notion 50-150ms (cloud). Momento est local mais se comporte comme Notion à cause de ces re-renders inutiles.
|
||||
|
||||
**En tant qu'utilisateur**, je veux que la frappe dans l'éditeur soit instantanée, sans aucun décalage perceptible, même sur des notes longues avec de nombreux blocs.
|
||||
|
||||
### 1. shouldRerenderOnTransaction: false (1 ligne)
|
||||
```typescript
|
||||
// rich-text-editor.tsx — useEditor()
|
||||
const editor = useEditor({
|
||||
extensions: [...],
|
||||
immediatelyRender: false,
|
||||
shouldRerenderOnTransaction: false, // <-- AJOUTER
|
||||
// ...
|
||||
})
|
||||
```
|
||||
- Le composant React EditorContent ne se re-render plus sur chaque transaction
|
||||
- Seul le DOM ProseMirror est mis à jour (ultra-rapide, natif)
|
||||
- Gain mesurable : de ~50-100ms par frappe à <16ms
|
||||
|
||||
### 2. useEditorState pour la toolbar et les panels
|
||||
```typescript
|
||||
import { useEditorState } from '@tiptap/react'
|
||||
|
||||
// Au lieu de useEditor + editor.isActive() dans le render :
|
||||
const { isBold, isItalic, isHeading } = useEditorState({
|
||||
editor,
|
||||
selector: (ctx) => ({
|
||||
isBold: ctx.editor.isActive('bold'),
|
||||
isItalic: ctx.editor.isActive('italic'),
|
||||
isHeading: ctx.editor.isActive('heading'),
|
||||
}),
|
||||
})
|
||||
```
|
||||
- La toolbar et le panneau propriétés ne se re-rendent que quand leur slice d'état change
|
||||
- Actuellement, tout le composant editor re-render à chaque frappe -> la toolbar aussi
|
||||
|
||||
### 3. Isoler l'éditeur dans un composant dédié
|
||||
- Créer `NoteEditorCore` (composant wrapper) qui ne reçoit que les props strictement nécessaires
|
||||
- Les re-renders du parent (note-panel, sidebar ouverture, etc.) ne doivent PAS propager dans l'éditeur
|
||||
- React.memo sur le wrapper si besoin
|
||||
|
||||
### 4. NodeViews : trackNodeViewPosition: false par défaut
|
||||
- Les NodeViews React (LiveBlock, Chart, DatabaseBlock) ne doivent pas se re-re-render quand seul leur position dans le document change
|
||||
- TipTap PR #7828 (mai 2026) : shallow prop comparison + opt-in position tracking
|
||||
- Vérifier que chaque NodeView utilise `stopEvent()`, `ignoreMutation()`, et ne déclenche pas de setState inutile
|
||||
|
||||
### 5. Vérification
|
||||
- `console.count('editor render')` dans le composant éditeur pour mesurer le nombre de re-renders
|
||||
- Objectif : 0 re-render React pendant la frappe pure (seul ProseMirror DOM bouge)
|
||||
|
||||
---
|
||||
|
||||
## US-EDITOR-UX — Micro-Interactions de Saisie
|
||||
|
||||
> **Status :** À FAIRE
|
||||
> **Depends on :** US-NEXTGEN-EDITOR (drag handle et menu bloc doivent être en place)
|
||||
> **Source recherche :** Mintlify "22 UX improvements" (mai 2026), BlockNote v0.50, BlockNote v0.49
|
||||
|
||||
**Contexte :**
|
||||
Après les quick wins performance (US-EDITOR-PERF) et le drag handle (US-NEXTGEN-EDITOR), il reste des micro-interactions qui font la différence entre un éditeur "correct" et un éditeur "agréable". Mintlify a listé 22 améliorations UX en mai 2026 — voici les plus pertinentes pour Momento.
|
||||
|
||||
**En tant qu'utilisateur**, je veux que chaque interaction courante (insérer un bloc, déplacer du contenu, transformer un format) soit fluide et intuitive, sans recourir à des raccourcis clavier obscurs.
|
||||
|
||||
### 1. Sélection globale de blocs (Haute priorité)
|
||||
- Shift+clic pour sélectionner plusieurs blocs contigus
|
||||
- Drag de sélection multi-blocs
|
||||
- Actions groupées : supprimer, déplacer, transformer en masse
|
||||
- Visuel : blocs sélectionnés avec fond accent/5, bordure accent/30
|
||||
- **Inspiration :** Mintlify "Global Block Selection" — nettoyage de pages longues sans actions répétées
|
||||
|
||||
### 2. Slash menu redessiné (Haute priorité)
|
||||
- Type-to-search avec catégories visuelles (Texte, Média, Données, Intégré, IA)
|
||||
- Navigation clavier fluide (flèches + Entrée, Esc pour fermer)
|
||||
- Épinglage des 3-5 commandes les plus utilisées en haut
|
||||
- Description courte sous chaque item (ex. "Code" -> "Bloc de code avec coloration syntaxique")
|
||||
- Preview visuel au survol pour les blocs complexes (tableau, database, chart)
|
||||
- **Inspiration :** Mintlify slash menu redesign, BlockNote catégories
|
||||
|
||||
### 3. Placeholders contextuels par type de bloc (Moyenne priorité)
|
||||
- Paragraphe vide : "Tapez / pour insérer un bloc..."
|
||||
- Heading H1 vide : "Titre principal"
|
||||
- Heading H2 vide : "Titre de section"
|
||||
- TaskItem vide : "Ajouter une tâche"
|
||||
- Bloc de code vide : "Code..."
|
||||
- Bullet list vide : "Liste"
|
||||
- **Inspiration :** BlockNote "Helpful placeholders"
|
||||
|
||||
### 4. Collage intelligent étendu (Moyenne priorité)
|
||||
- Coller une URL HTTP(S) -> propose : lien hypertexte / intégration image / intégration vidéo
|
||||
- Coller du code (détecté par caractères spéciaux {}[];) -> propose : bloc de code avec auto-détection langage
|
||||
- Coller une image depuis le presse-papier -> upload direct (déjà en prod, vérifier la fluidité)
|
||||
- Coller du HTML riche -> nettoyage intelligent (conserver structure, supprimer styles inline superflus)
|
||||
- **Inspiration :** US-3 Smart Paste existe pour les blocs connectés — étendre au contenu générique
|
||||
|
||||
### 5. "Turn into" instant (Moyenne priorité)
|
||||
- Raccourci clavier : sélectionner du texte + `Cmd+Shift+H` -> cycle H1 > H2 > H3 > paragraphe
|
||||
- Via le menu bloc (US-2) : transformation instantanée sans flash ni re-render visible
|
||||
- Conserver le contenu et les attributs (gras, liens, etc.) lors de la conversion
|
||||
- **Inspiration :** Mintlify "Turn Blocks Into Anything"
|
||||
|
||||
### 6. Undo/redo visuel discret (Basse priorité)
|
||||
- Toast subtil (2s) : "Action annulée" / "Action rétablie"
|
||||
- Raccourci affiché dans le toast : "Cmd+Z pour annuler, Cmd+Shift+Z pour rétablir"
|
||||
- Ne pas utiliser toast pour les actions normales — seulement undo/redo pour confirmer le feedback
|
||||
|
||||
---
|
||||
|
||||
## US-EDITOR-MOBILE — Expérience Tactile & Toolbar Mobile
|
||||
|
||||
> **Status :** À FAIRE
|
||||
> **Depends on :** US-NEXTGEN-EDITOR (drag handle existant)
|
||||
> **Source recherche :** Notion mobile app, Obsidian mobile, benchmark 2026
|
||||
|
||||
**Contexte :**
|
||||
L'éditeur fonctionne sur mobile mais l'expérience est dégradée : la bubble menu est trop petite pour les doigts, le drag handle est masqué (prévu) mais il n'y a pas d'alternative tactile, et les sélections longues sont douloureuses en contenteditable.
|
||||
|
||||
**En tant qu'utilisateur mobile**, je veux pouvoir éditer mes notes confortablement depuis mon téléphone ou tablette, avec des contrôles adaptés au tactile.
|
||||
|
||||
### 1. Toolbar mobile adaptée
|
||||
- Remplacer la bubble menu desktop par une toolbar fixe en bas d'écran (viewport < 768px)
|
||||
- Boutons 44x44px minimum (Apple HIG)
|
||||
- 8 actions principales : Gras, Italique, Surligner, Lien, Liste, Titre, Code, Plus (menu étendu)
|
||||
- Scroll horizontal si plus d'actions
|
||||
- **Inspiration :** Notion mobile toolbar
|
||||
|
||||
### 2. Menu bloc tactile
|
||||
- Pas de drag handle sur mobile (déjà prévu dans US-1)
|
||||
- Alternative : swipe gauche sur un bloc -> reveal actions (supprimer, dupliquer, transformer)
|
||||
- Ou : tap long sur un bloc -> menu contextuel mobile natif (action sheet iOS / bottom sheet Android)
|
||||
- Bouton "Déplacer" dans le menu -> mode réorganisation avec poignées tactiles
|
||||
|
||||
### 3. Sélection de texte améliorée
|
||||
- Les sélections longues en contenteditable sont frustrantes sur mobile
|
||||
- Ajouter un bouton "Sélectionner tout le bloc" dans le menu bloc tactile
|
||||
- Double-tap sélectionne le mot, triple-tap sélectionne le paragraphe (comportement natif iOS/Android, vérifier que TipTap ne l'écrase pas)
|
||||
|
||||
### 4. Performance mobile
|
||||
- Les NodeViews React lourds (Chart, DatabaseBlock) doivent avoir un fallback léger sur mobile
|
||||
- Désactiver les animations de la bubble menu sur mobile (prefers-reduced-motion)
|
||||
- `immediatelyRender: false` déjà en place — bon pour le premier rendu mobile
|
||||
|
||||
---
|
||||
|
||||
## US-EDITOR-MARKDOWN — Rendu WYSIWYG Markdown Fidèle
|
||||
|
||||
> **Status :** À FAIRE (low priority)
|
||||
> **Depends on :** rien (évaluation Milkdown)
|
||||
> **Source recherche :** Milkdown v7.20, "Human Markdown" extension VSCode, round-trip byte-for-byte
|
||||
|
||||
**Contexte :**
|
||||
Momento stocke les notes en HTML (TipTap). Mais les notes de type `markdown` existent aussi. Le problème classique : éditer en riche et voir le Markdown reformatté intégralement (indentations changées, lignes vides supprimées, `##` convertis en soulignements). Milkdown (11k+ stars, ProseMirror + remark) résout ce problème avec un round-trip byte-for-byte.
|
||||
|
||||
**En tant qu'utilisateur**, je veux que mes fichiers Markdown restent intacts quand je les édite en mode visuel — pas de diff parasite sur chaque modification.
|
||||
|
||||
### 1. Évaluation technique Milkdown
|
||||
- Installer `@milkdown/core` + `@milkdown/preset-commonmark` + `@milkdown/preset-gfm`
|
||||
- Benchmarker le round-trip : ouvrir un .md, éditer un paragraphe, sauvegarder, vérifier que seul ce paragraphe change dans le diff
|
||||
- Comparer avec la solution actuelle (TipTap HTML storage) pour les notes markdown
|
||||
- **Référence :** "Human Markdown" VSCode extension (Milkdown + byte-for-byte tests)
|
||||
|
||||
### 2. Mode d'édition dual (si Milkdown adopté)
|
||||
- Toggle dans la toolbar : mode Visuel (WYSIWYG) / mode Brut (CodeMirror)
|
||||
- Transition en <100ms, même position de scroll
|
||||
- Le mode Visuel affiche le rendu live (titres, listes, tables, images, checkboxes cliquables)
|
||||
- Le mode Brut affiche le Markdown source avec coloration syntaxique
|
||||
- **Inspiration :** "Human Markdown" — Cmd+Shift+V pour basculer
|
||||
|
||||
### 3. Intégration avec les notes existantes
|
||||
- Notes type `richtext` : inchangé (stockage HTML TipTap)
|
||||
- Notes type `markdown` : mode dual avec Milkdown
|
||||
- Détection automatique du type à l'ouverture
|
||||
- Conversion possible : `richtext` -> `markdown` (export) et `markdown` -> `richtext` (import)
|
||||
|
||||
### 4. Support GFM complet
|
||||
- Tables Markdown rendues comme de vrais tableaux éditables
|
||||
- Task lists avec checkboxes cliquables
|
||||
- Footnotes rendues inline
|
||||
- Frontmatter YAML en carte collapsible en haut de document
|
||||
- **Inspiration :** "Human Markdown" — GFM complet, Shiki pour le code
|
||||
|
||||
Reference in New Issue
Block a user