Markdown

Du Markdown conçu pour les réponses d’IA. Il s’affiche en streaming de façon fluide et ne montre jamais de syntaxe à moitié saisie, avec des titres que l’on peut lier, des tableaux copiables en Markdown ou CSV, des callouts GitHub, des listes de tâches, des notes de bas de page, des images, des citations en ligne et des blocs de code complets.

Les modèles répondent en Markdown, et l’écrivent un token à la fois. Un moteur de rendu simple fait clignoter des astérisques bruts, des tableaux à moitié construits et des blocs de code non fermés pendant le streaming. Markdown complète la syntaxe inachevée au fur et à mesure et cadence le texte comme le block Streaming, si bien que la mise en forme apparaît sur place.

Chaque élément est construit à partir du reste de HextaUI. Les blocs de code deviennent des Code Blocks, les callouts GitHub comme [!NOTE] utilisent Alert, les listes de tâches utilisent des Checkboxes en lecture seule, et les tableaux défilent latéralement avec un menu pour les copier en Markdown ou en CSV. Passez sources et [1] devient une chip de citation, tandis que les marques à l’intérieur du code sont laissées telles quelles.

Les titres reçoivent des ids tirés de leur texte, avec une icône de lien facultative pour les partager. Les images se chargent paresseusement avec un placeholder et une légende, les notes de bas de page renvoient vers leur marque, les liens externes s’ouvrent dans un nouvel onglet et le disent, et le sens du texte est détecté par bloc. Cela convient aussi bien aux README et aux journaux de modifications qu’aux réponses en streaming.

  1. Ajouter le registre Pro à components.json

    components.json
    {
      "registries": {
        "@hextaui-pro": {
          "url": "https://hextaui.com/r/pro/{name}.json",
          "headers": {
            "Authorization": "Bearer ${HEXTAUI_PRO_TOKEN}"
          }
        }
      }
    }
  2. Ajouter votre token

    Créez un token sur votre page de compte et placez-le dans .env.local sous le nom HEXTAUI_PRO_TOKEN.

  3. Ajouter le block

    pnpm dlx shadcn@latest add @hextaui-pro/markdown

Avec AI SDK

Affichez chaque part de texte d’un message useChat, avec les parts source-url comme sources. L’état de la part indique à Markdown quand le modèle écrit encore.

"use client"

import type { UIMessage } from "ai"

import { Markdown } from "@/components/blocks/markdown/markdown"

export function AssistantMessage({ message }: { message: UIMessage }) {
  const sources = message.parts.flatMap((part) =>
    part.type === "source-url"
      ? [{ id: part.sourceId, url: part.url, title: part.title ?? part.url }]
      : []
  )

  return message.parts.map((part, index) =>
    part.type === "text" ? (
      <Markdown
        key={index}
        text={part.text}
        streaming={part.state === "streaming"}
        sources={sources}
      />
    ) : null
  )
}

Contenu statique

Passez une chaîne en children pour des README, journaux de modifications ou réponses enregistrées. Définissez anchors pour donner aux titres un lien partageable.

import { Markdown } from "@/components/blocks/markdown/markdown"

const changelog = `## 2.4.0

> [!NOTE]
> Requires React 19.

- [x] Faster cold starts
- [x] Copy tables as CSV
- [ ] Offline mode`

export function Changelog() {
  return <Markdown anchors size="base">{changelog}</Markdown>
}

Anatomie

Les parties à composer, de l’extérieur vers l’intérieur.

PartieDescription
MarkdownLe moteur de rendu. Prend une chaîne et gère la cadence, l’analyse et chaque élément.
MarkdownTableUn tableau défilant avec le menu de copie.
MarkdownAlertUn callout pour [!NOTE] et les autres types d’alertes GitHub.
MarkdownHeadingUn titre avec un id et un lien d’ancre facultatif.
MarkdownImageUne image avec des états de chargement, d’erreur et de légende.
PropTypePar défaut
textLe Markdown jusqu’ici. Vous pouvez le passer en children à la place.
string–
streamingCadence le texte, affiche le curseur et complète la syntaxe inachevée.
booleanfalse
smoothDésactivez la cadence pour afficher le texte exactement comme reçu.
booleantrue
sourcesTransforme [1] en chip pour sources[0], et ainsi de suite. Sans sources, [1] reste du texte brut.
Source[][]
sizeTaille du texte. Utilisez sm dans le chat et base pour les articles.
"sm" | "base""sm"
anchorsAffiche une icône de lien sur les titres.
booleanfalse
componentsRemplacez n’importe quel élément, comme a ou img. Gardez l’objet stable, par exemple en dehors du composant, pour que les blocs ne soient pas remontés.
Components–
classNameClasses pour le wrapper.
string–
ToucheAction
TabParcourt les liens, citations, ancres de titre, menus de copie de tableau et actions de bloc de code dans l’ordre de lecture.
EnterOuvre un lien, ou le menu de copie d’un tableau.
↑↓Passe de Copy as Markdown à Copy as CSV.
  • Le wrapper est marqué aria-busy pendant le streaming, afin que les lecteurs d’écran attendent que le texte se stabilise.
  • Les callouts utilisent role=note avec leur type comme libellé, au lieu de s’annoncer comme des alertes live.
  • Les cases à cocher des listes de tâches sont en lecture seule et ignorées par Tab, donc elles se lisent comme un état plutôt que comme des contrôles.
  • Les liens externes indiquent « opens in a new tab », les chips de citation portent le nom de leur source, et les ancres de titre sont nommées « Link to … ».
  • Les images conservent leur texte alternatif, et les tableaux conservent leurs cellules d’en-tête pour la navigation au lecteur d’écran.
  • Avec réduction des animations, le curseur cesse de pulser et les images apparaissent sans fondu.

Construit avec

Les composants HextaUI gratuits dont Markdown est constitué. Chacun s’installe séparément.

Code

3 fichiers, ajoutés à components/blocks/markdown.