Let’s build a customizable rich text editor with Slate and React

July 15, 2018 0 Comments

Let’s build a customizable rich text editor with Slate and React



A rich text editor’s aim is to reduce the effort for users trying to express their formatting as valid HTML markup. A rich text editor enables the users the option to format their text.

Everyone has used a rich text editor at some point. So why not build one? Here are some most used rich text editor examples.

  • Reddit, YouTube, hacker news comments.
Reddit comments section
  • Online editors for producing content — writing blogs, tutorials, news, etc.
  • Twitter tweets, mentions, hashtags, polls, lists, etc.
  • Editing documents and excel sheets like Google docs, Microsoft Word, Dropbox paper.

2016 — Facebook open sourced their new rich text editor framework called Draft.js


Here’s the Draft.js introductory talk. Worth the 25 minutes to understand what kind of problems the facebook team ran into and solved.

Here’s hacker news thread discussion about Slate.js.

Slate.js: Customizeable rich text library inspired by Draft.js

The arguments for creating Slate are sound. Let’s check it out by creating a rich text editor.

What we will be needing for this project are the following:

  • Text editor, any will do, feel free to choose.
  • NodeJS installed with NPM/Yarn.
  • Basic JavaScript knowledge. If you’re learning the ropes — This list for learning JavaScript might be useful to you. Don’t feel dissuaded, everyone should join in! 🙂

Let’s gooooo!

Fire up your terminal and create a new react project with create-react-app.

Booting up our React app

Slate exposes a set of modules that you’ll use to build your editor. The most important of which is the Editor component. The Editor component is the fundamental layer everything will be built upon. Think of it as the root component for the whole editor.

Starting off we will create a folder components— Inside components directory we’ll create two files called index.js and TextEditor.js

If we open the browser, this is what we should see.

No problem! The Editor component expects an initial value — as can be seen from the source code.

See the last propType — it’s set to isRequired

Let’s add our initial value to the editor. We’ll dive into the exact model of the data later once we have a basic understand how slate works.

We should end up with My first paragraph! rendered on our app.

A paragraph being rendered

At first the text looks like a simple <p> paragraph. But if we inspect the element, there’s an ocean of complexity abstracted away from us.

Try clicking on the text. What do you see?

Editable text — notice the complex hierarchy of DOM elements. This is all abstracted away from us under the hood and we can focus on building our “product”

The text is editable! Woah! In case you don’t have the React developer tools, here’s a link to the chrome app store.

Note: Remember we added a onChange event listener to our Editor component,

  1. The onChange event listener is listening for keyboard events
  2. After catching a keystroke.
  3. We update the current state with the new keystroke
  4. dispatch the new state.
  5. Render new state on the screen.

Although, the editor is not very much useful to us yet. We’re missing key features like formatting, saving our text somewhere and many more.

It’s common to have a big header, sub header, italic, bold, code, etc formatted text.

Think about — what are the steps for formatting text?

Common practice is to start with pressing a command key like ctrl or cmd. Pressing the command key tells editor we’re editing and not typing.

For example, what we could do is the following: cmd ⌘+ b or alt + b is for adding bold to our selected text.

Our flow will look this:

  1. Listen for events/key strokes.

2. Distinguish the keys pressed, was it a alt, cmd or b and in what order? And what happens if indeed those were the keys pressed?

3. Trigger the actual text change with the desired formatting.

Let’s goo — start by adding a onKeyDown event for the Editor and pass in the callback.

Adding the onKeyDown event listener

We know what key the user pressed. Let’s make something happen depending on which keystroke is being pressed.

Good, now we have all the logic in place. If the user pressed alt + b, change the text to bold. How do you think we should approach the styling?

One way to go is to create a new reusable component called BoldMark.js which we can reuse every time we want bold text.

Creating a reusable component for bold text
importing and exporting the new component

The Editor component has a prop called renderMark which accepts a callback. Inside the renderMark we can decide how to style the text.

Importing the BoldMark component

Go on, try it out! Select the text and press alt + b

Wohoo, it works! Notice the BoldMark component being rendered inside the VDOM.

There’s an open question in the air, what happens if we change our mind? We want to undo the boldness.

Slate has you covered! Instead of adding the addMark(‘bold’ ) — we can use toggleMark(‘bold’)

Notice the toggleMark method instead addMark
Testing our toggleMark method in the browser

To top it off, can you do the same functionality but for italic?

Tag cloud