43

Let’s build a fast, slick and customizable rich text editor with Slate and React...

 5 years ago
source link: https://www.tuicool.com/articles/hit/nuIFfur
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Full speed ahead

The editor has to look sharp. Who wants to stare and use a scruffy editor? So why don’t we add some quick CSS to make it look more spectacular.

In a traditional create-react-app, we have the index.css file inside the src folder. index.css is used for applying “global” styles for our app. By global styles I’m keeping in mind DOM elements which apply to all pages/documents. For example body and html

yy2IRf3.png!web
Applying system fonts, background colors, paddings, margins, colors and the width for our editor.

If you’re curious about what kind of “shenanigans” is going on with the font-family

We are defaulting to the font (s) the user has installed on their computer. This has many performance boosts since there is no need to download the fonts.

Check out this clever explanation by css-tricks for more in detail.

We should end up with something more smart. :sweat_smile:

JRJ3amA.gif
Our freshly minted app

What are some of the key features a rich text editor has? Hmm — let’s see.

  • Images
  • Headers
  • Code highlighting
  • Embedded Videos
  • Text formatting (alignment, bullet list, ordered list, etc)
  • Save the text to a database for safe keeping
  • Links

Let’s start by adding the images.

Rich text editors have a toolbar which eases the efforts of editing. Take a look at Medium’s toolbar.

Mruu636.png!web
Medium’s toolbar for formatting

When we click on a selected text, a popup toolbar pops up from the ashes which allows us to format our text.

It makes sense to start implementing the toolbar first and then hook it up with the appropriate functionality.

Let’s grab a small library which enables us access to a huge array of icons.

ZzeuauE.png!web
7fMFJfJ.png!web

The icons we want to use are feather icons.

ZNNnYnV.png!web
https://feathericons.com/

I propose creating a component which holds all the formatting logic and styles in place. Call it FormatToolbar.js and place it inside components

fM36V3E.png!web
ZRrmUrr.png!web

The FormatToolbar is a stateless component which which render its content thanks to using props.children

A stateless component is a component which doesn’t make use of the this.state mechanism but rather let’s it parent figure out the state.

Think of it this way; We want to separate concerns as much as possible. A stateless component handles rendering the view ( divs , spans , images ) and only the view.

A stateful containers takes care of it’s internal state and passes it as props to the stateless components.

props.children allows you nest components inside a component.

if you’re unsure about props.children — this article is good at explaining the concept behind children props in React. :v:

Next up, we will import FormatToolbar.js component to our TextEditor.js

jIB32az.png!web
Importing our icons to the TextEditor component

And finally, consume our FormatToolbar like this:

vYZ7JbM.png!web
Passing our toolbar component to the editor render function

Oh and I also added some styles to make it look neat. Remember, The .format-toolbar is our container component which holds all the icons. We set it to flex so they’re all nicely aligned in a row and start from the left. We also removed the default border from our button since we’re going for the clean/minimalist approach.

beyiiiq.png!web
Applying styles to our tooltip

Terminology: The toolbar is the full row and the tooltip is a single item/collection.

zeYNruM.png!web
What gets rendered on the screen

Woah! Starts to look like an actual rich text editor! Well done! Allow yourself a fresh coffee and let’s get right back to tackling with our app!

There’s no shortage of remarkable ideas, what’s missing is the will to execute them. — Seth Godin

One finds limits by pushing them

Clicking on the icons have no affect since we didn’t add a single event listener to our icons.

Time to change that. The goal of this tutorial is teach how to approach problems and how to solve them. Solving complex problems are very challenging. An ubiquitous approach to problem solving is breaking the problem apart to small solvable pieces.

Think about it — what are missing? We have the formatting functionality in place, the icons and the styling.

You guessed it, we need to bundle icons and text together. By clicking on the icon, we want to format our text.

Let’s start by adding a event listener on the button. Which event listener should we use? There are bazillion options out there like onClick , onMouseDown , touchend

Good question and I’m glad you asked. We’re going to use a new event listener which was introduced in React version 16.4 . The event listener has a particular name — pointer event .

I wrote this brief introduction to pointer events . In a nutshell, instead of writing an event listener for the mouse, touch surface and the pen we use a different approach. That approach uses the all 3-in-1 solution, compatible with all devices.

nM7bUbJ.png!web
Browser support for the pointer events

The pointer is like any event, just attach it to your button like so;

RjMZbqZ.png!web
Adding pointer events to our buttons

The onPointerDown is fired just like onMouseDown

Notice we added a callback with the name onMarkClick. The first argument is the event object and the second argument type is the formatting we want to apply.

7na6Nnr.png!web
onMarkClick method

Don’t be startled, the comments make it seem bloated. The only functionality we applied was the following;

1. Cancel the browser default behavior

2. Get the this.state.value — remember this is the initial value we passed to Slate. The slate model has built in functions, just like mongoose.

3. Apply the formatting on the selected text with the desired format.

4. Finally call an update on the component to display the newly made changes.

VFv6Vjz.gif
Clicking on the icon changes our text

Marvellous!

Let’s finish up by adding some final touches. We’ll be adding code formatting, lists, and underlining functionality. Try following our examples and finish it up.

NNF73ea.png!web
eAnQJjn.png!web
onKeyDown the left and renderMark the right
qiq6naM.png!web
importing icons

And finally, creating our elements inside the render

Z3AZzmj.png!web

Wohop! We made it. Time for the long-awaited dopamine hit.

Q7vIjmf.gif

The editor already looks like a tool we use everyday. Notice the elements being placed and removed in the vDOM — React takes care of this for you.

Congratulations for making to the end. If you would like me to add more features, let me know on twitter or at the discussion section.

Thanks for reading! ❤


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK