Lumeo

Rich Text Editor

A fully-featured WYSIWYG editor built on TipTap/ProseMirror. Supports mentions, slash commands, tables, code blocks, task lists, AI actions, image upload, and Word import — all wired through Blazor parameters.

Installation

dotnet add package Lumeo.Editor

One-time app setup (AddLumeo(), CSS & JS) is covered in the installation guide.

Usage

@using Lumeo

<RichTextEditor />

When to Use

  • Content authoring surfaces — blog posts, knowledge-base articles, product descriptions
  • Long-form fields that benefit from headings, lists, quotes, links, and tables
  • Comment or reply surfaces where users expect bold, italic, mentions, and emoji
  • Document editors that need Word import, AI writing assistance, or collaborative slash commands
  • Anywhere you currently use a Textarea but want structured HTML output

Minimal — Bold, Italic, Link

Standard (default) — Headings, marks, lists, link, undo/redo

Full — Standard + tables, image, code block, AI menu, Word import

None — Toolbar hidden; bubble menu and keyboard shortcuts still active

Markdown shortcuts work too — try '**bold**' or '# Heading'.

Read-only — content is selectable but not editable

Disabled — dimmed and non-interactive

Plain-text character limit: 500. The editor scrolls internally when content overflows 260 px.

Keyboard Shortcuts

Shortcut Action
Ctrl / ⌘ + BBold
Ctrl / ⌘ + IItalic
Ctrl / ⌘ + UUnderline
Ctrl / ⌘ + Shift + XStrikethrough
Ctrl / ⌘ + ZUndo
Ctrl / ⌘ + Shift + ZRedo
Ctrl / ⌘ + Alt + 1 – 3Heading 1 / 2 / 3
/ (on a new line)Open slash-command palette
@ # $Open the corresponding trigger dropdown
**text**Bold (markdown shortcut)
# text (space)Heading 1 (markdown shortcut)
- or * (space)Bullet list (markdown shortcut)
[ ] (space)Task list item (markdown shortcut)

API Reference

RichTextEditor

Property Type Default Description
Valuestring?nullCurrent HTML content. Two-way bindable via @bind-Value.
ValueChangedEventCallback<string?>Fired on every document change. Carries the serialised HTML.
Placeholderstring"Start writing…"Placeholder shown when the editor is empty.
ToolbarEditorToolbarPresetStandardToolbar density. None hides it; Minimal = Bold/Italic/Link; Standard = headings + marks + lists + undo/redo; Full adds tables, image, code block, AI menu, Word import.
MinHeightint180Minimum editor height in pixels.
MaxHeightint?nullOptional maximum height in pixels. When set, the content area scrolls internally beyond this height.
DisabledboolfalseDisables editing and dims the toolbar.
ReadOnlyboolfalsePrevents edits but keeps content selectable (no dimming).
RequiredboolfalseMarks the field as required; sets aria-required on the root element.
InvalidboolfalseShows a destructive ring and sets aria-invalid. Also driven automatically when nested inside a <FormField> with an error.
ErrorTextstring?nullError message rendered below the editor when Invalid is true (only when not inside a FormField).
HelperTextstring?nullHelper text rendered below the editor when there is no error (only when not inside a FormField).
Labelstring?nullInline label rendered above the editor (only when not inside a FormField).
Namestring?nullHTML name attribute, useful for form identification.
TriggersIReadOnlyList<EditorTrigger>?nullOne or more trigger characters (e.g. @, #, $). Each trigger provides an async ItemSource callback.
EnableSlashCommandbooltrueEnables the built-in / command palette (Notion-style). Supply a custom / trigger to override the default commands.
EnableTablesbooltrueEnables the TipTap Table extension.
EnableCodeBlockbooltrueEnables syntax-highlighted code blocks.
EnableImagesbooltrueEnables image upload/paste. Falls back to base64 when OnImageRequested is null.
EnableTaskListbooltrueEnables checkable task-list items.
EnableMarkdownShortcutsbooltrueEnables Markdown input shortcuts (e.g. **bold**, # Heading).
EnableAiActionsboolfalseShows an AI button in the bubble menu when text is selected. Requires OnAiAction to be wired.
EnableBubbleMenubooltrueShows the floating bubble menu (Bold, Italic, Link, etc.) when text is selected.
EnableDragHandlebooltrueShows the drag handle on the left of each block node for drag-and-drop reordering.
MaxLengthint?nullOptional plain-text character limit enforced by the editor.
AllowWordImportboolfalseAdds an Import .docx button to the Full toolbar. By default, conversion runs in-browser via WordImporter. Override with OnWordImportRequested for server-side conversion.
OnImageRequestedFunc<EditorImageRequest, ValueTask<string?>>?nullAsync callback that receives file metadata and returns the final image URL. When null, images are inlined as base64.
OnAiActionFunc<string, string, ValueTask<string?>>?nullAsync callback receiving (actionId, selectedText); returns replacement HTML. Action IDs: improve, shorten, expand, fix-grammar, summarize, translate.
OnWordImportRequestedFunc<WordImportPayload, ValueTask<string>>?nullOptional override. Receives the picked file (filename + bytes) and returns the HTML to insert. When not set, the editor calls WordImporter.ToHtmlAsync in-browser and inserts the result.
ToolbarModeRichTextToolbarMode?nullLegacy alias for Toolbar. Values: None, Basic, Full. Use Toolbar (EditorToolbarPreset) for new code.
MaxWordImportByteslong52428800Maximum file size (bytes) allowed for Word import. Default is 50 MB.
FormFieldFormFieldContext?nullCascaded context from a parent FormField; drives Invalid, Required, and error display automatically.
Classstring?nullAdditional CSS classes applied to the root wrapper element.
AdditionalAttributesDictionary<string, object>?nullSplatted onto the root element. Useful for data-* or ARIA attributes.

EditorTrigger

Property Type Default Description
CharcharThe character that activates this trigger (e.g. '@').
ItemSourceFunc<string, ValueTask<IReadOnlyList<TriggerItem>>>Async callback called on each keystroke with the partial query; returns matching items.
ItemTemplateRenderFragment<TriggerItem>?nullOptional custom row renderer for the dropdown list.
ChipClassstring?nullCSS classes applied to the chip/pill inserted into the document when an item is selected.

TriggerItem

Property Type Default Description
IdstringUnique identifier stored in the document node's data attribute.
LabelstringDisplay name shown in the dropdown and rendered in the chip.
Subtitlestring?nullSecondary text shown below the label in the dropdown row.
IconNamestring?nullLucide icon name (e.g. "User") displayed alongside the label.
Payloadobject?nullArbitrary data passed back to the consumer for custom rendering or server look-ups.

EditorImageRequest

Property Type Description
FileNamestringOriginal file name chosen by the user.
MimeTypestringMIME type of the selected file (e.g. image/png).
SizelongFile size in bytes.

EditorToolbarPreset

Value Description
NoneNo toolbar. Bubble menu and keyboard shortcuts remain available.
MinimalBold, Italic, Link only.
StandardHeadings, basic marks (bold, italic, underline, strikethrough), lists, link, undo/redo. Default value.
FullStandard plus tables, image, code block, AI action menu, and Word import button.

WordImporter (server-side)

WordImporter is a static server-side helper in Lumeo.Editor that converts a .docx stream to clean HTML using Mammoth.NET. Call it from an API endpoint and return the result to the editor via SetHtmlAsync.

Member Description
ToHtmlAsync(stream, options?)Converts a .docx stream to WordImportResult containing Html and Warnings.
DefaultStyleMapBuilt-in Mammoth style map covering English and German Word styles (Title, Heading 1-6, Body Text, Quote, etc.).
WordImportOptions.StyleMapCustom style map appended after the default map (so custom rules win).
WordImportOptions.ConvertImageOptional async callback (contentType, stream) => url to upload embedded images rather than base64-inlining them.

ASP.NET Core endpoint example

// ASP.NET Core controller endpoint
[HttpPost("/api/upload-docx")]
public async Task<IActionResult> ImportDocx(IFormFile file)
{
    using var stream = file.OpenReadStream();
    var result = await WordImporter.ToHtmlAsync(stream);
    return Ok(new { html = result.Html, warnings = result.Warnings });
}

// Optional: custom image upload during import
var options = new WordImportOptions
{
    ConvertImage = async (contentType, imageStream) =>
    {
        var url = await _storage.UploadAsync(contentType, imageStream);
        return url;
    }
};
var result = await WordImporter.ToHtmlAsync(stream, options);
  • Textarea — Plain multi-line text input without formatting
  • FormField — Wraps any input with a label, help text, and validation error
  • Form — Full form wrapper with model validation
  • Input — Single-line text input