Skip to content
# RichTextEditor **Also known as:** WysiwygEditor, HtmlEditor ## Description A native WYSIWYG editor whose HTML you two-way bind with Value. Its toolbar is a flags enum of groups you can reorder and extend; every byte in and out passes an allowlist sanitizer; and markdown typing rules, a slash menu, mentions, keyboard chords, counting, localization and EditForm validation are built in. The toolbar, panels and menus follow the keyboard and ARIA patterns of their roles, and Alt+0 lists every shortcut. ## Parameters | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | AutoFocus | `bool` | false | Automatically moves keyboard focus into the editor after the first render. | | AutoLink | `bool` | true | Turns a URL typed into the editor into a link as soon as the word is finished. | | Classes | `BitRichTextEditorClassStyles?` | null | Custom CSS classes for different parts of the rich text editor. | | ColorPalette | `IReadOnlyList<BitRichTextEditorColor>?` | null | The colors the text and highlight color buttons offer as swatches (plus a custom field). Null or empty keeps the browser's color picker. | | DebounceMs | `int` | 200 | Debounce window (ms) for content-change notifications while typing. Negative values are treated as 0. | | Description | `string?` | null | The helper text shown in the footer of the editor; the editing surface is described by it. | | ErrorMessage | `string?` | null | The message shown under the editor when its content was rejected. It marks the editor invalid, describes the surface and is announced as it appears. | | FontFamilies | `IReadOnlyList<string>?` | null | Font families offered in the font-family selector. Null/empty uses defaults. | | FontSizes | `IReadOnlyList<string>?` | null | Font sizes offered in the font-size selector. Null/empty uses defaults. | | Height | `string?` | null | The height the editing surface starts at (any CSS length); it grows with the content up to MaxHeight. Null leaves it to --bit-RichTextEditor-height (300px). | | Invalid | `bool` | false | Marks the content as invalid (error border and aria-invalid) for a rejection that does not come from the cascading EditContext. | | KeyboardShortcuts | `IReadOnlyDictionary<string, string>?` | null | Custom key-combo to command map, merged over the built-in defaults. | | Label | `string?` | null | The visible label of the editor. It names the editing surface for assistive technologies, and clicking it focuses the text. | | Localizer | `IBitRichTextEditorLocalizer?` | null | Localized labels/tooltips provider. Null uses built-in English labels. | | MaxHeight | `string?` | null | Maximum height of the editing surface (any CSS length); content beyond it scrolls inside the editor. Null leaves it to --bit-RichTextEditor-max-height (unbounded). | | MaxImageSize | `long` | 10485760 | The largest image, in bytes, that a drop or a paste may insert (10 MB). Checked in the browser and again before OnImageUpload; zero or less restores the default. | | MaxLength | `int?` | null | Maximum plain-text character count. Null means unlimited. | | OnBlur | `EventCallback` | | Callback for when the editor loses focus. | | OnChange | `EventCallback<string?>` | | Callback for when the editor content changes. | | OnError | `EventCallback<BitRichTextEditorError>` | | Callback for when the editor encounters a recoverable error. | | OnFocus | `EventCallback` | | Callback for when the editor gains focus. | | OnMentionSearch | `Func<string, Task<IReadOnlyList<BitRichTextEditorMention>>>?` | null | Supplies the suggestions shown after the user types "@". Leaving it null disables mentions. | | OnMentionSelected | `EventCallback<BitRichTextEditorMention>` | | Callback for when a mention is picked from the menu. | | OnImageUpload | `Func<BitRichTextEditorImageUpload, Task<string?>>?` | null | Invoked to persist an image binary, returning the URL to embed. While it runs the editor shows and announces the upload (aria-busy on the surface). When null, dropped or pasted images are embedded as inline data URLs. | | OnSelectionChange | `EventCallback<BitRichTextEditorSelectionState>` | | Callback for when the selection - or the formatting under it - changes; receives the same snapshot the toolbar highlights itself from. | | PasteAsPlainText | `bool` | false | When true, pasted content is inserted as plain text. | | Placeholder | `string?` | null | The placeholder value of the editor shown while it is empty. | | ReadOnly | `bool` | false | Makes the editor readonly. | | Required | `bool` | false | Marks the editor as required: aria-required on the surface and an asterisk on the Label. | | Resizable | `bool` | false | Lets the reader drag the bottom edge of the editing surface to make it taller or shorter. | | SanitizationPolicy | `BitRichTextEditorSanitizationPolicy?` | null | Allowlist policy applied to all content. When null a secure default allowlist is applied. | | ShowCount | `bool` | false | Show the character/word count footer. | | ShowQuickToolbar | `bool` | false | Whether a small formatting toolbar floats next to the current text selection. | | ShowToolbar | `bool` | true | Whether the formatting toolbar is shown. | | SmartTypography | `bool` | false | Replaces common text patterns with their typographic characters as they are typed: curly quotes, em dash, ellipsis, copyright/registered/trademark signs, fractions, arrows and comparison symbols. | | SpellCheck | `bool` | true | Whether the browser's native spell checking runs over the editor content. | | StickyToolbar | `bool` | false | Keeps the toolbar in view while the page scrolls past a tall editor, --bit-RichTextEditor-toolbar-sticky-offset below the top. | | Styles | `BitRichTextEditorClassStyles?` | null | Custom CSS styles for different parts of the rich text editor. | | Toolbar | `BitRichTextEditorToolbar` | BitRichTextEditorToolbar.All | Which toolbar groups to display. | | ToolbarConfig | `BitRichTextEditorToolbarConfig?` | null | Custom toolbar items and ordering. Null uses the default group order. | | Value | `string?` | null | The two-way bound HTML content of the editor. | | AriaLabel | `string?` | null | Gets or sets the accessible label for the component, used by assistive technologies. | | Class | `string?` | null | Gets or sets the CSS class name(s) to apply to the rendered element. | | Dir | `BitDir?` | null | Gets or sets the text directionality for the component's content. | | Disabled | `bool` | false | Gets or sets a value indicating whether the component is disabled and cannot respond to user interaction. | | ForceAnimation | `bool` | false | Gets or sets a value indicating whether the component's animations play at their full duration even when reduced motion is requested. | | HtmlAttributes | `Dictionary<string, object>` | new Dictionary<string, object>() | Captures additional HTML attributes to be applied to the rendered element, in addition to the component's parameters. An attribute written on the component wins over an entry of the same name. | | Id | `string?` | null | Gets or sets the unique identifier for the component's root element. | | Style | `string?` | null | Gets or sets the CSS style string to apply to the rendered element. | | TabIndex | `string?` | null | Gets or sets the tab order index for the component when navigating with the keyboard. | | Visibility | `BitVisibility` | BitVisibility.Visible | Gets or sets the visibility state (visible, hidden, or collapsed) of the component. | ## Public Members | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | CharacterCount | `int` | | The plain-text character count of the current content, as the count footer and MaxLength count it. | | ClearAsync | `Task` | | Clears the editor content. | | ExecuteCommandAsync | `Task` | | Runs a raw editing command against the editor. | | FocusAsync | `ValueTask` | | Moves keyboard focus into the editor. | | GetHtmlAsync | `ValueTask<string>` | | Returns the current HTML content of the editor. | | GetSelectedTextAsync | `ValueTask<string>` | | Returns the plain text of the current selection, or an empty string when nothing inside the editor is selected. | | GetTextAsync | `ValueTask<string>` | | Returns the current content of the editor as plain text, with block boundaries rendered as newlines and all markup removed. | | InsertHtmlAsync | `Task` | | Inserts HTML at the current caret position, after running it through the active sanitization policy. | | InsertTextAsync | `Task` | | Inserts plain text at the current caret position, honoring MaxLength. | | IsEmpty | `bool` | | Whether the editor holds nothing a reader would see - no text and none of the elements that are content without carrying text (images, tables, rules, media). | | RedoAsync | `Task` | | Redoes the last undone edit. | | SelectionState | `BitRichTextEditorSelectionState` | | The formatting under the current selection, the snapshot the toolbar highlights itself from. | | SelectAllAsync | `ValueTask` | | Selects the whole editor content. | | SetHtmlAsync | `Task` | | Replaces the whole content with the given HTML (sanitized), or clears it when null/empty. | | UndoAsync | `Task` | | Undoes the last edit. | | WordCount | `int` | | The word count of the current content. | | UniqueId | `Guid` | Guid.NewGuid() | Gets the readonly unique identifier for the component's root element, assigned when the component instance is constructed. | | RootElement | `ElementReference` | | Gets the reference to the root HTML element associated with this component. | ## Enums ### BitRichTextEditorToolbar Enum | Name | Value | Description | | :--- | :--- | :---------- | | None | 0 | | | History | 1 | | | BlockFormat | 2 | | | Inline | 4 | | | Lists | 8 | | | Blocks | 16 | | | Link | 32 | | | Alignment | 64 | | | Clear | 128 | | | Image | 256 | | | Color | 512 | | | Font | 1024 | | | Indent | 2048 | | | Script | 4096 | | | Source | 8192 | | | Table | 16384 | | | Media | 32768 | | | Rule | 65536 | | | Emoji | 131072 | | | Find | 262144 | | | FullScreen | 524288 | | | Direction | 1048576 | | | Help | 2097152 | | | All | 255 | | | AllExtended | 4194303 | | ### BitVisibility Enum | Name | Value | Description | | :--- | :--- | :---------- | | Visible | 0 | The content of the component is visible. | | Hidden | 1 | The content of the component is hidden, but the space it takes on the page remains (visibility:hidden). | | Collapsed | 2 | The component is hidden (display:none). | ### BitDir Enum | Name | Value | Description | | :--- | :--- | :---------- | | Ltr | 0 | Ltr (left to right) is to be used for languages that are written from the left to the right (like English). | | Rtl | 1 | Rtl (right to left) is to be used for languages that are written from the right to the left (like Arabic). | | Auto | 2 | Auto lets the user agent decide. It uses a basic algorithm as it parses the characters inside the element until it finds a character with a strong directionality, then applies that directionality to the whole element. | ## Sub Classes ### BitRichTextEditorClassStyles Properties | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Root | `string?` | null | Custom CSS classes/styles for the root of the BitRichTextEditor. | | Label | `string?` | null | Custom CSS classes/styles for the label of the BitRichTextEditor. | | Toolbar | `string?` | null | Custom CSS classes/styles for the toolbar of the BitRichTextEditor. | | Group | `string?` | null | Custom CSS classes/styles for the toolbar groups of the BitRichTextEditor. | | Button | `string?` | null | Custom CSS classes/styles for the toolbar buttons of the BitRichTextEditor. | | Panel | `string?` | null | Custom CSS classes/styles for the tool panels (link, image, media, table, find, emoji, color and keyboard help) of the BitRichTextEditor. | | QuickToolbar | `string?` | null | Custom CSS classes/styles for the floating selection toolbar of the BitRichTextEditor. | | Menu | `string?` | null | Custom CSS classes/styles for the slash command and mention menus of the BitRichTextEditor. | | Error | `string?` | null | Custom CSS classes/styles for the inline error banner (a failed command, link or upload) of the BitRichTextEditor. | | Editor | `string?` | null | Custom CSS classes/styles for the editor (content) area of the BitRichTextEditor. | | Source | `string?` | null | Custom CSS classes/styles for the HTML source view textarea of the BitRichTextEditor. | | ErrorMessage | `string?` | null | Custom CSS classes/styles for the error message (the ErrorMessage parameter) of the BitRichTextEditor. | | Footer | `string?` | null | Custom CSS classes/styles for the footer row (holding the description and the counts) of the BitRichTextEditor. | | Description | `string?` | null | Custom CSS classes/styles for the description (helper text) in the footer of the BitRichTextEditor. | | Count | `string?` | null | Custom CSS classes/styles for the character/word counts in the footer of the BitRichTextEditor. | ### BitRichTextEditorToolbarConfig Properties Configures toolbar ordering and custom items. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Order | `IReadOnlyList<string>?` | null | Explicit ordering of toolbar entry ids (built-in group ids and custom item ids). Use BitRichTextEditorToolbarConfig.GroupIds for the built-in ids. | | CustomItems | `IReadOnlyList<BitRichTextEditorToolbarItem>?` | null | Custom toolbar items (max 50 are rendered). | ### BitRichTextEditorToolbarItem Properties A custom toolbar button supplied by the host. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Id | `string` | | Unique id used for ordering and lookup. It must not collide with a built-in group id. | | Label | `string?` | null | Text label shown when no icon is provided. | | Icon | `RenderFragment?` | null | Optional icon content. | | AriaLabel | `string?` | null | Optional accessible label / tooltip. When omitted, Label is used as the accessible name. | | IsActive | `Func<BitRichTextEditorSelectionState, bool>?` | null | Whether the item shows as pressed (and reports aria-pressed) for the formatting at the caret. Null makes a plain action button. | | OnActivate | `Func<BitRichTextEditor, Task>` | | Action invoked when the item is activated; receives the editor instance. | ### BitRichTextEditorSanitizationPolicy Properties An allowlist sanitization policy. Only the listed tags, attributes, and URI schemes are retained; everything else is removed. The static Default property returns a fresh copy of the built-in policy. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | AllowedTags | `ISet<string>` | | Permitted (lowercase) element/tag names. | | AllowedAttributes | `IDictionary<string, ISet<string>>` | | Permitted attributes per tag name. Use the key "*" for attributes allowed on any tag. A permitted style attribute is filtered further, down to presentational CSS properties. | | AllowedUriSchemes | `ISet<string>` | | Permitted URI schemes for href/src attributes (e.g. http, https, mailto). | | AllowDataImageUris | `bool` | true | Whether data: image URIs are permitted in image sources. | | AllowedIframeHosts | `IReadOnlyCollection<string>?` | null | Hosts an iframe may point at, over https. Null applies the built-in approved embed hosts (YouTube, YouTube-nocookie, Vimeo); an empty collection permits no iframe at all; a single "*" entry lifts the restriction and lets any https source through. | ### BitRichTextEditorImageUpload Properties An image to be persisted by the host's OnImageUpload delegate. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | FileName | `string` | | Original file name, when available. | | ContentType | `string` | | MIME type, e.g. "image/png". | | Content | `byte[]` | | Raw image bytes. | ### BitRichTextEditorSelectionState Properties Snapshot of the formatting under the selection, reported to OnSelectionChange and used to highlight the toolbar. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Bold | `bool` | false | Whether the selection is bold. | | Italic | `bool` | false | Whether the selection is italic. | | Underline | `bool` | false | Whether the selection is underlined. | | StrikeThrough | `bool` | false | Whether the selection is struck through. | | InlineCode | `bool` | false | Whether the selection sits inside an inline code span (not a code block). | | Subscript | `bool` | false | Whether the selection is subscript. | | Superscript | `bool` | false | Whether the selection is superscript. | | OrderedList | `bool` | false | Whether the selection sits in a numbered list. | | UnorderedList | `bool` | false | Whether the selection sits in a bulleted list. | | TaskList | `bool` | false | Whether the selection sits in a checklist item. | | JustifyLeft | `bool` | false | Whether the block is aligned left. | | JustifyCenter | `bool` | false | Whether the block is centered. | | JustifyRight | `bool` | false | Whether the block is aligned right. | | JustifyFull | `bool` | false | Whether the block is justified. | | Block | `string` | "" | The current block tag ("p", "h1", "blockquote", "pre", ...), lowercase. | | Direction | `string?` | null | Text direction of the selected block ("ltr"/"rtl"), or null. | | ForeColor | `string?` | null | Active text color of the selection, or null when mixed/none. | | BackColor | `string?` | null | Active highlight color of the selection, or null when mixed/none. | | FontName | `string?` | null | Active font family, or null when the selection spans several. | | FontSize | `string?` | null | Active font size as a CSS length, or null when the selection spans several. | | InLink | `bool` | false | Whether the selection sits inside a hyperlink. | | LinkHref | `string?` | null | The href of the link under the selection, or null when none/multiple. | | LinkNewTab | `bool` | false | Whether that link opens in a new tab (target="_blank"). | | InTable | `bool` | false | Whether the selection sits inside a table cell, which is what enables the table operations. | | ImageSelected | `bool` | false | Whether an image inside the editor is selected. | | ImageAlign | `string?` | null | Alignment of the selected image ("left", "center", "right"), or null when it flows inline. | | ImageSrc | `string?` | null | Source of the selected image, or null when no image is selected. | | ImageAlt | `string?` | null | Alternative text of the selected image (empty when it has none), or null when no image is selected. | | ImageWidth | `int?` | null | Width in pixels the selected image was given, or null when it keeps its natural size or no image is selected. | | HasSelection | `bool` | false | Whether a non-empty range inside the editor is selected. | | SelectionTop | `double` | 0 | Top of the selection rectangle, in pixels relative to the component root. | | SelectionLeft | `double` | 0 | Left edge of the selection rectangle, in pixels relative to the component root. | | SelectionWidth | `double` | 0 | Width of the selection rectangle in pixels. | | SelectionHeight | `double` | 0 | Height of the selection rectangle in pixels. | ### BitRichTextEditorMention Properties A single suggestion offered by the mention menu. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Id | `string` | | Stable identifier written into the inserted markup as data-mention-id. | | Display | `string` | | The text shown in the menu and inserted after the trigger character. | | Description | `string?` | null | Optional secondary line shown under the display text in the menu. | ### BitRichTextEditorColor Properties A color offered as a swatch by the text and highlight color panels. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Value | `string` | | The color applied, as a hex value (#2563eb); a hex value also lets the swatch show it is the color under the caret. | | Name | `string?` | null | The accessible name and tooltip of the swatch ("Brand blue"). Without it the value is read out. | ### BitRichTextEditorError Properties An error surfaced by the editor (e.g. invalid URL, failed upload, invalid HTML). | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Code | `string` | | Stable error code, e.g. "invalid-url". | | Message | `string` | | Human-readable description. | ### IBitRichTextEditorLocalizer Properties Provides localized labels and tooltips for the editor's controls. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | this[string key] | `string?` | | Returns the localized string for the given key, or null to use the built-in English default. | ## CSS Variables Public CSS custom properties read off the component's root. Set one on `:root` to restyle every instance, on any ancestor to restyle the ones inside it, or on the `Style` of one instance to restyle it and every instance nested inside it, which inherits the value too - a parameter changes one alone, as does the real CSS property on its `Style` / `Styles` when that property does not inherit (`opacity`); an inherited one (`color`, `font-family`) reaches the nested instances that do not set it themselves. | Name | Default Value | Description | | :--- | :------------ | :---------- | | `--bit-RichTextEditor-color` | var(--bit-clr-fg-pri) | Text color of the editor. | | `--bit-RichTextEditor-background` | var(--bit-clr-bg-pri) | Background of the editor and of its floating toolbar and menus. | | `--bit-RichTextEditor-border-color` | var(--bit-clr-brd-pri) | Color of the outer border. | | `--bit-RichTextEditor-border-width` | var(--bit-shp-brd-width) | Width of the outer border. | | `--bit-RichTextEditor-border-radius` | var(--bit-shp-radius-surface) | Corner radius of the editor. | | `--bit-RichTextEditor-divider-color` | var(--bit-clr-brd-sec) | Lines between the toolbar, its panels, the surface and the footer, and between the toolbar groups. | | `--bit-RichTextEditor-focus-color` | var(--bit-clr-pri-focus) | Every focus indicator of the editor. While it is unset, every focus ring held off its element is the library's own --bit-shd-focus-ring; the ones drawn flush against a cell or a field keep this color. | | `--bit-RichTextEditor-error-color` | var(--bit-clr-err) | Border of an invalid editor, the required asterisk, the error message, the inline error and the limit reached. | | `--bit-RichTextEditor-height` | spacing(37.5) | Height the editing surface starts at (the Height parameter sets it on the instance). | | `--bit-RichTextEditor-max-height` | none | Height past which the surface scrolls (the MaxHeight parameter sets it on the instance). | | `--bit-RichTextEditor-padding` | spacing(1.75) spacing(2) | Padding of the editing surface and the source view. | | `--bit-RichTextEditor-font-family` | inherit | Font of the content. | | `--bit-RichTextEditor-font-size` | inherit | Font size of the content. | | `--bit-RichTextEditor-line-height` | 1.6 | Line height of the content and the source view. | | `--bit-RichTextEditor-placeholder-color` | var(--bit-clr-fg-sec) | Placeholder text of the editing surface and of the fields of its panels (link, image, media, find and replace, search). | | `--bit-RichTextEditor-link-color` | var(--bit-clr-pri) | Links in the content. | | `--bit-RichTextEditor-code-background` | var(--bit-clr-bg-sec) | Background of code spans, code blocks and the source view. | | `--bit-RichTextEditor-quote-border-color` | var(--bit-clr-brd-pri) | Leading rule of a block quote. | | `--bit-RichTextEditor-table-border-color` | var(--bit-clr-brd-pri) | Table cell borders and horizontal rules in the content. | | `--bit-RichTextEditor-mention-color` | var(--bit-clr-pri-dark) | Text of a mention chip. | | `--bit-RichTextEditor-mention-background` | var(--bit-clr-pri-light) | Background of a mention chip. | | `--bit-RichTextEditor-find-background` | var(--bit-clr-wrn-light) | Highlight of every find match (the current one takes the primary color). | | `--bit-RichTextEditor-toolbar-background` | var(--bit-clr-bg-sec) | Background of the toolbar and its panels. | | `--bit-RichTextEditor-toolbar-sticky-offset` | 0 | Gap between a StickyToolbar and the top of the scrolling area once it is pinned (the height of a fixed header). | | `--bit-RichTextEditor-button-size` | var(--bit-siz-ctrl-md) | Height (and minimum width) of a toolbar button and selector. | | `--bit-RichTextEditor-button-color` | var(--bit-clr-fg-pri) | Glyph of a toolbar button. | | `--bit-RichTextEditor-button-radius` | var(--bit-shp-radius-button) | Corner radius of a toolbar button. | | `--bit-RichTextEditor-button-hover-background` | var(--bit-clr-bg-sec-hover) | Background of a toolbar button, an emoji or a menu item under the pointer. | | `--bit-RichTextEditor-button-active-color` | var(--bit-clr-pri) | Glyph and border of a pressed button (the format at the caret, an open panel) and of the current menu item. | | `--bit-RichTextEditor-button-active-background` | var(--bit-clr-bg-pri-active) | Background of a pressed button and of the current menu item. | | `--bit-RichTextEditor-description-color` | var(--bit-clr-fg-sec) | Helper text (Description) in the footer. | | `--bit-RichTextEditor-footer-color` | var(--bit-clr-fg-sec) | Text of the counts in the footer. | | `--bit-RichTextEditor-footer-background` | var(--bit-clr-bg-sec) | Background of the footer that holds the description and the counts. | ## Examples \n**Basic**: ```razor ``` \n**Placeholder & size**: ```razor ``` \n**Binding**: ```razor Set content Clear Append
Changes: @changeCount
@bindingHtml
``` ```csharp private string? bindingHtml = "

The bound value is just a string you own.

"; private int changeCount; ``` \n**Toolbar**: ```razor ``` ```csharp private string? toolbarHtml = "

Every group

Scroll the page while this editor is in view: the toolbar stays pinned to the top.

  • Try the table, emoji and find buttons
  • Toggle full screen
"; ``` \n**Custom toolbar**: ```razor ``` ```csharp private string? customHtml = "

The inline group comes first, 'Today' inserts the date and 'Callout' toggles a quote.

"; private readonly BitRichTextEditorToolbarConfig customConfig = new() { Order = [BitRichTextEditorToolbarConfig.GroupIds.Inline, "insert-date", "callout"], CustomItems = [ new() { Id = "insert-date", Label = "Today", AriaLabel = "Insert today's date", OnActivate = editor => editor.InsertTextAsync(DateTime.Now.ToString("yyyy-MM-dd")) }, new() { Id = "callout", Label = "Callout", IsActive = state => state.Block == "blockquote", OnActivate = editor => editor.ExecuteCommandAsync("formatBlock", editor.SelectionState.Block == "blockquote" ? "p" : "blockquote") } ] }; ``` \n**Read-only & disabled**: ```razor ``` \n**Links**: ```razor @if (linkError is not null) { @linkError } ``` ```csharp private string? linkHtml = "

Read the Blazor docs to learn more.

"; private string? linkError; private void HandleLinkHtmlChanged(string? value) { linkHtml = value; // A successful content update means the previous error no longer applies. linkError = null; } ``` \n**Images**: ```razor @if (lastUpload is not null) {
Last upload: @lastUpload
} ``` ```csharp private string? imageHtml = "

Images can sit inline with text.

"; private string? lastUpload; private async Task HandleImageUpload(BitRichTextEditorImageUpload image) { lastUpload = $"{image.FileName} ({image.ContentType}, {image.Content.Length:N0} bytes)"; // Upload the bytes to your storage here and return the public URL (or null to cancel); // the delay stands in for that round trip, while the editor shows it is uploading. await Task.Delay(1500); return $"data:{image.ContentType};base64,{Convert.ToBase64String(image.Content)}"; } ``` \n**Colors & fonts**: ```razor ``` ```csharp private string? colorHtml = "

Make words colorful or highlighted, then pick a typeface.

"; private readonly string[] fonts = ["Segoe UI", "Georgia", "Courier New", "Comic Sans MS"]; private readonly string[] sizes = ["12px", "16px", "20px", "28px"]; private readonly BitRichTextEditorColor[] palette = [ new("#1f2937", "Ink"), new("#5b3df5", "Brand violet"), new("#2563eb", "Blue"), new("#059669", "Green"), new("#d97706", "Amber"), new("#dc2626", "Red"), new("#fff3a3", "Soft yellow"), new("#dbeafe", "Soft blue"), ]; ``` \n**Tables**: ```razor ``` \n**Media & rules**: ```razor ``` \n**Find & replace**: ```razor ``` \n**Sanitization & paste**: ```razor ``` ```csharp private string? sanitizationHtml = "

Only allowlisted tags, attributes and URI schemes survive.

"; private string? plainPasteHtml; private readonly BitRichTextEditorSanitizationPolicy sanitizationPolicy = new() { AllowedTags = new HashSet(StringComparer.OrdinalIgnoreCase) { "p", "br", "strong", "em", "a", "ul", "ol", "li" }, AllowedAttributes = new Dictionary>(StringComparer.OrdinalIgnoreCase) { ["*"] = new HashSet(StringComparer.OrdinalIgnoreCase) { "class" }, ["a"] = new HashSet(StringComparer.OrdinalIgnoreCase) { "href", "title" }, }, AllowedUriSchemes = new HashSet(StringComparer.OrdinalIgnoreCase) { "http", "https", "mailto" }, AllowDataImageUris = false, }; ``` \n**Typing aids**: ```razor ``` \n**Keyboard shortcuts**: ```razor ``` ```csharp private string? shortcutHtml = "

Press Ctrl/Cmd+Shift+S, Ctrl/Cmd+Shift+L or Ctrl/Cmd+Shift+1, and Alt+0 to list them all.

"; private readonly Dictionary shortcuts = new() { ["ctrl+shift+s"] = "strikeThrough", ["ctrl+shift+l"] = "insertUnorderedList", ["ctrl+shift+1"] = "h1", }; ``` \n**Selection toolbar**: ```razor ``` \n**Mentions**: ```razor @if (lastMention is not null) {
Last mention: @lastMention
} ``` ```csharp private string? mentionHtml = "

Type @ to bring up the people picker.

"; private string? lastMention; private static readonly BitRichTextEditorMention[] people = [ new("1", "Ada Lovelace", "Analytical engine"), new("2", "Alan Turing", "Computing machinery"), new("3", "Grace Hopper", "Compilers"), new("4", "Katherine Johnson", "Orbital mechanics"), new("5", "Margaret Hamilton", "Flight software"), ]; private Task> SearchMentions(string term) { IReadOnlyList matches = string.IsNullOrWhiteSpace(term) ? people : people.Where(p => p.Display.Contains(term, StringComparison.OrdinalIgnoreCase)).ToArray(); return Task.FromResult(matches); } ``` \n**Forms & validation**: ```razor Submit @if (formSubmitted) { Submitted successfully! } Save comment ``` ```csharp private readonly FormModel formModel = new(); private bool formSubmitted; private void HandleValidSubmit() { formSubmitted = true; } public class FormModel : IValidatableObject { [Required(ErrorMessage = "The description is required.")] public string? Body { get; set; } public IEnumerable Validate(ValidationContext validationContext) { // The value is HTML, so measure its visible text: markup with no text passes [Required]. var stripped = System.Text.RegularExpressions.Regex.Replace(Body ?? "", "<[^>]+>", ""); var text = System.Net.WebUtility.HtmlDecode(stripped).Trim(); if (string.IsNullOrWhiteSpace(Body) is false && text.Length == 0) { yield return new ValidationResult("The description is required.", [nameof(Body)]); } else if (text.Length > 0 && text.Length < 20) { yield return new ValidationResult("Add a bit more detail (min 20 characters).", [nameof(Body)]); } } } private string? commentHtml = "

Save this to see the server reject it, then edit it to clear the error.

"; private string? commentError; // Stands in for a server round trip that refuses the content. private void SaveComment() => commentError = "The server refused the comment: it reads like spam."; ``` \n**Events**: ```razor
Editor is @focusState; the caret is in: @selectionSummary
``` ```csharp private string? eventsHtml = "

A heading

Some bold text with a link in it.

"; private string focusState = "blurred"; private string selectionSummary = "nothing yet"; private void HandleSelectionChange(BitRichTextEditorSelectionState state) { var parts = new List(); if (string.IsNullOrEmpty(state.Block) is false) parts.Add(state.Block); if (state.Bold) parts.Add("bold"); if (state.Italic) parts.Add("italic"); if (state.InLink) parts.Add("a link"); if (state.InTable) parts.Add("a table cell"); if (state.ImageSelected) parts.Add("an image"); selectionSummary = parts.Count > 0 ? string.Join(", ", parts) : "nothing yet"; } ``` \n**Localization**: ```razor ``` ```csharp private string? localizedHtml = "

Pase el cursor sobre los botones para ver las descripciones traducidas.

"; private readonly SpanishEditorLocalizer localizer = new(); // Only the keys present here are translated; every other key keeps the built-in English text. public class SpanishEditorLocalizer : IBitRichTextEditorLocalizer { private static readonly Dictionary Labels = new() { ["toolbar"] = "Formato", ["editor"] = "Editor de texto enriquecido", ["undo"] = "Deshacer (Ctrl+Z)", ["undo-label"] = "Deshacer", ["redo"] = "Rehacer (Ctrl+Y)", ["redo-label"] = "Rehacer", ["bold"] = "Negrita (Ctrl+B)", ["bold-label"] = "Negrita", ["italic"] = "Cursiva (Ctrl+I)", ["italic-label"] = "Cursiva", ["underline"] = "Subrayado (Ctrl+U)", ["underline-label"] = "Subrayado", ["strikethrough"] = "Tachado", ["paragraph-format"] = "Formato de párrafo", ["block-normal"] = "Normal", ["heading-1"] = "Título 1", ["heading-2"] = "Título 2", ["heading-3"] = "Título 3", ["bullet-list"] = "Lista con viñetas", ["numbered-list"] = "Lista numerada", ["task-list"] = "Lista de tareas", ["quote"] = "Cita", ["code-block"] = "Bloque de código", ["link"] = "Insertar o editar enlace", ["link-label"] = "Insertar o editar enlace", ["find-replace"] = "Buscar y reemplazar", ["find-replace-label"] = "Buscar y reemplazar", ["find"] = "Buscar", ["replace"] = "Reemplazar", ["no-matches"] = "Sin coincidencias", ["clear-formatting"] = "Borrar formato", }; public string? this[string key] => Labels.TryGetValue(key, out var value) ? value : null; } ``` \n**Imperative API**: ```razor FocusAsync ExecuteCommand("bold") InsertTextAsync InsertHtmlAsync SelectAllAsync UndoAsync GetHtmlAsync GetTextAsync GetSelectedTextAsync Counts ClearAsync
Result:
@apiResult
``` ```csharp private BitRichTextEditor apiEditor = default!; private string? apiHtml = "

Drive me from the buttons above.

"; private string? apiResult; private async Task FocusEditor() => await apiEditor.FocusAsync(); private async Task GetEditorHtml() => apiResult = await apiEditor.GetHtmlAsync(); private async Task GetEditorText() => apiResult = await apiEditor.GetTextAsync(); private async Task GetEditorSelection() => apiResult = await apiEditor.GetSelectedTextAsync(); private void ShowEditorFacts() => apiResult = $"{apiEditor.WordCount} words, {apiEditor.CharacterCount} chars, empty: {apiEditor.IsEmpty}"; ``` \n**Cascading parameters**: ```razor ``` ```csharp private readonly BitRichTextEditorParams[] richTextEditorParams = [ new() { Height = "6rem", ShowCount = true, StickyToolbar = true, Toolbar = BitRichTextEditorToolbar.Inline | BitRichTextEditorToolbar.Lists | BitRichTextEditorToolbar.Link, Placeholder = "Defaults come from BitParams...", } ]; ``` \n**Style & Class**: ```razor ``` ```csharp private string? cssVariablesHtml = "

Restyled with the public CSS variables: no class needed.

Even the quote rule.
"; private const string cssVariablesStyle = "--bit-RichTextEditor-border-radius:1rem;" + "--bit-RichTextEditor-border-color:var(--bit-clr-pri);" + "--bit-RichTextEditor-toolbar-background:color-mix(in srgb, var(--bit-clr-pri) 12%, transparent);" + "--bit-RichTextEditor-footer-background:color-mix(in srgb, var(--bit-clr-pri) 12%, transparent);" + "--bit-RichTextEditor-button-radius:999px;" + "--bit-RichTextEditor-quote-border-color:var(--bit-clr-pri);" + "--bit-RichTextEditor-font-family:Georgia, serif;" + "--bit-RichTextEditor-line-height:1.8;"; ``` \n**RTL**: ```razor ``` ```csharp private string? rtlHtml = "

این ویرایشگر از راست به چپ چیده شده است.

And this block is left-to-right.

"; ```