Components
Editors
Each editor variant maps to a different TipTap extension set. All text editors output ProseMirrorJSON.
Editor Variants
Choose the variant that matches your content needs. Each example below is a live editor.
Live Example
An Editable Heading
<Editable.Data key="hero" {data}>
{#snippet children({ text })}
<h1>{@render text('title')}</h1>
{/snippet}
</Editable.Data>Loads only Document, Text, History, and Placeholder. No paragraph wrapping.
Live Example
This is a multiline editor. It supports multiple paragraphs but no formatting marks.
Press Enter to create a new paragraph.
<Editable.Data key="hero" {data}>
{#snippet children({ multiline })}
<div class="text-muted-foreground">
{@render multiline('subtitle')}
</div>
{/snippet}
</Editable.Data>Adds Paragraph to the plain set. Supports multiple paragraphs, no formatting marks.
Live Example
This is a rich text editor. Try adding bold, italic, headings, and more.
<Editable.Data key="post" {data}>
{#snippet children({ rich })}
<article class="prose">
{@render rich('body')}
</article>
{/snippet}
</Editable.Data>Bold, Italic, Underline, Strike, Headings (1-3), Lists, Blockquote, Links, Images, and History.
Live Example
<Editable.Data key="hero" {data}>
{#snippet children({ image })}
<div class="aspect-video overflow-hidden rounded-lg">
{@render image('image', {
maxWidth: 1200,
maxHeight: 675,
quality: 0.85,
aspect: 16 / 9
})}
</div>
{/snippet}
</Editable.Data>Click to upload, drag to pan, scroll to zoom. Exports WebP via OffscreenCanvas. Set aspect to constrain the crop ratio.
Multiple Data Sections
Nest multiple Data components under a single Root. Each gets a unique key and appears in the save
map.
Live Example
Hero Section
First Note
Content of the first note.
Second Note
Content of the second note.
<Editable.Root {editing} onsave={handleSave}>
{#snippet children({ state, save })}
<Editable.Data key="hero" data={hero}>
{#snippet children({ text, image })}
<h1>{@render text('title')}</h1>
{@render image('cover', { maxWidth: 1200, maxHeight: 675, quality: 0.85 })}
{/snippet}
</Editable.Data>
{#each notes as note, i}
<Editable.Data key={`notes-${i}`} data={note}>
{#snippet children({ text, multiline })}
<h3>{@render text('title')}</h3>
<p>{@render multiline('body')}</p>
{/snippet}
</Editable.Data>
{/each}
{/snippet}
</Editable.Root>