Rich Text Editor
Tiptap-based rich text editor with a toolbar for formatting, alignment, lists, and tables.
Basic usage
Use with zaf to embed in a block or form schema:
import { RichTextEditor } from '@repo/cms'
import { zaf } from '@repo/form'
import { z } from 'zod'
const schema = z.object({
content: zaf(RichTextEditor.schema, { component: RichTextEditor.Root }),
})
The editor stores content as Tiptap JSONContent -- an array of node objects.
Schema
RichTextEditor.schema validates that content has at least one node:
// z.object({ content: z.array(z.any()).min(1) }).passthrough()
import { RichTextEditor } from '@repo/cms'
const editorSchema = RichTextEditor.schema
Tiptap extensions
RichTextEditor.tiptapExtensions is the default extension set:
| Extension | Capability |
|---|---|
| StarterKit | Bold, italic, headings, paragraphs, lists, code, blockquote |
| TextAlign | Left, center, right alignment on headings and paragraphs |
| Underline | Underline formatting |
| Table | Resizable tables |
| TableCell | Table cell support |
| TableHeader | Table header cells |
| TableRow | Table rows |
Toolbar
The editor toolbar includes:
- Text type selector (Paragraph, H1, H2, H3)
- Bold, Italic, Underline
- Undo / Redo
- Alignment (left, center, right)
- Bullet list / Ordered list
- Table controls (insert, add/remove rows and columns, toggle header)
ActionButton
RichTextEditor.ActionButton is the toolbar button component used internally. It accepts an icon, active state, and standard button props:
<script lang="ts">
import { RichTextEditor } from '@repo/cms'
</script>
<RichTextEditor.ActionButton
active={editorState.bold}
onclick={() => editor?.chain().focus().toggleBold().run()}
icon={BoldIcon}
/>
Integration with zaf
The editor works as a custom zaf component. In a form, it auto-renders as a rich text field:
const blogSchema = z.object({
title: z.string(),
body: zaf(RichTextEditor.schema, { component: RichTextEditor.Root }),
})
The value binds to JSONContent -- the editor reads it on mount and writes back on every change.