Files
malio-layer-ui/app/story/input/inputRichText.story.vue
matthieu ea92acff3a fix(input-rich-text) : couleurs de texte et surlignage façon Jira
Ajoute deux boutons à la toolbar avec popover en palette pour
appliquer une couleur de texte ou un surlignage sur la sélection.

- Extensions TipTap : @tiptap/extension-text-style,
  @tiptap/extension-color, @tiptap/extension-highlight (multicolor).
- Palette de 8 couleurs (texte) + 8 pastels (surlignage) + reset.
- Indicateur de couleur active sous l'icône.
- Fermeture du popover sur clic extérieur, Echap, ou clic dans
  l'éditeur.
- Inclut les améliorations rendu/markdown du commit précédent
  (default outputFormat html, normalizeEditorInput, styles deep
  pour h2/h3/p/ul/ol/blockquote).
- Tests : 4 nouveaux cas (15 au total).
- Story et COMPONENTS.md à jour.

Note : les couleurs ne sont pas sérialisables en markdown ; pour
les conserver au save/reload utiliser output-format=\"html\".

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-04 20:01:55 +02:00

222 lines
6.6 KiB
Vue

<template>
<Story title="Input/RichText">
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Simple</h2>
<MalioInputRichText
v-model="simpleValue"
label="Note"
placeholder="Écrire ici…"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Avec contenu initial + hint</h2>
<MalioInputRichText
v-model="hintValue"
label="Description"
hint="Mise en forme via la barre d'outils"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Erreur</h2>
<MalioInputRichText
v-model="errorValue"
label="Compte-rendu"
error="Le compte-rendu doit faire au moins 20 caractères"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Succès</h2>
<MalioInputRichText
v-model="successValue"
label="Compte-rendu"
success="Compte-rendu validé"
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Désactivé</h2>
<MalioInputRichText
v-model="disabledValue"
label="Note"
disabled
/>
</div>
<div class="rounded-lg border p-4">
<h2 class="mb-4 text-xl font-bold">Readonly</h2>
<MalioInputRichText
v-model="readonlyValue"
label="Note"
readonly
/>
</div>
<div class="rounded-lg border p-4 lg:col-span-2">
<h2 class="mb-4 text-xl font-bold">Affichage seul (editable=false)</h2>
<MalioInputRichText
:model-value="readonlyValue"
:editable="false"
/>
</div>
<div class="rounded-lg border p-4 lg:col-span-2">
<h2 class="mb-4 text-xl font-bold">Sortie HTML</h2>
<MalioInputRichText
v-model="htmlValue"
label="Article"
output-format="html"
min-height="200px"
/>
</div>
<div class="rounded-lg border p-4 lg:col-span-2">
<h2 class="mb-4 text-xl font-bold">Couleurs &amp; surlignage</h2>
<MalioInputRichText
v-model="colorValue"
label="Note colorée"
output-format="html"
min-height="180px"
hint="Tester les boutons couleur du texte et surlignage (palettes Jira-like)"
/>
</div>
</div>
</Story>
</template>
<docs lang="md">
# MalioInputRichText
Éditeur de texte riche basé sur **TipTap v3** + **StarterKit** + **tiptap-markdown**.
Sortie en **HTML** (par défaut) ou en **markdown**. Aligné sur le thème Malio
(couleurs `m-*`, icônes `mdi:*`, états error / success / hint).
------------------------------------------------------------------------
## Props détaillées
### id
- Type: `string`
- Description: Identifiant HTML.
- Comportement: Généré automatiquement si non fourni (`malio-input-rich-text-…`).
### label
- Type: `string`
- Description: Label affiché au-dessus de l'éditeur.
- Comportement: Change de couleur selon l'état (focus `m-primary`, error `m-danger`, success `m-success`).
### modelValue
- Type: `string | null | undefined`
- Description: Contenu de l'éditeur (markdown ou HTML selon `outputFormat`).
- Comportement: `v-model` ; sync bidirectionnelle.
### placeholder
- Type: `string`
- Défaut: `''`
- Description: Texte affiché quand l'éditeur est vide.
### minHeight
- Type: `string`
- Défaut: `160px`
- Description: Hauteur minimale de la zone d'édition (CSS valid value).
### editable
- Type: `boolean`
- Défaut: `true`
- Description: `false` → mode affichage seul, **toolbar masquée**, contenu rendu en `prose`.
### disabled
- Type: `boolean`
- Défaut: `false`
- Description: Désactive l'édition et la toolbar (opacité réduite).
### readonly
- Type: `boolean`
- Défaut: `false`
- Description: Lecture seule (toolbar visible mais désactivée, pas de saisie).
### hint / error / success
- Type: `string`
- Description: Messages contextuels affichés sous l'éditeur.
- Priorité: `error` > `success` > `hint`.
### outputFormat
- Type: `'markdown' | 'html'`
- Défaut: `'html'`
- Description: Format émis dans `update:modelValue`.
- `html` : utilise `editor.getHTML()`.
- `markdown` : utilise `tiptap-markdown` (`getMarkdown()`).
### groupClass / labelClass / editorClass
- Type: `string`
- Description: Classes Tailwind additionnelles fusionnées via `twMerge` pour override.
------------------------------------------------------------------------
## Toolbar
Boutons (icônes `mdi:*`) :
- Gras, Italique, Barré
- Titre H2, Titre H3
- Liste à puces, Liste numérotée
- Citation
- Code inline, Bloc de code
- Lien (prompt URL ; vide pour retirer)
- Couleur du texte (palette de 8 swatches + reset)
- Surlignage (palette de 8 swatches + reset)
- Annuler / Rétablir
Les palettes couleur/surlignage s'ouvrent en popover sous leur bouton.
Fermeture : clic sur un swatch, clic en dehors, ou touche **Échap**.
> Les couleurs et surlignages ne sont **pas persistés en markdown** (spec Markdown ne couvre pas la couleur). Pour préserver les couleurs au save/reload, utiliser `output-format="html"`.
------------------------------------------------------------------------
## Accessibilité
- Le label est lié à la zone d'édition via `for` / `id`.
- `aria-invalid="true"` sur la zone d'édition en cas d'erreur.
- `aria-describedby` référence le message d'erreur / succès / hint.
- Boutons toolbar : `aria-pressed` reflète l'état actif, `aria-label` pour l'usage screen-reader.
------------------------------------------------------------------------
## Events
### update:modelValue
- Émis à chaque modification du contenu.
- Payload : `string` (markdown ou HTML selon `outputFormat`).
</docs>
<script setup lang="ts">
import {ref} from 'vue'
import MalioInputRichText from '../../components/malio/input/InputRichText.vue'
const simpleValue = ref('')
const hintValue = ref('## Titre\n\nUn paragraphe avec du **gras**, de l\'*italique* et un [lien](https://malio.fr).')
const errorValue = ref('Trop court')
const successValue = ref('Tout est bon de mon côté.')
const disabledValue = ref('Contenu indisponible.')
const readonlyValue = ref('## Compte-rendu\n\n- Point 1\n- Point 2\n\n> Citation importante')
const htmlValue = ref('<p>Contenu <strong>riche</strong>.</p>')
const colorValue = ref('<p>Sélectionner du texte puis utiliser les boutons <span style="color: #bf2600">couleur</span> ou <mark data-color="#fff0b3" style="background-color: #fff0b3">surlignage</mark>.</p>')
</script>