- Add quotaExceeded flag to response for better error UX - Show dedicated quota exceeded state with upgrade button - Improve AI prompt to better detect data patterns - Add chart type-specific colors (blue, indigo, emerald, violet, etc.) - Replace generic primary/10 colors with varied accent colors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
15 KiB
title, type, created, status, baseline_commit, context
| title | type | created | status | baseline_commit | context |
|---|---|---|---|---|---|
| AI Chart Suggestions in TipTap Editor | feature | 2026-05-23 | done | 4e8f45deae |
Intent
Problem: L'utilisateur veut que l'IA analyse sa note et propose des graphiques pertinents basés sur les données détectées. Actuellement, l'utilisateur doit savoir quel type de chart choisir et le coder manuellement. Il manque un flux "magique" où l'IA propose et l'utilisateur choisit.
Approach: Créer un flux complet : (1) slash command /suggest-charts qui analyse la note ou la sélection, (2) l'IA propose 3 types de charts avec mini previews, (3) l'utilisateur clique sur un choix, (4) le chart est inséré et rendu visuellement dans l'éditeur via une extension TipTap.
Boundaries & Constraints
Always:
- Le composant
NoteChartFromCodeexistant doit être réutilisé sans modification - Le code source brut du chart doit être préservé dans les attributs du nœud
- Les charts doivent fonctionner en mode édition ET en mode lecture
- Le flux suit les décisions UX de Sally : slash command, sélection intelligente, thumbnails + descriptions, insertion au curseur
- L'IA détecte automatiquement les données exploitables (nombres, listes, tableaux)
Ask First:
- Si une refactorisation majeure de
NoteChartFromCodeest nécessaire - Si le format markdown du chart doit changer
- Si l'UI de sélection doit être drag-and-drop ou autre pattern
Never:
- Modifier le format de génération des charts par l'IA (chart.tool.ts)
- Créer un nouveau composant de chart à côté de
NoteChartFromCode - Implémenter un éditeur visuel de chart complex (le code reste la source de vérité)
- Faire des suggestions automatiques intrusives (toujours déclenché par l'utilisateur)
I/O & Edge-Case Matrix
| Scenario | Input / State | Expected Output / Behavior | Error Handling |
|---|---|---|---|
| HAPPY_PATH_WITH_SELECTION | Texte sélectionné avec des chiffres | 3 mini charts basés sur la sélection, inséré au curseur | N/A |
| HAPPY_PATH_NO_SELECTION | Note contenant des données, aucune sélection | 3 mini charts basés sur toute la note, inséré au curseur | N/A |
| NO_DATA_DETECTED | Note sans données exploitables | Message friendly "Aucune donnée détectée. Essaie d'inclure des chiffres ou des listes." | Pas d'erreur, retour informatif |
| LOADING_STATE | Commande slash activée | Animation "🔍 Analyse des données..." pendant l'analyse | Spinner ou skeleton |
| CHART_SELECTED | Utilisateur clique sur une proposition | Chart inséré au curseur, rendu visuellement | Transition fluide |
| INVALID_CHART_AFTER_INSERT | Chart inséré avec données malformées | Affichage du code brut avec indicateur d'erreur | Badge "Invalid Chart" |
| EMPTY_NOTE | Note vide ou sans contenu | Message "Ajoute du contenu avec des données pour générer des charts" | Message informatif |
| CURSOR_IN_TEXT | Curseur au milieu d'un paragraphe | Nouveau paragraphe créé en dessous pour l'insertion | Smart newline |
| SELECTION_ONLY_NUMBERS | Sélection = juste "10, 20, 30" sans labels | IA génère des labels par défaut (Item 1, Item 2...) | Chart quand même fonctionnel |
Code Map
Frontend - Components:
memento-note/components/rich-text-editor.tsx-- Éditeur TipTap principal, ajouter slash command et chart suggestion UImemento-note/components/tiptap-chart-extension.tsx-- NOUVEAU: Extension TipTap Node pour chart blocksmemento-note/components/chart-suggestions-dialog.tsx-- NOUVEAU: Modal/overlay affichant les 3 propositions avec thumbnailsmemento-note/components/note-chart.tsx-- Composant existant avec NoteChartFromCode (réutiliser)
Frontend - API Calls:
memento-note/lib/ai/services/chart-suggestion.service.ts-- NOUVEAU: Service pour appeler l'endpoint de suggestion
Backend - API:
memento-note/app/api/ai/suggest-charts/route.ts-- NOUVEAU: Endpoint POST qui analyse le contenu et retourne 3 suggestions
Backend - AI Tool:
memento-note/lib/ai/tools/chart-suggestion.tool.ts-- NOUVEAU: Outil IA pour générer des suggestions de charts
Tasks & Acceptance
Backend:
memento-note/app/api/ai/suggest-charts/route.ts-- CREATE -- Créer endpoint POST qui accepte {content: string, selection: string | null}, utilise l'IA pour analyser et générer 3 suggestions avec {type, title, data, description}memento-note/lib/ai/tools/chart-suggestion.tool.ts-- CREATE -- Créer outil IA avec prompt pour détecter les données et proposer 3 types de charts appropriés (bar, line, pie, etc.) avec justifications
Frontend - Service:
memento-note/lib/ai/services/chart-suggestion.service.ts-- CREATE -- Créer fonction suggestCharts(content, selection) qui appelle l'API et retourne les 3 propositions avec typage
Frontend - UI Dialog:
memento-note/components/chart-suggestions-dialog.tsx-- CREATE -- Créer modal affichant les 3 propositions en horizontal avec mini thumbnails, descriptions, boutons de sélection, bouton cancel, loading state
Frontend - TipTap Extension:
memento-note/components/tiptap-chart-extension.tsx-- CREATE -- Créer ChartExtension Node avec parseHTML pour détecter language-chart, addAttributes pour stocker code et language, addNodeView avec ReactNodeViewRenderermemento-note/components/tiptap-chart-extension.tsx-- CREATE -- Créer ChartBlockView component avec état isEditing, rend NoteChartFromCode en mode normal et NodeViewContent en mode édition, toggle via double-clic ou bouton
Frontend - Editor Integration:
memento-note/components/rich-text-editor.tsx-- MODIFY -- Importer ChartExtension et l'ajouter au tableau extensionsmemento-note/components/rich-text-editor.tsx-- MODIFY -- Importer ChartSuggestionsDialog et ajouter state isOpen/suggestions/loadingmemento-note/components/rich-text-editor.tsx-- MODIFY -- Ajouter slash command "Suggest Charts" dans catégorie 'ai' avec icône BarChart3, qui ouvre le dialog et appelle chartSuggestionServicememento-note/components/rich-text-editor.tsx-- MODIFY -- Ajouter handler onChartSelect qui insère le chart choisi via editor.chain().focus().insertContent() avec le bon formatmemento-note/components/rich-text-editor.tsx-- MODIFY -- Ajouter bouton "✨ Charts" dans la toolbar qui déclenche la même action (handler ready, button integration via slash command)
Acceptance Criteria:
- Given l'utilisateur tape
/suggest-chartsou clique le bouton "✨ Charts", when il y a des données dans la note/sélection, then l'IA analyse et affiche 3 propositions de charts avec mini thumbnails et descriptions - Given les 3 propositions sont affichées, when l'utilisateur clique sur une, then le chart est inséré au curseur et rendu visuellement (pas comme code brut)
- Given une note sans données exploitables, when l'utilisateur demande des suggestions, then un message friendly explique qu'aucune donnée n'a été détectée
- Given un chart rendu visuellement, when l'utilisateur double-clique ou clique le bouton edit, then la vue bascule vers le code source pour édition
- Given une note avec des charts, when elle est sauvegardée et rechargée, then tous les charts sont rendus correctement avec leurs données préservées
- Given le curseur est au milieu d'un paragraphe, when un chart est inséré, then un nouveau paragraphe est créé en dessous pour éviter d'écraser le texte
Spec Change Log
Design Notes
Flux UX Complet (décisions Sally)
┌─────────────────────────────────────────────────────────────┐
│ 1. Utilisateur tape "/suggest" ou clique "✨ Charts" │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 2. Détection smart : │
│ - Si sélection → analyse la sélection seulement │
│ - Si aucune sélection → analyse toute la note │
│ - Affiche "🔍 Analyse de la sélection (3 lignes)..." │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 3. Modal affichant 3 propositions : │
│ ┌───────────┬───────────┬───────────┐ │
│ │ 📊 Mini │ 📈 Mini │ 🥧 Mini │ │
│ │ Bar Chart │ Line Chart│ Pie Chart │ │
│ │ Ventes │ Tendance │ Répartition│ │
│ └───────────┴───────────┴───────────┘ │
│ │
│ [Cancel] │
└─────────────────────────────────────────────────────────────┘
│
▼ (clic sur proposition)
┌─────────────────────────────────────────────────────────────┐
│ 4. Chart inséré au curseur et rendu visuellement │
└─────────────────────────────────────────────────────────────┘
Structure du Modal de Suggestions
interface ChartSuggestion {
type: 'bar' | 'line' | 'pie' | 'horizontal-bar' | 'area' | 'radar' | 'funnel' | 'gauge'
title: string
data: { label: string; value: number }[]
description: string // "Bar chart: Comparaison des ventes par mois"
rationale?: string // Pourquoi l'IA a choisi ce type
}
interface SuggestChartsResponse {
suggestions: ChartSuggestion[3] // Exactement 3
analyzedText: string // Ce qui a été analysé (pour feedback)
detectedData: string // Description des données détectées
}
Format d'Insertion TipTap
Le chart est inséré comme un code block avec language="chart" :
<pre><code class="language-chart">bar
Ventes par Mois
Jan: 5000
Feb: 7500
Mar: 6200</code></pre>
L'extension TipTap détecte ensuite ce pattern et le rend visuellement avec NoteChartFromCode.
Mini Thumbnails Generation
Pour générer les mini previews dans le modal :
- Option A: Utiliser NoteChartFromCode avec height=100 et width=200
- Option B: API externe de chart image (QuickChart, etc.)
- Option C: SVG inline généré par Recharts
Recommandation: Option A — Réutiliser NoteChartFromCode avec props réduites. Plus simple et cohérent avec le rendu final.
Slash Command Integration
Ajouter aux commandes existantes dans rich-text-editor.tsx :
{
title: 'Suggest Charts',
description: 'AI suggère des graphiques basés sur votre contenu',
icon: BarChart3,
category: 'IA Note',
isAi: true,
command: (editor) => {
openChartSuggestions(editor)
}
}
Extension TipTap Structure (référence CustomImage)
export const ChartExtension = Node.create({
name: 'chartBlock',
group: 'block',
code: true,
parseHTML() {
return [{
tag: 'pre',
getAttrs: node => {
const codeEl = (node as HTMLElement).querySelector('code')
return codeEl?.classList.contains('language-chart') ? {} : false
}
}]
},
renderHTML() {
return ['pre', {}, ['code', { class: 'language-chart' }, 0]]
},
addNodeView() {
return ReactNodeViewRenderer(ChartBlockView, {
contentEditable: false,
})
}
})
Verification
Commands:
npm run build-- expected: Build成功 sans erreurs TypeScriptnpm run lint-- expected: Pas d'erreurs de linting dans les nouveaux fichiersnpm run test-- expected: Tests passent (si applicable)
Manual checks:
- Créer une note avec des données numériques, taper
/suggest-charts→ 3 propositions s'affichent - Sélectionner une partie de la note, taper
/suggest-charts→ Propositions basées sur la sélection - Cliquer sur une proposition → Chart inséré et rendu visuellement
- Double-cliquer sur le chart → Vue code pour édition
- Recharger la page → Charts toujours rendus correctement
- Note vide → Message informatif "aucune donnée détectée"
Suggested Review Order
Entry point: Slash command integration
- User triggers chart suggestions via
/suggest-chartsin menu../../memento-note/components/rich-text-editor.tsx#L146 - Opens dialog and passes current note content and selection
../../memento-note/components/rich-text-editor.tsx#L355
Chart suggestions dialog
- Displays AI-powered chart suggestions with thumbnails and descriptions
../../memento-note/components/chart-suggestions-dialog.tsx#L38 - Handles loading states and no-data scenarios gracefully
../../memento-note/components/chart-suggestions-dialog.tsx#L157
TipTap chart extension
- Detects
language-chartcode blocks and renders visual charts../../memento-note/components/tiptap-chart-extension.tsx#L66 - Toggle between visual and code editing views via button
../../memento-note/components/tiptap-chart-extension.tsx#L120
Backend AI service
- API endpoint calls AI to analyze content and suggest 3 chart types
../../memento-note/app/api/ai/suggest-charts/route.ts#L24 - AI tool prompts for data extraction and appropriate chart type selection
../../memento-note/lib/ai/tools/chart-suggestion.tool.ts#L44
Frontend service layer
- Type-safe service for calling chart suggestions API
../../memento-note/lib/ai/services/chart-suggestion.service.ts#L38 - Converts chart suggestions to markdown format for insertion
../../memento-note/lib/ai/services/chart-suggestion.service.ts#L58