Rich text editor
Installation
Package has peer dependencies: react, react-dom, @mantine/hooks and @mantine/core:.
Install with npm:
npm install @mantine/rte @mantine/core @mantine/hooks
Install with yarn:
yarn add @mantine/rte @mantine/core @mantine/hooks
Demo
Usage
value
and onChange
props are required for component to work.
Note that though component is controlled you cannot force value (limitation of Quill.js library).
import { useState } from 'react;import { RichTextEditor } from '@mantine/rte';const initialValue ='<p>Your initial <b>html value</b> or an empty string to init editor without value</p>';function Demo() {const [value, onChange] = useState(initialValue);return <RichTextEditor value={value} onChange={onChange} />;}
Configure toolbar
RichTextEditor supports these controls in toolbar:
bold
,strike
,italic
,underline
– general inline formattingclean
– removes all inline formattingh1
,h2
, ...,h6
– headings, in default toolbar only h1-h4 headings are displayedlink
– link editorblockquote
– blockquotesub
,sup
– super and sub scriptsvideo
,image
– video and image embedsunorderedList
,orderedList
– ul and ol tagsalignCenter
,alignLeft
,alignRight
– controls text-align
You can add, remove and configure controls arrangement in toolbar with controls
prop:
<RichTextEditorcontrols={[['bold', 'italic', 'underline', 'link', 'image'],['unorderedList', 'h1', 'h2', 'h3'],['sup', 'sub'],['alignLeft', 'alignCenter', 'alignRight'],]}/>
To configure sticky toolbar properties set following props:
sticky
– set to false to make toolbar stay at the topstickyOffset
– top property, used with sticky position, use it to offset elements with fixed position, for example, Mantine docs website has 60px header, in this case you should set stickyOffset to 60
// Toolbar stays at the top<RichTextEditor sticky={false} />// Toolbar position is set to sticky with top: 40px<RichTextEditor stickyOffset={40} />
Images and videos embeds
Images upload
RichTextEditor will handle images upload in following situations:
- Image button click in toolbar
- Image was pasted from clipboard into editor
- Image was dropped into editor
To set up images upload add onImageUpload
function:
import { useState } from 'react';import { RichTextEditor } from '@mantine/rte';// Example with imgbb.com, usually you would use similar logic to upload to S3 like storages// Function must return a promise that resolves with uploaded image url// After promise is resolved blurred image placeholder with be replaced with uploadedconst handleImageUpload = (file: File): Promise<string> =>new Promise((resolve, reject) => {const formData = new FormData();formData.append('image', file);fetch('https://api.imgbb.com/1/upload?key=api_key', {method: 'POST',body: formData,}).then((response) => response.json()).then((result) => resolve(result.data.url)).catch(() => reject(new Error('Upload failed')));});function Demo() {const [value, onChange] = useState('');return <RichTextEditor value={value} onChange={onChange} onImageUpload={handleImageUpload} />;}
Important! If you do not provide onImageUpload
all images will be converted to
base64 format. In most cases this is not a valid option to store images so make sure you provide onImageUpload
if you are planning to use images.
Keyboard shortcuts
⌘ + B
/Ctrl + B
– toggle bold format in current selection⌘ + I
/Ctrl + I
– toggle italic format in current selection⌘ + U
/Ctrl + U
– toggle underline format in current selection⌘ + K
/Ctrl + K
– add link to current selection⌘ + option + 1
/Ctrl + Alt + 1
– toggle heading at current line, valid for 1-6 headings
Server side rendering
Quill does not support server side rendering as it relies on browser API. To make component work on server you will need to create a wrapper component with additional checks.
General strategy:
// Create a separate component which will load RichTextEditor only in browserimport React from 'react';import type { RichTextEditorProps } from '@mantine/rte';export function RichText(props: RichTextEditorProps) {if (typeof window !== 'undefined') {// eslint-disable-next-line import/extensions, global-requireconst { RichTextEditor } = require('@mantine/rte');return <RichTextEditor {...props} />;}// Render anything as fallback on server, e.g. loader or html content without editorreturn null;}
Usage with Next.js
To make component work with Next.js use dynamic module:
// RichText.tsx in your components folderimport dynamic from 'next/dynamic';export default dynamic(() => import('@mantine/rte'), {// Disable during server side renderingssr: false,// Render anything as fallback on server, e.g. loader or html content without editorloader: () => null,});
Then when you want to use RichTextEditor import your component instead:
import RichTextEditor from '../components/RichText';function MyPage() {return <RichTextEditor />;}