Markdown

Renders Markdown headings, lists, tables, quotes and syntax-highlighted code at conversation scale.

import { Markdown } from "@usefragments/ui";Source

Preview

<Markdown content={`# Hello World

This is a paragraph with **bold text** and *italic text*.

Here is some \`inline code\` within a sentence.

Usage

Use when

  • Rendering an LLM reply
  • Showing text a user wrote in Markdown
  • Docs or readme content inside the app

Avoid when

  • The string has no formatting (use Text)
  • The user needs to edit it (use an editor)

Implementation notes

  • react-markdown and remark-gfm are peer dependencies; install both
  • The parser loads on demand, so the first frame is plain text; call Markdown.preload() at startup to skip it
  • For server-rendered pages (docs, a blog), import react-markdown and remark-gfm and pass them as parser, so the HTML is parsed before any script runs
  • Without react-markdown installed it degrades to plain paragraphs
  • Body reads 12 on 18 with compact headings, sized for replies and side panels
  • Fenced code renders through CodeBlock, with copy and highlighting
  • Set streaming while an assistant reply arrives; it never reflows what is already shown
  • components overrides how any element renders, including the built-in fence and table
  • react-markdown sanitises the content for you

Installation

pnpm add @usefragments/ui

Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Additional packages

  • react-markdown — Optional — parses markdown; without it content renders as plain paragraphs.
  • remark-gfm — Optional — adds GitHub-flavored markdown (tables, strikethrough, task lists).
pnpm add react-markdown remark-gfm

Anatomy

Import Markdown once, then compose its parts with dot notation.

  • Markdown.preload

Examples

GFM Table

remark-gfm adds tables and checkbox items on top of the basics.

<Markdown content={`## Data Overview

| Feature    | Status    | Priority |
|------------|-----------|----------|
| Markdown   | Done      | High     |
| Tables     | Done      | Medium   |

Code Block

Fenced blocks get the same code surface as CodeBlock.

<Markdown content={`## Code Example

Here is a JavaScript function:

```js
function greet(name) {

Mixed Content

A realistic document — the worst case worth checking.

<Markdown content={`# Project Update

## Summary

The project is progressing well. Here are the **key highlights**:

Streaming

An assistant reply as it arrives; the open fence shows as code.

const partialReply = "## Summary\n\nTwo files need updated imports…";

<Markdown content={partialReply} streaming />

API reference

Component props
Prop
Type
Default
Description
classNamestring | undefinedNot setAdditional CSS class name
componentsMarkdownComponentMap | undefinedNot setOverride map for markdown element components (e.g., { h1: MyHeading }). Accepts custom renderer component signatures used by react-markdown
contentRequiredstringNot setMarkdown string to render
parserMarkdownParser | undefinedNot setThe parser, imported by the app: { ReactMarkdown, remarkGfm }. The first render is then parsed, so server rendering sends real headings and links
streamingboolean | undefinedfalseThe text is still arriving: an open fence is closed for display, a still caret follows the last block, and the region is busy

Accessibility

  • Output is real headings, lists and tables
  • Wide tables scroll in a named, focusable region
  • Links render as underlined anchors; images keep their alt text
  • A streaming reply sets aria-busy until it completes
  • TextalternativeUse Text for plain, non-markdown text
  • CodeBlockcomplementaryCodeBlock can be used via components prop for syntax highlighting
  • MessageparentMessage wraps Markdown when markdown prop is true

Next steps