react-quill icon indicating copy to clipboard operation
react-quill copied to clipboard

Adding custom fonts(or any custom functionality) with NextJS

Open ejkkan opened this issue 1 year ago • 9 comments

  • [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.
);

ejkkan avatar Jun 28 '23 07:06 ejkkan

Any takers on this?

ejkkan avatar Jun 29 '23 20:06 ejkkan

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
);

ejkkan avatar Jun 30 '23 08:06 ejkkan

There is any complete solution to this issue?

luciamvm avatar Aug 31 '23 12:08 luciamvm

Use dynamic import. It won't work server side unfortunately

ejkkan avatar Aug 31 '23 13:08 ejkkan

@ejkkan Can you share the whole code as to how you solved this issue in Next.js?

SurajanShrestha avatar Jan 17 '24 11:01 SurajanShrestha

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?

horia-ologu avatar May 28 '24 08:05 horia-ologu

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.

t-ashraf avatar May 28 '24 08:05 t-ashraf

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

SolmazPoursiaban avatar Jul 12 '24 21:07 SolmazPoursiaban