Files
Momento/_bmad-output/implementation-artifacts/spec-tiptap-chart-extension.md
Antigravity 18ffd76c1e fix(chart): improve error handling and color variety
- 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>
2026-05-23 09:19:52 +00:00

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 NoteChartFromCode existant 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 NoteChartFromCode est 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 UI
  • memento-note/components/tiptap-chart-extension.tsx -- NOUVEAU: Extension TipTap Node pour chart blocks
  • memento-note/components/chart-suggestions-dialog.tsx -- NOUVEAU: Modal/overlay affichant les 3 propositions avec thumbnails
  • memento-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 ReactNodeViewRenderer
  • memento-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 extensions
  • memento-note/components/rich-text-editor.tsx -- MODIFY -- Importer ChartSuggestionsDialog et ajouter state isOpen/suggestions/loading
  • memento-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 chartSuggestionService
  • memento-note/components/rich-text-editor.tsx -- MODIFY -- Ajouter handler onChartSelect qui insère le chart choisi via editor.chain().focus().insertContent() avec le bon format
  • memento-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-charts ou 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 TypeScript
  • npm run lint -- expected: Pas d'erreurs de linting dans les nouveaux fichiers
  • npm 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

Chart suggestions dialog

TipTap chart extension

Backend AI service

Frontend service layer