Search

Search the site

All components

Markdown Editor

Markdown textarea with formatting toolbar, edit/preview toggle, keyboard shortcuts, and optional character count.

Default
Toolbar formatting, preview toggle, and sample markdown.
1import { MarkdownEditor } from "@/registry/ui/markdown-editor";
2
3const SAMPLE_MARKDOWN = `# Release notes
4
5Ship faster with **bold claims** and _italic nuance_.
6
7## Highlights
8
9- Formatting toolbar inserts Markdown at the cursor
10- Toggle **Preview** to render lists, headings, and code
11- Keyboard shortcuts: \`⌘B\` / \`⌘I\`
12
13\`\`\`ts
14const greeting = "Hello, Markdown";
15console.log(greeting);
16\`\`\`
17
18~~Deprecated API~~ - use the new endpoint instead.
19`;
20
21export function MarkdownEditorDefaultExample() {
22 return (
23 <div className="mx-auto w-full max-w-2xl p-4">
24 <MarkdownEditor defaultValue={SAMPLE_MARKDOWN} />
25 </div>
26 );
27}
With limits
Placeholder, max length, and character count.
0 / 500
1import { MarkdownEditor } from "@/registry/ui/markdown-editor";
2
3export function MarkdownEditorWithLimitsExample() {
4 return (
5 <div className="mx-auto w-full max-w-2xl p-4">
6 <MarkdownEditor
7 placeholder="Describe your feature in Markdown…"
8 maxLength={500}
9 showCharacterCount
10 />
11 </div>
12 );
13}
Controlled
Parent owns value state for forms and persistence.

Parent state: 37 characters

1"use client";
2
3import { useState } from "react";
4import { MarkdownEditor } from "@/registry/ui/markdown-editor";
5
6export function MarkdownEditorControlledExample() {
7 const [value, setValue] = useState("**Controlled** value from the parent.");
8
9 return (
10 <div className="mx-auto flex w-full max-w-2xl flex-col gap-3 p-4">
11 <MarkdownEditor value={value} onChange={setValue} />
12 <p className="text-xs text-muted-foreground">
13 Parent state: {value.length} characters
14 </p>
15 </div>
16 );
17}

Installation & source

Install via the shadcn CLI or copy the registry files manually.

bash
npx shadcn@latest add @tt-ui/markdown-editor

Props

NameTypeDefaultDescription
valuestringundefinedControlled markdown string (pair with onChange).
defaultValuestring""Initial value when uncontrolled.
onChange(value: string) => voidundefinedCalled when markdown content changes.
maxLengthnumberundefinedOptional character limit.
showCharacterCountbooleanfalseShow character count footer.
defaultMode"edit" | "preview""edit"Initial edit or preview mode.