FormsAlea Pro
RichTextEditor
A rich text (WYSIWYG) editor with a toolbar that collapses to the most used tools: text styles and sizes, marks, lists and checklists, tables you can edit, images, find and replace, and Markdown shortcuts. Pasted content and the value are cleaned to a safe set of tags.
import { sanitizeRichText } from '@alea/ui';import { RichTextEditor } from '@alea/pro';
Examples
RichTextEditor
Every tool, in a toolbar that starts with the most used ones: More tools shows text size, case, color and highlight, indent, alignment and direction, images (upload or address, with alternative text), tables you can edit, emoji, special characters, find and replace, the HTML view and full screen. The HTML you get is cleaned.
Fewer tools
tools picks which tools show, in order. RICH_TEXT_BASIC is a ready set for comments and chat (bold, italic, strike, code, link, list, emoji); RICH_TEXT_STANDARD fits posts.
Read only and safe HTML
isReadOnly shows the content without the toolbar. sanitizeRichText cleans any HTML to the same allow-list: the script, the inline handler and the javascript: link below never get through.
Checklists, Markdown and the selection toolbar
Type "[] " for a checklist, "# " for a heading, "- " or "1. " for lists, "> " for a quote; check an item by clicking its box or with ⌘Enter (Ctrl+Enter). selectionToolbar adds a small bar over selected text.
Tokens
The design tokens this component reads, with their value in the current theme. Override any of them to restyle it.
Color
--alea-accent…--alea-accent-strong…--alea-accent-subtle…--alea-bg…--alea-border…--alea-border-control…--alea-border-strong…--alea-chip-bg…--alea-chip-text…--alea-field-bg…--alea-focus…--alea-focus-halo…--alea-status-danger…--alea-surface-hover…--alea-surface-raised…--alea-text…--alea-text-faint…--alea-text-muted…
Space
--alea-space-2…--alea-space-3…--alea-space-4…--alea-space-5…
Radius
--alea-radius-field…--alea-radius-md…--alea-radius-sm…
Type
--alea-font-family-body…--alea-font-family-mono…--alea-font-size-md…--alea-font-size-sm…--alea-font-size-xs…--alea-font-weight-medium…--alea-font-weight-semibold…
Shadow
--alea-shadow-pop…
Motion
--alea-motion-duration-base…--alea-motion-duration-fast…--alea-motion-duration-instant…--alea-motion-ease-emphasized…--alea-motion-ease-out…
Layer
--alea-z-modal…
Props
RichTextEditor props
A rich text (WYSIWYG) editor: text styles and sizes, marks, case, color and highlight, lists, checklists and indent, quotes and code, links, alignment and direction, tables you can edit, images by address or upload with alternative text, emoji and special characters, find and replace, Markdown shortcuts, an HTML view, full screen, undo, and a word count. The toolbar is one Tab stop and collapses to the most used tools; pasted content and the value are cleaned to a safe set of tags, so nothing pasted can run script.
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | - | Name for screen readers when there is no visible label. |
className | string | - | Extra class names. |
collapsibleToolbar | boolean | true | Shows the most used tools first, with a More tools button for the rest (only when it would hide more than three). Default true; false shows every tool. |
defaultToolbarExpanded | boolean | false | Starts with every tool showing. Default false. |
defaultValue | string | '' | The content at first (uncontrolled). |
description | ReactNode | - | Help text under the editor. |
isDisabled | boolean | - | Disables editing. |
isReadOnly | boolean | - | Shows the content without the toolbar and without editing. |
label | ReactNode | - | The visible label. |
markdownShortcuts | boolean | true | Markdown as you type: "# " heading, "- " list, "1. " numbered, "[] " checklist, "> " quote, "---" rule, three backticks code. Default true. |
maxHeight | number | 400 | Height of the writing area before it scrolls, in px. Default 400. |
maxImageSize | number | 2 | Largest image file people can upload, in MB (stored in the HTML as data). Default 2. |
maxLength | number | - | Shows a character count against this limit (a soft limit: it warns, it doesn't cut). |
minHeight | number | 180 | Least height of the writing area, in px. Default 180. |
onChange | ((html: string) => void) | - | Called with the cleaned HTML on every change. |
placeholder | string | - | Shown while the editor is empty. |
selectionToolbar | boolean | false | A small toolbar over selected text (bold, italic, underline, link, highlight, code), for the pointer. Default false. |
showCount | boolean | true | Shows the word and character count. Default true. |
tools | RichTextTool[] | ALL | Which tools show, in order. Default all. Presets: RICH_TEXT_BASIC (comments), RICH_TEXT_STANDARD (posts) and the default (everything). |
value | string | - | The content as HTML (controlled). It is cleaned to the allowed tags. |
Specs
Generated from the source: the variants in the types, the states and tokens in the CSS, and the motion patterns that apply. The grids render the real component in both themes; the numbers are measured from the page.
- States
- Focus insideHover (CSS)Pressed (CSS)DisabledFocus (CSS)Read onlyHoverExpanded
- Dark and light
- Every color comes from theme tokens, so it follows data-theme (and presets like Graphite) on the page or any wrapper. Contrast is checked in both themes.
- Styling hooks
.alea-rte-find.alea-rte-find-current.alea-rte-tool.alea-rte-pop.alea-rte-caret.alea-rte-popover.alea-rte-swatches.alea-rte-swatch-grid.alea-rte-swatch.alea-rte-select.alea-rte-chars.alea-rte-char- Data attributes
data-variant=ghostdata-emptydata-overdata-fulldata-tabledata-ondata-checklist
Accessibility
- The writing area is a labelled multi-line text box; its help text and character count are linked to it.
- The toolbar is one Tab stop: arrows move between tools, Home and End jump. Each tool says whether it is on (aria-pressed) and names its shortcut.
- The toolbar keeps the selection: pressing a tool formats what was selected and puts the caret back.
- Pasted HTML and the value go through an allow-list (paragraphs, headings, lists, quotes, code, links with safe addresses, text alignment), so scripts, styles and javascript: links never get in.
- Escape leaves the writing area, so keyboard users are never trapped in it.
- More tools is a disclosure button (aria-expanded); the collapsed toolbar keeps the most used tools, and the table tools appear while the caret is in a table.
- Find and replace is a search landmark: the match count is announced, matches are highlighted without changing the text, and replacements are announced.
- Checking a checklist item is announced. In content shown outside the editor, the box is visual: say done or pending in the text when it matters.
- The selection toolbar is a pointer shortcut: every tool in it is also in the main toolbar and on the keyboard.
Keyboard
| Key | Does |
|---|---|
| ⌘B / Ctrl+B | Bold |
| ⌘I / Ctrl+I | Italic |
| ⌘U / Ctrl+U | Underline |
| ⌘K / Ctrl+K | Add a link |
| ⌘F / Ctrl+F | Find and replace |
| Shift+⌘V / Ctrl+Shift+V | Paste without formatting |
| ⌘Enter / Ctrl+Enter | Check or uncheck a checklist item |
| # , - , 1. , [] , > then Space | Heading, list, numbered list, checklist, quote |
| --- or three backticks, then Enter | Divider or code block |
| ⌘Z / Ctrl+Z | Undo |
| Shift+⌘Z / Ctrl+Y | Redo |
| Arrow keys (in the toolbar) | Move between tools |
| Escape | Leaves the editor, or closes the link or find bar |
Do and don't
Do
- Pick only the tools your content needs with tools: a comment box needs bold, italic, link and list.
- Store the cleaned HTML from onChange, and clean it again on the server before saving.
- Use maxLength to warn about long text; it never cuts what people wrote.
Don't
- Don't render stored HTML with dangerouslySetInnerHTML without cleaning it: use sanitizeRichText or show it in a read-only editor.
- Don't use it for plain text fields: TextArea is lighter and clearer.
- Don't use it when people write Markdown: MarkdownEditor keeps their syntax.
In Figma
RichTextEditor with the toolbar groups as boolean properties, states Default, Focus, Disabled and Read only.