react ~8 KB 0 deps v0.4.0 β†— GitHub β†—

@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 #

PropTypeDefaultDescription
valuestringβ€”Controlled HTML string
defaultValuestring""Uncontrolled initial HTML
onChange(html) => voidβ€”Called on content change
placeholderstringβ€”Placeholder text when empty
showToolbarbooleantrueShow formatting toolbar
toolbarItemsToolbarItem[]allWhich toolbar buttons to show
minHeightstring"120px"Minimum editor height
maxHeightstringβ€”Maximum editor height (scrolls)
size"sm" | "md" | "lg""md"Font and padding size
tone"neutral" | "primary""neutral"Accent color
disabledbooleanfalseMake editor read-only
onFocus() => voidβ€”Focus callback
onBlur() => voidβ€”Blur callback
wordCountbooleanfalseShow word/character count
spellCheckbooleantrueEnable spell check
allowedTagsstring[](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).
sanitizePastebooleantrueStrip 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).
shortcutsboolean | ShortcutMaptrueBuilt-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.
bubbleMenuboolean | objectfalseFloating bubble menu over a non-empty selection. Default items: bold, italic, underline, link.
autoLinkbooleanfalseAuto-wrap typed URLs in <a> after a space or newline.
autoLinkPatternRegExphttp(s) URLOverride the pattern used by autoLink.
maxCharsnumberβ€”Hard cap on plain-text characters. Inserts past the cap are blocked; deletes always pass.
maxWordsnumberβ€”Hard cap on whitespace-separated words.
onMaxReached(kind: "chars" | "words") => voidβ€”Fired when the cap blocks an insert.
labelReactNodeβ€”Label rendered above the editor.
hintReactNodeβ€”Hint rendered below the editor.
errorReactNodeβ€”Error message rendered below the editor; implies invalid.
invalidbooleanfalseMark the editor invalid. Sets data-invalid + aria-invalid; uses --rrt2-border-error.
requiredbooleanfalseAdds an asterisk to the label and aria-required.
namestringβ€”Renders a hidden <input> with the editor HTML for native <form> submission.
idstringautoid 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.

Edit this page on GitHub