Hover menu and toolbar should be configurable
scarroll32 opened this issue · comments
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:
There are also renderless components for:
BubbleMenu
InlineMenu
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.