Acknowledgement & Credit -
QuillEditor.constants.ts
export const TOOLBAR_ICONS = {
BOLD_ICON: `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="currentColor"><path d="M20.5 13.5C20.5 13.0404 20.4095 12.5852 20.2336... (truncated for brevity)
};
export const FORMATS = ['bold', 'italic', 'underline', 'link', 'list'];
export const TOOLBAR_ID = 'quill_toolbar_id';
export const MODULES = {
toolbar: `#${TOOLBAR_ID}`,
};
export const TEXT_AREA_HEIGHT = 200;
QuillEditorComponent.tsx
import dynamic from 'next/dynamic';
import { LegacyRef, JSX } from 'react';
import type ReactQuill from 'react-quill';
import { TOOLBAR_ICONS } from './QuillEditor.constants.ts';
interface IWrappedComponent extends React.ComponentProps<typeof ReactQuill> {
forwardedRef: LegacyRef<ReactQuill>;
}
const ReactQuillBase = dynamic(
async () => {
const { default: RQ } = await import('react-quill');
function QuillJS({ ...props }: React.ComponentProps<typeof ReactQuill>) {
const icons = RQ.Quill.import('ui/icons');
icons.bold = TOOLBAR_ICONS.BOLD_ICON;
icons.italic = TOOLBAR_ICONS.ITALIC_ICON;
icons.underline = TOOLBAR_ICONS.UNDERLINE_ICON;
icons.link = TOOLBAR_ICONS.LINK_ICON;
icons.list = {
bullet: TOOLBAR_ICONS.LIST_BULLETS_ICON,
ordered: TOOLBAR_ICONS.LIST_ORDERED_ICON,
};
return <RQ {...props} />;
}
return QuillJS;
},
{
ssr: false,
},
);
export function QuillEditorComponent(
params: JSX.IntrinsicAttributes &
IWrappedComponent & {
minHeight: number;
maxHeight: number;
},
) {
return (
<>
<ReactQuillBase {...params} />
</>
);
}
QuillToolbarComponent.tsx
import { TOOLBAR_ID } from './QuillEditor.constants';
// https://quilljs.com/docs/modules/toolbar/
export const QuillToolbarComponent = () => {
return (
<div id={TOOLBAR_ID}>
<div className="ql-formats">
<button className="ql-bold" />
<button className="ql-italic" />
<button className="ql-underline" />
<button className="ql-link" />
<button className="ql-list" value="bullet" />
<button className="ql-list" value="ordered" />
</div>
</div>
);
};
UsageExample.tsx
<>
<QuillToolbarComponent />
<QuillEditorComponent
forwardedRef={quillTextAreaRef}
defaultValue={quillValue as DeltaStatic}
onChange={handleChange}
modules={MODULES}
minHeight={TEXT_AREA_HEIGHT}
maxHeight={TEXT_AREA_HEIGHT}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
placeholder={placeholder}
onFocus={handleFocus}
formats={FORMATS}
/>
</>