MarkdownEditor
A plain-text Markdown editor with a formatting toolbar, Ctrl/⌘ shortcuts and a Write / Preview / Split view rendered in Nasaq typography, controlled or uncontrolled, with a hidden input for form posts.
Code
import { MarkdownEditor } from "@fadymondy/nasaq/web";import { useState } from "react";export function Description() { const [value, setValue] = useState("## Notes\n\nWrite **here**."); return <MarkdownEditor value={value} onValueChange={setValue} defaultView="split" aria-label="Description" />;}Editors · beta
Live examples and controls: MarkdownEditor in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/markdown-editor.jsonA textarea with a toolbar and a live preview. The value is Markdown text, so you store and diff it as is.
When to use
- Descriptions, comments, release notes and docs where people know or tolerate Markdown.
- When you need the source text, not HTML.
When not to use
- Writers who expect a word processor: use
RichTextEditor. - Showing Markdown only: use
Markdown. - A short single-line field: use
Input.
Import
import { MarkdownEditor } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
import { MarkdownEditor } from "@fadymondy/nasaq/web";
import { useState } from "react";
export function Description() {
const [value, setValue] = useState("## Notes\n\nWrite **here**.");
return <MarkdownEditor value={value} onValueChange={setValue} defaultView="split" aria-label="Description" />;
}Anatomy
MarkdownEditor data-slot="markdown-editor", data-view="write|preview|split"
├─ toolbar (role="toolbar") bold, italic, headings, lists, task list, quote, link, code, code block
├─ ToggleGroup Write · Preview · Split (Split from md up)
├─ textarea monospace, dir="auto"
├─ preview data-slot="markdown-editor-preview", <Markdown>
└─ input type="hidden" when `name` is setAPI
MarkdownEditor: every div prop except onChange and defaultValue, plus:
| Prop | Type | Default | Description |
|---|---|---|---|
value / defaultValue | string | "" | Controlled or initial Markdown. |
onValueChange | (value) => void | Every edit, including toolbar actions. | |
view / defaultView | "write" | "preview" | "split" | "write" | Controlled or initial view. |
onViewChange | (view) => void | ||
placeholder | string | localised | |
rows | number | 10 | Height of the text area. |
disabled | boolean | false | |
name | string | Adds a hidden input with the value for form posts. | |
aria-label | string | "Write" | Name of the text area when there is no visible label. |
labels | Partial<MarkdownEditorLabels> | Override any string. |
Shortcuts: Ctrl/⌘+B bold, Ctrl/⌘+I italic, Ctrl/⌘+K link. Toolbar actions wrap the selection, or insert a placeholder, and keep it selected.
Accessibility
- The toolbar is labelled and
aria-controlsthe text area; every icon button has a name and a tooltip. - Toolbar buttons keep focus and the selection in the text area.
- The preview is
aria-live="polite".
RTL & i18n
- English and Arabic strings follow the Nasaq locale. The text area uses
dir="auto", so Arabic and English lines each read the right way; Split puts Write at the inline start.
Styling & tokens
Cardsurface,rounded-card, mono text area, preview inMarkdowntypography. Target[data-slot="markdown-editor"].
Do / Don't
- Do sanitise Markdown on the server before rendering it elsewhere.
- Do start in Split on wide screens for people new to Markdown.
- Don't use it for chat input; Enter makes a new line here.
Related
Lab
https://docs.nasaqui.com/?path=/docs/components-editors-markdown-editor--docs
LandingPageEditor
Section-based landing page editor with an outline (add, reorder, hide, duplicate, delete), a live preview at desktop or phone width and forms for hero, features, FAQ, call to action and text sections plus page address, search fields and direction.
RichMarkdown
Markdown with sortable and filterable tables, code blocks with line numbers and download, and a frontmatter table.