A TipTap rich text editor with a toolbar (bold, italic, headings 2 and 3, bulleted and numbered lists, quote, link, image), plus `RichText`, the renderer for the HTML it stores, with print-friendly prose styles.
Examples of v0.1.5 are shown as code; only the latest version runs live. Open the live examples →
A controlled editor in a `FormField`. The preview below it is `RichText` on the same HTML.
Basic Rich Text Editor
1const SAMPLE_HTML =2 '<h2>Before you get in</h2><p>The hot tub is on the back deck, past the <strong>string lights</strong>. It stays at 102°F all year.</p><ul><li>Shower first.</li><li>Keep the cover on whenever nobody is in.</li></ul><h3>Turning on the jets</h3><ol><li>Lift the cover from the house side.</li><li>Press <strong>Jets</strong> once for low, twice for high.</li></ol><blockquote><p>Please be out of the tub by 10 pm.</p></blockquote><p>Something not working? See <a href="/guide/who-to-call">Who to call</a>. <em>Never drain the tub yourself.</em></p>';34const BasicRichTextEditor = () => {5 const [html, setHtml] = useState(SAMPLE_HTML);67 return (8 <>9 <FormField10 label="About the house"11 htmlFor="about"12 hint="Shown on the home page."13 >14 <RichTextEditor15 id="about"16 value={html}17 onChange={setHtml}18 aria-label="About the house"19 />20 </FormField>21 <RichText html={html} />22 </>23 );24};2526render(<BasicRichTextEditor />);
With `onInsertImage`, the toolbar shows an Image button. The picker here resolves with a stand-in image.
With Image Rich Text Editor
1const WithImageRichTextEditor = () => {2 const [html, setHtml] = useState("<p>Add a photo with the image button.</p>");34 return (5 <RichTextEditor6 value={html}7 onChange={setHtml}8 aria-label="Page body"9 onInsertImage={async () => ({10 src: "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='640' height='360'><rect width='640' height='360' fill='%23bc13fe'/></svg>",11 alt: "A purple placeholder",12 width: 640,13 height: 360,14 })}15 />16 );17};1819render(<WithImageRichTextEditor />);
`features` limits the toolbar to the formats a field needs, here a short bio.
Bio Rich Text Editor
1const BioRichTextEditor = () => {2 const [html, setHtml] = useState("<p>Painter and potter.</p>");34 return (5 <RichTextEditor6 value={html}7 onChange={setHtml}8 aria-label="Artist bio"9 features={["bold", "italic", "link"]}10 />11 );12};1314render(<BioRichTextEditor />);
Invalid state for a required field that is empty; `FormField` shows the message.
Invalid Rich Text Editor
1const InvalidRichTextEditor = () => (2 <FormField label="Body" htmlFor="body" error="Add some text." required>3 <RichTextEditor4 id="body"5 value=""6 onChange={() => {}}7 aria-label="Body"8 invalid9 />10 </FormField>11);1213render(<InvalidRichTextEditor />);