Skip to content

Prose Editor <l-prose-editor>

A rich text editor built on Tiptap (ProseMirror). Form-associated — its value is the editor HTML, so it submits inside a <form> like a native field.

html
<l-prose-editor placeholder="Write something…"></l-prose-editor>

The editable area renders in light DOM, so its content styles ship as a separate stylesheet you import once globally. See Importing.

HTML tag<l-prose-editor>
Native HTML
Progressive
Custom
Shadow DOM
Custom Element · Shadow DOM

Options

Basic

The default toolbar covers headings, marks, lists, links, code, an emoji picker and undo/redo. Set initial content with initial-html.

Code
html
<l-prose-editor
  placeholder="Write something…"
  initial-html="<h2>Release notes</h2><p>This editor ships with a <strong>default</strong> toolbar covering headings, marks, lists, links and more.</p><ul><li>Built on Tiptap</li><li>Form-associated</li></ul>"
></l-prose-editor>

Toolbar preset

Set toolbar-preset="minimal" for a compact bold/italic/underline toolbar.

Code
html
<l-prose-editor
  toolbar-preset="minimal"
  placeholder="Bold, italic, underline only…"
></l-prose-editor>

Custom toolbar

Set toolbar to a comma-separated list of commands to build your own layout. Use divider to insert a separator.

Code
html
<l-prose-editor
  toolbar="bold,italic,link,divider,bulletlist,orderedlist,divider,undo,redo"
  placeholder="Custom toolbar…"
></l-prose-editor>

Available commands: heading-1, heading-2, heading-3, bold, italic, underline, strike, highlight, bulletlist, orderedlist, blockquote, code-block, horizontal-rule, link, emoji, attachment, undo, redo, divider.

Toolbar placement

Set toolbar-placement="bottom" to move the toolbar below the content.

Code
html
<l-prose-editor
  toolbar-placement="bottom"
  placeholder="Toolbar sits below the content…"
></l-prose-editor>

Emoji picker data

The emoji toolbar button opens a picker that loads its emoji data from a CDN by default. For an offline or behind-auth app, serve an emojibase-data JSON locally and point emoji-data-source at it.

html
<l-prose-editor emoji-data-source="/emoji/en/data.json"></l-prose-editor>

Examples

Form integration

The editor participates in forms via its name attribute. The submitted value is the HTML string; required blocks submission while empty.

Code
html
<form
  class="flex flex-col items-start gap-4"
  onsubmit="
    event.preventDefault();
    const data = new FormData(event.target);
    alert('description = ' + data.get('description'));
  "
>
  <label class="flex w-full flex-col gap-1">
    <span class="text-sm font-medium">Description</span>
    <l-prose-editor
      name="description"
      required
      toolbar-preset="minimal"
      placeholder="Describe your product…"
    ></l-prose-editor>
  </label>
  <button
    type="submit"
    class="l-button"
    data-variant="primary"
  >
    Submit
  </button>
</form>

Accessibility

Criteria

Toolbar role

The toolbar uses role="toolbar" with an accessible label

WCAG4.1.2
RGAA7.1
Button state

Each toolbar button exposes aria-pressed reflecting whether the mark/format is active

WCAG4.1.2
Button label

Icon-only buttons carry an aria-label and title describing the action

WCAG1.1.1
RGAA1.3
Focus state

Visible focus ring on toolbar buttons for keyboard users

WCAG2.4.7
RGAA10.7
Form validation

When required, an empty editor reports a valueMissing validation message to the form

WCAG3.3.1

Keyboard interactions

Tab
Moves focus into the toolbar, then into the editable content
Ctrl/CmdB
Toggles bold
Ctrl/CmdI
Toggles italic
Ctrl/CmdU
Toggles underline
Ctrl/CmdZ
Undo
Ctrl/CmdShiftZ
Redo
Escape
Closes the emoji picker when open

API reference

Importing

Import the element and the content stylesheet once globally. The stylesheet styles the editable area, which renders in light DOM to avoid contenteditable caret bugs inside shadow trees.

js
import 'luxen-ui/prose-editor';
css
@import 'luxen-ui/css/prose-editor';

Attributes & Properties

editorEditorProperty
The Tiptap editor instance. Available after the first render.
initial-htmlstringProperty
Initial HTML content.
initial-jsonstringProperty
Initial content as a serialized ProseMirror JSON string.
editor-classstringdefault:'prose'Property
Class applied to the .ProseMirror editable element (e.g. for Tailwind Typography prose).
toolbarToolbarCommandName[]default:[]Property
Explicit list of toolbar commands. Overrides toolbar-preset when set.
toolbar-preset'default' | 'minimal'default:'default'Property
Built-in toolbar layout used when toolbar is not set.
toolbar-placement'top' | 'bottom'default:'top'Property
Where the toolbar sits relative to the content.
autofocusbooleandefault:falseProperty
Focus the editor on creation.
placeholderstringProperty
Placeholder shown when the editor is empty.
emoji-data-sourcestringProperty
URL the emoji picker fetches its data from. Point this at a locally served emojibase-data JSON to run fully offline (no CDN). Defaults to the picker's bundled CDN source.
validationTargetHTMLElement | undefinedProperty

Methods

getHTML()stringMethod
Get the current content as an HTML string. Empty paragraph resolves to ''.
getJSON()JSONContentMethod
Get the current content as ProseMirror JSON.
clear()Method
Remove all content.
focus()Method
blur()Method
toggleBold()Method
toggleItalic()Method
toggleUnderline()Method
toggleStrike()Method
toggleHighlight()Method
toggleHeading(level: 1 | 2 | 3)Method
toggleBulletList()Method
toggleOrderedList()Method
toggleBlockquote()Method
toggleCodeBlock()Method
setHorizontalRule()Method
undo()Method
redo()Method
toggleLink()Method
formResetCallback()Method

Events

changeEvent
Fired when the content changes. detail is { html, json }.
add-fileEvent
Fired when the attachment toolbar button is clicked.

Slots

toolbar-startSlot
Content placed before the generated toolbar buttons.
toolbar-endSlot
Content placed after the generated toolbar buttons.

CSS Parts

wrapperPart
The editor frame wrapping the toolbar and content.
toolbarPart
The toolbar row.
toolbar-buttonPart
Any toolbar button.
dividerPart
A toolbar divider.
editorPart
The container around the editable content.

CSS custom properties

--border-colorCustom property
Color of the editor frame border.
--border-widthCustom property
Width of the editor frame border.
--border-radiusCustom property
Corner radius of the editor frame.
--backgroundCustom property
Background color of the editor.
--colorCustom property
Text color of the editor.
--toolbar-backgroundCustom property
Background color of the toolbar.
--toolbar-paddingCustom property
Padding around the toolbar.
--toolbar-gapCustom property
Gap between toolbar buttons.
--toolbar-divider-colorCustom property
Color of toolbar dividers.
--toolbar-button-sizeCustom property
Size of toolbar buttons.
--toolbar-button-radiusCustom property
Corner radius of toolbar buttons.
--toolbar-button-colorCustom property
Icon color of inactive toolbar buttons.
--toolbar-button-color-activeCustom property
Icon color of hovered/active toolbar buttons.
--toolbar-button-background-hoverCustom property
Background of hovered toolbar buttons.
--toolbar-button-background-activeCustom property
Background of active toolbar buttons.
--content-paddingdefault:0.75rem 1remCustom property
Padding inside the editable content region.
--content-min-heightdefault:8remCustom property
Minimum height of the editable content region.
--placeholder-colorCustom property
Placeholder text color.