Headings, lists, inline formatting, links, undo/redo.
Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/rich-text-editor.jsonUsage
Use as a controlled (`value` + `onChange`) or uncontrolled (`defaultValue`) editor.
TSImport
import { RichTextEditor } from "@/components/ui/rich-text-editor";TSExample
import * as React from "react";
import { RichTextEditor } from "@/components/ui/rich-text-editor";
export function Example() {
const [value, setValue] = React.useState("<p>Hello <strong>Squad</strong>.</p>");
return (
<RichTextEditor
value={value}
onChange={setValue}
placeholder="Start writing…"
/>
);
}Composition
Anatomy of the RichTextEditor.
RichTextEditor (TipTap-backed)
├── Toolbar (top or bottom)
│ ├── Headings (H1/H2/H3)
│ ├── Bold / Italic / Underline / Strike / Code
│ ├── Lists (bullet / ordered)
│ ├── Blockquote
│ ├── Link (popover)
│ ├── Undo / Redo
│ ├── Spell-check popover (optional, retext stack lazy-loaded)
│ └── Dictation mic (optional, Web Speech API)
├── EditorContent (contenteditable)
└── Footer (optional character count)Default toolbar
Headings, lists, inline formatting, links, undo/redo.
Headings, lists, inline formatting, links, undo/redo.
Inline markdown (ClickUp-style description)
`RichTextEditorInline` — a flat, borderless variant that takes markdown in and out via `@tiptap/markdown`. There is no fixed toolbar; highlighting text raises a floating BubbleMenu with formatting tools, just like a ClickUp task description. Pass `collapsible` to clip long content to a fixed height with a fade and an Expand/Collapse toggle, like long code blocks. Type `/` at the start of a word for a slash-command palette (headings, lists, quote, code block, divider) — entries gated off via `disabledFeatures` are hidden from it too.
Flat ClickUp-style description — markdown in/out, highlight text for a floating toolbar.
Character limit
Cap content length using the character-count extension.
Enforced via @tiptap/extension-character-count.
Toolbar on bottom
Pin the toolbar below the editable area.
Error state
Pass a string to `error` to show the red outline and an inline message below the editor.
Content is required
With caption
Pass `caption` to render helper copy under the label. Error wins when both are present.
Markdown-style formatting is supported.
With dictation
Pass `dictation` to mount a Web Speech API mic at the end of the toolbar. Chrome/Edge only — the button hides itself in unsupported browsers (Safari, Firefox, mobile WebKit).
Web Speech API mic in the toolbar — Chrome/Edge only; hides itself elsewhere.
With spell check
Pass `spellCheck` to lazily load the retext stack (spelling, repeated words, a/an, redundant acronyms, contractions, smart quotes, double spaces) and surface issues in a popover triggered from a toolbar button. The button shows a red badge with the issue count.
Lazy-loaded retext stack underlines misspellings, repeated words, a/an mistakes, and more. Hover an underline for the message.
Disabled
Read-only editor for display purposes.
API Reference
Props exposed by the RichTextEditor.
RichTextEditor
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled HTML value. Pair with `onChange`. |
defaultValue | string | — | Uncontrolled initial HTML. |
onChange | (html: string) => void | — | Fires whenever the editor content changes. |
placeholder | string | — | Empty-state placeholder text. |
disabled | boolean | false | Render as read-only. |
toolbarPosition | "top" | "bottom" | "top" | Pin the toolbar above or below the editable region. |
maxLength | number | — | Cap content via `@tiptap/extension-character-count`; shows a counter footer. |
error | boolean | string | false | Error state. `true` applies the red outline only; a string also renders the inline message (`text-xs mt-1.5 text-red-500`) below the editor. |
caption | ReactNode | — | Helper copy shown below the editor via FieldHint. Error wins when both are present. |
dictation | boolean | false | Mount a Web Speech API mic at the end of the toolbar. Streams transcribed phrases into the editor at the current cursor. Auto-hides in unsupported browsers (Safari, Firefox, mobile WebKit). |
spellCheck | boolean | false | Run a lazy-loaded retext stack (retext-spell + dictionary-en, retext-repeated-words, retext-indefinite-article, retext-redundant-acronyms, retext-contractions, retext-quotes, retext-sentence-spacing) on the editor's text and surface issues in a toolbar popover with a count badge. Each entry shows the offending word + the retext message in a DescriptionList. |
disabledFeatures | RichTextFeature[] | — | Hide toolbar features, e.g. `["h1", "blockquote", "indent"]`. Features: bold, italic, underline, strike, code, h1, h2, h3, bulletList, orderedList, blockquote, link. |
minHeight | number | — | Minimum editable area height in pixels. |
className | string | — | Override or extend the wrapper classes. |
RichTextEditorInline
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled markdown value. Pair with `onChange`. |
defaultValue | string | — | Uncontrolled initial markdown. |
onChange | (markdown: string) => void | — | Fires with the content serialized back to markdown via `editor.getMarkdown()`. |
placeholder | string | "Add a description…" | Empty-state placeholder text. |
disabled | boolean | false | Render as read-only. |
minHeight | number | 80 | Minimum editable area height in pixels. |
collapsible | boolean | false | Collapse the content to `collapsedHeight` with a fade-out gradient and an Expand overlay button, like collapsible code blocks. The toggle only appears when the content overflows. |
defaultCollapsed | boolean | true | Initial collapsed state for `collapsible`. |
collapsedHeight | number | 160 | Collapsed max-height in pixels. |
collapsedLines | number | — | Collapsed height expressed in text lines (24px each). Takes precedence over `collapsedHeight`. |
autoHeight | boolean | false | Fit the collapsed viewport to the space remaining below the editor in the browser viewport (re-measured on resize). Takes precedence over `collapsedLines`/`collapsedHeight`. |
expandOnFocus | boolean | true | Auto-expand when the editor gains focus (click/typing), like ClickUp descriptions. |
disabledFeatures | RichTextFeature[] | — | Hide toolbar features, e.g. `["h1", "blockquote", "indent"]`. Features: bold, italic, underline, strike, code, h1, h2, h3, bulletList, orderedList, blockquote, link, indent (indent is inline-only). |
className | string | — | Override or extend the wrapper classes. |