gtgalone / react-quilljs

React Hook Wrapper for Quill, powerful rich text editor.
https://www.npmjs.com/package/react-quilljs
MIT License
248 stars 28 forks source link

How to add undo/redo buttons to toolbar #35

Closed DaltheCow closed 3 years ago

DaltheCow commented 3 years ago

I've been following along with this trying to get undo and redo into the toolbar but I'm running into complications figuring out how to set this up.

const modules = {
    toolbar: {
      container: "#toolbar",
      handlers: {
        undo: undoChange,
        redo: redoChange
      }
    },
    history: {
      delay: 500,
      maxStack: 100,
      userOnly: true
    }
  };
  const { quill, quillRef, Quill } = useQuill({
    theme,
    modules,
    formats,
  });

  function undoChange() {
    quill?.history.undo();
  }
  function redoChange() {
    quill?.history.redo();
  }

This is the approach that would follow when attempting the react-quill solution but it doesn't yet work with hooks and react-quilljs. I'm not sure how to work around needing to define the handler functions in modules before "quill" exists

gtgalone commented 3 years ago

@DaltheCow Thank you for using.

You should not forget to add also in formats.

https://github.com/gtgalone/react-quilljs#with-custom-options

And please check it out

https://codesandbox.io/s/react-quilljs-basic-forked-32x6n

https://quilljs.com/docs/modules/toolbar/#handlers

If you don't get the way after trying it out, Let me know. I will write the way.

DaltheCow commented 3 years ago

I have a working solution now! Typescript is very mad about this.quill.history.undo() but I think I can manage that. I decided to use the handlers in the end instead of adding an onClick since that seems to be the recommended method. Thank you! Here are the important bits for posterity:

  const modules = {
    toolbar: {
      container: "#toolbar",
      handlers: {
        undo: function () {
          this.quill?.history?.undo();
        },
        redo: function () {
          this.quill?.history?.redo();
        },
      },
    },
    history: {
      delay: 500,
      maxStack: 100,
      userOnly: true,
    },
  };
  const { quill, quillRef, Quill } = useQuill({
    // your theme,
    modules,
    // your formats,
  });

And I render something like this:

const CustomUndo = () => (
  <svg viewBox="0 0 18 18">
    <polygon className="ql-fill ql-stroke" points="6 10 4 12 2 10 6 10" />
    <path
      className="ql-stroke"
      d="M8.09,13.91A4.6,4.6,0,0,0,9,14,5,5,0,1,0,4,9"
    />
  </svg>
);

const CustomRedo = () => (
  <svg viewBox="0 0 18 18">
    <polygon className="ql-fill ql-stroke" points="12 10 14 12 16 10 12 10" />
    <path
      className="ql-stroke"
      d="M9.91,13.91A4.6,4.6,0,0,1,9,14a5,5,0,1,1,5-5"
    />
  </svg>
);
<div id="toolbar">
  <span className="ql-formats">
    <select className="ql-font" defaultValue="arial">
      <option value="arial">Arial</option>
      <option value="comic-sans">Comic Sans</option>
      <option value="courier-new">Courier New</option>
      <option value="georgia">Georgia</option>
      <option value="helvetica">Helvetica</option>
      <option value="lucida">Lucida</option>
    </select>
  </span>
  <span className="ql-formats">
    <button className="ql-undo">
      <CustomUndo />
    </button>
    <button className="ql-redo">
      <CustomRedo />
    </button>
  </span>
</div>
<div ref={quillRef} />

Note: I did not include <div id="editor" /> which I saw in examples, didn't seem to serve any purpose. Not sure if it is there for ssr purposes or what but what I have looks to be working fine as is