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.
- 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.
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.
Fire up your terminal and create a new react project with create-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 directory we’ll create two files called
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.
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.
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?
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
onChangeevent listener is listening for keyboard events
- After catching a keystroke.
- We update the current state with the new keystroke
- dispatch the new state.
- 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:
- Listen for events/key strokes.
2. Distinguish the keys pressed, was it a
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.
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.
Editor component has a prop called
renderMark which accepts a callback. Inside the
renderMark we can decide how to style the text.
Go on, try it out! Select the text and press
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
To top it off, can you do the same functionality but for italic?