@mshafiqyajid/react-rich-text
Headless rich text hook and styled component. contentEditable-based WYSIWYG editor. Bold, italic, underline, strikethrough, lists, alignment. No external deps.
Playground #
Props
TSX
import { RichTextStyled } from "@mshafiqyajid/react-rich-text/styled";
import "@mshafiqyajid/react-rich-text/styles.css";
<RichTextStyled
value={value}
onChange={setValue}
/>Install #
npm install @mshafiqyajid/react-rich-text Quick start #
import { RichTextStyled } from "@mshafiqyajid/react-rich-text/styled";
import "@mshafiqyajid/react-rich-text/styles.css";
const [html, setHtml] = useState("");
<RichTextStyled
value={html}
onChange={setHtml}
placeholder="Write something..."
tone="primary"
/> Headless #
import { useRichText } from "@mshafiqyajid/react-rich-text";
const {
editorProps,
execCommand,
isBold,
isItalic,
html,
} = useRichText({
defaultValue: "<p>Edit meβ¦</p>",
});
return (
<div className="rt">
<div className="rt__toolbar">
<button data-active={isBold} onClick={() => execCommand("bold")}>B</button>
<button data-active={isItalic} onClick={() => execCommand("italic")}>I</button>
</div>
<div {...editorProps} className="rt__editor" />
<p>HTML: {html.length} chars</p>
</div>
); API #
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | β | Controlled HTML string |
| defaultValue | string | "" | Uncontrolled initial HTML |
| onChange | (html) => void | β | Called on content change |
| placeholder | string | β | Placeholder text when empty |
| showToolbar | boolean | true | Show formatting toolbar |
| toolbarItems | ToolbarItem[] | all | Which toolbar buttons to show |
| minHeight | string | "120px" | Minimum editor height |
| maxHeight | string | β | Maximum editor height (scrolls) |
| size | "sm" | "md" | "lg" | "md" | Font and padding size |
| tone | "neutral" | "primary" | "neutral" | Accent color |
| disabled | boolean | false | Make editor read-only |
| onFocus | () => void | β | Focus callback |
| onBlur | () => void | β | Blur callback |
| wordCount | boolean | false | Show word/character count |
| spellCheck | boolean | true | Enable spell check |
| allowedTags | string[] | (safe set) | Tag whitelist used by both the on-change pass and paste sanitization. Defaults cover standard formatting tags (p, br, strong, em, u, s, h1-h6, ol, ul, li, a, blockquote, code, pre). |
| sanitizePaste | boolean | true | Strip style, class, on* attributes and disallowed tags from pasted HTML. Blocks javascript: and data: URLs. Plain text paste preserves newlines as <br>. |
| transformPaste | (html) => string | β | Run after sanitizePaste. Use for custom paste transforms (e.g. converting smart quotes). |
| shortcuts | boolean | ShortcutMap | true | Built-in keyboard shortcuts. Defaults: Mod+B bold, Mod+I italic, Mod+U underline, Mod+K link. Pass false to disable, or a partial map to override specific actions. |
| defaultLinkPrompt | "popover" | "prompt" | "popover" | Use the inline link popover (with new-tab toggle and Edit / Remove on existing links) or fall back to window.prompt. |
| renderLinkPrompt | (args) => ReactNode | β | Render-prop override for the link prompt UI. |
| bubbleMenu | boolean | object | false | Floating bubble menu over a non-empty selection. Default items: bold, italic, underline, link. |
| autoLink | boolean | false | Auto-wrap typed URLs in <a> after a space or newline. |
| autoLinkPattern | RegExp | http(s) URL | Override the pattern used by autoLink. |
| maxChars | number | β | Hard cap on plain-text characters. Inserts past the cap are blocked; deletes always pass. |
| maxWords | number | β | Hard cap on whitespace-separated words. |
| onMaxReached | (kind: "chars" | "words") => void | β | Fired when the cap blocks an insert. |
| label | ReactNode | β | Label rendered above the editor. |
| hint | ReactNode | β | Hint rendered below the editor. |
| error | ReactNode | β | Error message rendered below the editor; implies invalid. |
| invalid | boolean | false | Mark the editor invalid. Sets data-invalid + aria-invalid; uses --rrt2-border-error. |
| required | boolean | false | Adds an asterisk to the label and aria-required. |
| name | string | β | Renders a hidden <input> with the editor HTML for native <form> submission. |
| id | string | auto | id for the editor; wires up the label. |
What's new in 0.3.0 #
This release adds editor features expected in modern WYSIWYG: keyboard shortcuts (Mod+B/I/U/K), an inline link popover with new-tab toggle and Edit / Remove on existing links, an opt-in floating bubbleMenu on selections, opt-in autoLink for typed URLs, hard maxChars / maxWords caps, and full form-input parity (label, hint, error, invalid, required, name). All additive β existing props and defaults are unchanged.