Skip to main content

Editor

Edits rich text with formatting, autosave, and a word count.

import { Editor } from "@/fragments/ui";Source

Preview

<Editor placeholder="Start typing your masterpiece here..." />

Installation

npx @usefragments/cli add editor
pnpm add @tiptap/react @tiptap/starter-kit @tiptap/extension-link

Writes src/fragments/ui/components/Editor plus what it imports, the globals stylesheet, and .fragments/registry-lock.json, then prints the packages to add. No account, no key.

Your own registry: publish from Fragments Cloud and add --registry org/name. Connect a workspace.

Anatomy

Editor is a compound: import the root and reach its parts through dot notation.

  • Editor.Toolbar
  • Editor.ToolbarGroup
  • Editor.ToolbarButton
  • Editor.Separator
  • Editor.StatusIndicator
  • Editor.Content
  • Editor.StatusBar
  • Editor.preload

Examples

With Auto-Save and Publish

Save state sits next to the primary action in the toolbar.

<Editor
  placeholder="Start typing your masterpiece here..."
  onValueChange={(v) => console.log(v)}
>
  <Editor.Toolbar>
    <Editor.ToolbarGroup aria-label="Text formatting">

Save Failed

A failed autosave turns the status text red.

<Editor defaultValue="This draft could not be saved.">
  <Editor.Toolbar>
    <Editor.ToolbarGroup aria-label="Text formatting">
      <Editor.ToolbarButton format="bold" />
      <Editor.ToolbarButton format="italic" />
    </Editor.ToolbarGroup>

Disabled

Dimmed and inert, but the text stays readable.

<Editor
  defaultValue="This content cannot be edited."
  disabled
/>

Read Only

Text can be selected and copied, but never changed.

<Editor
  defaultValue="This content is read-only. You can select and copy text but cannot modify it."
  readOnly
/>

Custom Toolbar

Separators split the controls into labelled clusters.

<Editor
  placeholder="Write your blog post..."
  onValueChange={(v) => console.log(v)}
>
  <Editor.Toolbar>
    <Editor.ToolbarGroup aria-label="Basic formatting">

Full Formatting

Every opt-in format switched on, at the tallest preset.

<Editor
  placeholder="Write an article..."
  size="lg"
>
  <Editor.Toolbar>
    <Editor.ToolbarGroup aria-label="History">

With Character Limit

The counter warns near 280 characters and turns red past it.

<Editor
  placeholder="Write a tweet-sized message..."
  maxLength={280}
  size="sm"
  formats={['bold', 'italic', 'link']}
/>

Small Size

A 120px body with a trimmed toolbar, for tight spaces.

<Editor
  placeholder="Quick note..."
  size="sm"
  formats={['bold', 'italic', 'code']}
/>

API

Component props
Prop
Type
Default
Description
childrennodeNot set
valuestringNot setControlled editor value
defaultValuestringDefault value for uncontrolled usage
onValueChangefunctionNot setCalled when content changes
placeholderstringStart typing...Placeholder text shown when empty
disabledbooleanfalseDisable the editor
readOnlybooleanfalseMake the editor read-only
formatsarray["bold", "italic", "strikethrough", "link", "code", "bulletList"]Which format buttons to show in the toolbar
toolbarbooleantrueShow default toolbar
statusBarbooleantrueShow default status bar with word/character counts
onAutoSavefunctionNot setAuto-save callback, called at autoSaveInterval (may be async)
autoSaveIntervalnumber30000Auto-save interval in milliseconds
sizeenumsmmdlgmdEditor size preset: "sm" (120px), "md" (200px), or "lg" (400px)
maxLengthnumberNot setMaximum character count. Shows counter in status bar with warning (90%) and error (over limit) states
toolbarIconsobjectNot setOptional toolbar icon overrides keyed by format/action (e.g. bold, italic, undo). Values can be React nodes or render functions.

Accessibility

  • Toolbar has role="toolbar" with aria-label
  • Format buttons use aria-pressed to indicate active state
  • Action buttons (undo/redo) omit aria-pressed since they are not toggles
  • Status indicator uses aria-live="polite" for save status announcements
  • Keyboard shortcuts match standard text editor conventions (Ctrl+B, Ctrl+I, etc.)
  • Global shortcuts (e.g., Sidebar Ctrl+B) automatically yield when focus is inside the Editor
  • Focus ring appears on the editor container when any child element is focused

Guidance

Use when

  • Blog posts and long-form articles
  • Text that needs formatting controls beside it
  • Drafts that autosave and report a word count
  • Markdown or WYSIWYG authoring

Avoid when

  • Single-line text (use Input)
  • Multi-line with no formatting (use Textarea)
  • Chat or AI prompt input (use Prompt)
  • Code editing (use CodeBlock)
  • PromptsiblingPrompt is for AI/chat input; Editor is for long-form content editing
  • TextareaalternativeUse Textarea for simple multi-line input without formatting toolbar
  • InputalternativeUse Input for single-line text input

Next steps