typewriter-editor / typewriter

A rich text editor based off of Quill.js and Ultradom, and using Svelte for UI.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hover menu and toolbar should be configurable

scarroll32 opened this issue · comments

commented

We should be able to pass in a hash of configuration for the toolbar / hover menu.

The Quill model is a good place to start:

var toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
  ['blockquote', 'code-block'],

  [{ 'header': 1 }, { 'header': 2 }],               // custom button values
  [{ 'list': 'ordered'}, { 'list': 'bullet' }],
  [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
  [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
  [{ 'direction': 'rtl' }],                         // text direction

  [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
  [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

  [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
  [{ 'font': [] }],
  [{ 'align': [] }],

  ['clean']                                         // remove formatting button
];

Think this makes perfect sense for now, can win quill devotees over in the future perhaps

I've decided to not go with the restrictive JSON config approach so creators can have more flexibility in their editors. I've gone with renderless Svelte components. Here is a toolbar:

<script>
import { Editor } from 'typewriter-editor';
import Root from 'typewriter-editor/lib/Root.svelte';
import Toolbar from 'typewriter-editor/lib/Toolbar.svelte';

const editor = new Editor();
</script>

<Toolbar {editor} let:active let:commands>
  <div class="toolbar">
    <button
      class="toolbar-button material-icons"
      class:active={active.header === 2}
      on:click={commands.header2}>title</button>

    <button
      class="toolbar-button material-icons header3"
      class:active={active.header === 3}
      on:click={commands.header3}>title</button>

    <button
      class="toolbar-button material-icons"
      class:active={active.bold}
      on:click={commands.bold}>format_bold</button>

    <button
      class="toolbar-button material-icons"
      class:active={active.italic}
      on:click={commands.italic}>format_italic</button>

    <button
      class="toolbar-button material-icons"
      disabled={!active.undo}
      on:click={commands.undo}>undo</button>

    <button
      class="toolbar-button material-icons"
      disabled={!active.redo}
      on:click={commands.redo}>redo</button>
  </div>
</Toolbar>

<div use:asRoot={editor}></div>

<style>
.toolbar {
  display: flex;
  background: #eee;
  padding: 8px;
  margin-bottom: 8px;
  border-radius: 3px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 2px 6px rgba(0, 0, 0, .1);
}
.toolbar-button {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
  margin: 0;
  width: 40px;
  height: 40px;
  margin-right: 4px;
  border-radius: 4px;
  border: 1px solid #ced4da;
  transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
  cursor: pointer;
}
.toolbar-button:hover {
  outline: none;
  border-color: #80bdff;
  box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}
.toolbar-button.active {
  border-color: #80bdff;
  background: #eaf4ff;
}
</style>

Becomes:

Screen Shot 2021-01-19 at 3 14 55 PM

There are also renderless components for:

BubbleMenu

Screen Shot 2021-01-19 at 3 16 09 PM

InlineMenu

Screen Shot 2021-01-19 at 3 16 30 PM

which are both common UI elements. We could create some default implementations for those who want out-of-the-box solutions, but I didn't want the default to be a restrictive UI that you then had to fight to replace with your own.