Skip to main content

Text editor

Package: @zuilib/text-editor · 0.11.1

A markdown editor for React, built on Lexical.

This is the first composite in ZUI: a large component built entirely on the token contract. It exists because an editor is the most commonly rebuilt piece of complex UI (tables, code highlighting, diagrams, outline) and the one that most benefits from being built once and themed per product.

The goal is a markdown editor of the standard people now expect from writing tools, in your app with minimal effort. One component, one controlled string, plain markdown out. Tables, diagrams, highlighted code, an outline and section folding work without setup. When the defaults do not fit, every part is replaceable: the toolbar is composable, the editor is exposed through a headless hook, and the transformers and nodes are exported for a Lexical editor of your own. It reads the same tokens as every other ZUI package; a theme applies to it with no editor-specific overrides; the examples on these pages are the real editor.

Features

  • Three modes driven by one controlled value string: rich WYSIWYG (edit-md), raw markdown (edit-raw), read-only render (view)
  • Markdown shortcuts while typing: headings, lists, checklists, blockquotes, links, fenced code, tables
  • Tables: GFM pipe tables edited in place; rows and columns added or removed from hover rails or the keyboard; per-table width and density
  • Code blocks highlighted by the package's own lexer (15 grammars, no Prism / highlight.js / Shiki in your bundle) with themeable colours
  • Diagrams: an embedded drawing canvas with eight box shapes, bound connectors that follow their boxes, auto-routed elbows, multi-select, colour presets, dark mode and Mermaid export. Generators (LLMs, scripts) write a coordinate-free ```diagram skeleton that the editor lays out
  • Text measure and block width: an opt-in readable text column; each table and diagram picks full, text or content width
  • Outline sidebar with click-to-scroll and current-section highlight; section folding under any heading, view-layer only
  • Toolbar with inline formatting and insert buttons; extend it, move it, or replace it with your own UI through a headless hook
  • YAML frontmatter block support (--- at the top)

Everything round-trips through the markdown string: tables as GFM, diagrams as ```drawing fenced JSON, frontmatter as --- blocks, table settings as one HTML comment above the table. A document written in the editor opens in any other markdown tool.

Installation

pnpm add @zuilib/text-editor @zuilib/tokens \
lexical @lexical/react @lexical/markdown @lexical/rich-text \
@lexical/code @lexical/list @lexical/link @lexical/table @lexical/utils

All lexical / @lexical/* packages are peer dependencies at ^0.35.0; react / react-dom at ^18 || ^19. @zuilib/tokens is an optional peer: without it the editor's chrome falls back to built-in defaults (see Theming).

Quick start

import { useState } from 'react'
import '@zuilib/tokens/styles.css'
import '@zuilib/text-editor/styles.css'
import { MarkdownEditor } from '@zuilib/text-editor'

function Notes() {
const [value, setValue] = useState('# Hello\n\n- [ ] Try checklists')
return <MarkdownEditor value={value} onChange={setValue} outline />
}

The component is controlled: pass value and persist what onChange emits. The emitted string is always plain markdown. Every example on these pages is the real component; Markdown shows the string it emits:

Loading editor

Styles

Load both stylesheets once in your app layout. Document content (headings, lists, inline code) is styled with Tailwind utility classes, so a Tailwind v4 host must scan the package for them to be generated:

@import "@zuilib/tokens/styles.css";
@source "../node_modules/@zuilib/text-editor/dist";
@import "@zuilib/text-editor/styles.css";

Dark mode is the ZUI convention: a dark class on <html>.

Guide

PageCovers
EditorProps, modes, the controlled value, outline and folding, shortcuts, form integration
ToolbarDefault toolbar, extending it, compound components, the headless useMarkdownEditor() hook
TablesGFM round-trip, rows and columns, keyboard, density, settings markers
LayoutText measure and block width (full / text / content)
Code blocksBuilt-in languages, colours, registering a grammar
DiagramsThe drawing canvas, the ```diagram skeleton, the ```drawing format, Mermaid, ink style
ThemingCSS entry points, dark mode, block classes, custom properties
AI authoringGenerating documents and diagrams programmatically
APIEvery export
ChangelogVersion history