Skip to Content
⭐️ Leave a star →
ComponentsRichText

Rich Text

A slot-based Markdown editor scaffold built on top of Markdown. It provides a toolbar with selection-wrapping actions, an editor textarea, and a live preview, with edit, preview, and split modes.

Features

Three view modes: edit, preview, and split.
Toolbar actions wrap the current selection or insert text at the caret.
Live Markdown preview powered by a pluggable parser (wrap remark/marked).
Custom render-part overrides forwarded to the Markdown preview.
Controlled or uncontrolled value and mode.
Actions preserve the editor selection — they never steal focus.

Example

Hello

Type markdown on the left, see it rendered on the right.

  • item one
  • item two
import { RichText } from '@wire-ui/react' <RichText.Root defaultMode="split" parse={parse}> <RichText.Toolbar> <RichText.Action wrap="**">B</RichText.Action> <RichText.Action wrap="_">I</RichText.Action> <RichText.Action wrap={['[', '](url)']}>Link</RichText.Action> <RichText.Action insert={'\n- '}>List</RichText.Action> </RichText.Toolbar> <RichText.Editor placeholder="Write some markdown…" /> <RichText.Preview /> </RichText.Root>

Styling

RichText.Root sets data-mode ("edit" / "preview" / "split") so you can lay out the editor and preview differently per mode — for example switching the inner wrapper between one and two columns. Editor and Preview also carry data-mode, and Editor is unmounted in preview mode while Preview is unmounted in edit mode.

<RichText.Root className=" data-[mode=split]:grid-cols-2 "> <RichText.Editor className="font-mono" /> <RichText.Preview /> </RichText.Root>

Using data attributes

RichText.Root, Editor, and Preview all set data-mode reflecting the current view mode.

[data-mode="edit"] { /* editor only */ } [data-mode="preview"] { /* preview only */ } [data-mode="split"] { /* both side by side */ }

Root props

PropTypeDefaultDescription
valuestringControlled Markdown source
defaultValuestring''Initial Markdown source (uncontrolled)
onChange(value: string) => voidCalled when the source changes
mode'edit' | 'preview' | 'split'Controlled view mode
defaultMode'edit' | 'preview' | 'split''edit'Initial view mode (uncontrolled)
onModeChange(mode: RichTextMode) => voidCalled when the view mode changes
parse(content: string) => MarkdownNode[]Parser used by Preview (wrap remark/marked)
componentsMarkdownComponentsRender-part overrides forwarded to the Markdown preview

Action props

PropTypeDefaultDescription
wrapstring | [string, string]Wrap the selection — a single string is used for both sides, or pass [before, after]
insertstringInsert text at the caret

Also accepts all native <button> attributes.

Editor props

Accepts all native <textarea> attributes except value / onChange (managed by Root). Examples: rows, placeholder.

Toolbar / Preview props

Both accept all native <div> attributes. Toolbar renders with role="toolbar". Preview renders the parsed Markdown via the Markdown component.

Data attributes

AttributeElementValues
data-modeRoot, Editor, Preview"edit" / "preview" / "split"

Toolbar sets role="toolbar".

Accessibility

  • The toolbar is exposed as role="toolbar".
  • Action buttons call preventDefault on mousedown so clicking a button never steals the editor’s text selection — the wrap/insert applies to whatever was selected.
Last updated on

MIT License © 2026 wire-ui

Rich Text – Wire UI