react-quill
react-quill copied to clipboard
Adding custom fonts(or any custom functionality) with NextJS
- [x] I have verified that the issue persists under ReactQuill
v2.0.0-beta.2
ReactQuill version
- [ ] master
- [x] v2.0.0-beta.2
- [ ] v2.0.0-beta.1
- [ ] 1.3.5
- [ ] 1.3.4 or older
- [ ] Other (fork)
I've tried the proposed solutions from other threads(for example this) but adding custom properties does not seem to be handled.
Code example:
loading react-quill dynamically
const ReactQuill = dynamic(
import('react-quill').then((mod) => {
const Quill = mod.default.Quill;
var Font = Quill.import('formats/font');
Quill.register(Font, true);
return mod;
}),
{ ssr: false }
);
Modules
const modules = {
toolbar: [
[
{
font: [
'monospace',
'serif',
'raleway',
'montserrat',
'lato',
'rubik',
'roboto'
],
},
],
],
};
Usage:
<ReactQuill
theme="snow"
value={value}
modules={modules}
bounds={'.app'}
formats={formats}
onChange={(content) => {
console.log(content);
}}
/>
I've also added the necessary css for fonts and styling:
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;700&display=swap');
/* Set content font-families */
.ql-font-Roboto {
font-family: 'Roboto';
}
.ql-font-Raleway {
font-family: 'Raleway';
}
.ql-font-Montserrat {
font-family: 'Montserrat';
}
.ql-font-Lato {
font-family: 'Lato';
}
.ql-font-Rubik {
font-family: 'Rubik';
}
Still this shows 'Sens Serif', as I guess this is the fallback font, for all instances. Testing some the CSS hacks in the mentioned thread, I can get them to change to their proper names. However, if I use any other fonts than the three default ones(serif, monspace and sans serif), the onChange
is not triggered by any change except for the three default ones.
Has anyone got react-quill working properly with NextJS?
I have even tried to apply the whitelist in the dynamic load without any success:
const ReactQuill = dynamic(
import('react-quill').then(async (mod) => {
const { default: RQ } = await import('react-quill');
var Font = RQ.Quill.import('formats/font');
Font.whitelist = [
'monospace',
'serif',
'raleway',
'montserrat',
'lato',
'rubik',
'roboto'
];
const modules = {
toolbar: [[{ font: Font.whitelist }]],
};
RQ.Quill.register(Font, true);
return ({ forwardedRef, ...props }) => (
<RQ modules={modules} ref={forwardedRef} {...props} />
);
}),
{ ssr: false } // This line is important. It's needed to disable server-side render for this component.
);
Any takers on this?
Solved by using the component with dynamic import to make the component CSR:
const TextEditCsr = dynamic(
() => import('./TextEdit'),
{ ssr: false } // This will make the component only rendered on client-side
);
There is any complete solution to this issue?
Use dynamic import. It won't work server side unfortunately
@ejkkan Can you share the whole code as to how you solved this issue in Next.js?
I am also looking for a solution to customize fonts of ReactQuill in NextJS. Nothing seems to work at this time. I have tried playing around with the code above in quite a few possible solutions. I have also tried creating the client component separately and use the dynamc import, but I seem doing something wrong since @ejkkan managed to do it. I keep getting the Sans Serif replacing all custom fonts I am trying to add. Only the default 'Serif', 'Sans Serif' and 'Monospace' are working. Can anybody share a solution for this? Or, at least, how to customize the './TextEdit' component in order to load more fonts?
Here is a solution for custom fonts using Typescript:
Interface iFont.ts:
/**
* This interface is used by the WYSIWYG ToolbarFontFamilyDropdown
*/
interface IFont {
/**
* The font family
*/
family: string;
/**
* The ID used in CSS and data-* attributes
*/
id: string;
/**
* The display name
*/
name: string;
}
export default IFont;
File src/models/wysiwyg/index.ts:
import IFont from 'src/interfaces/component/iFont';
const fonts = new Array<IFont>(
{ family: 'Arial', id: 'arial', name: 'Arial' },
{ family: 'Comic Sans MS', id: 'comic-sans', name: 'Comic Sans' },
{ family: 'Courier New', id: 'courier-new', name: 'Courier New' },
{ family: 'Helvetica', id: 'helvetica', name: 'Helvetica' },
{ family: 'Inter', id: 'inter', name: 'Inter' },
{ family: 'Roboto Mono', id: 'roboto-mono', name: 'Roboto Mono' },
{ family: 'Times New Roman', id: 'times-new-roman', name: 'Times New Roman' },
{ family: 'Trebuchet MS', id: 'trebuchet-ms', name: 'Trebuchet MS' },
{ family: 'Verdana', id: 'verdana', name: 'Verdana' }
);
export { fonts };
ReactQuillWrapper.tsx which creates a React component with custom fonts:
import { Font, FontSize } from 'quill';
import MagicUrl from 'quill-magic-url';
import React from 'react';
import ReactQuill, { ReactQuillProps } from 'react-quill';
import { fonts } from 'src/models/wysiwyg';
type Props = ReactQuillProps & {
reactQuillRef?: React.Ref<ReactQuill>;
};
/**
* This is used to load react-quill server-side and useRefs client-side
*/
const ReactQuillWrapper = (props: Props) => {
const { reactQuillRef, ...args } = props;
const quill = ReactQuill.Quill;
const font = quill.import('formats/font') as Font;
font.whitelist = fonts.map((x) => x.id);
quill.register('modules/magicUrl', MagicUrl, true);
quill.register(font, true);
return <ReactQuill ref={reactQuillRef} {...args} />;
};
export default ReactQuillWrapper;
SSR Dynamic wrapper for NextJS ReactQuillDynamicWrapper.tsx:
import dynamic from 'next/dynamic';
const ReactQuillDynamicWrapper = dynamic(() => import('./ReactQuillWrapper'), {
ssr: false
});
ReactQuillDynamicWrapper.displayName = 'ReactQuillDynamicWrapper';
export default ReactQuillDynamicWrapper;
Hope this helps.
Here is my solution that worked for me: I registered my font in RQ.Quil as below (For now just Roboto font which I already installed in my project).
RichTextEditor.tsx file:
'use client';
import RQ from 'react-quill';
import './RichTextEditor.scss';
import React, { useEffect } from 'react';
import 'react-quill/dist/quill.snow.css';
const RichTextEditor = () => {
useEffect(() => {
const quill = RQ.Quill;
const Font = quill.import('formats/font');
Font.whitelist = ['roboto'];
quill.register(Font, true);
}, []);
const toolbarOptions = [[{ font: ['roboto'] }]];
return <RQ theme='snow' modules={{ toolbar: toolbarOptions }} />;
};
export default RichTextEditor;
In the SCSS file, I have defined a mixin to fix the issue with font option names. Previously, all unknown fonts for Quill were displayed as "Sans serif" option names. includes Roboto.
RichTextEditor.scss
@mixin ql-font($font-name) {
.ql-font-#{$font-name} {
@apply font-#{$font-name};
}
span[data-value='#{$font-name}']::before {
@apply capitalize;
content: '#{$font-name}' !important;
}
}
// Usage example
@include ql-font('roboto');
HomePage.tsx
import RichTextEditor from '@components/RichTextEditor/RichTextEditor';
const HomePage = ()=><RichTextEditor />
export default HomePage