mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-22 19:02:31 +01:00
Lexical: Refined editor UI
- Cleaned up dropdown lists to look integrated - Added icons for color picker clear and menu list items
This commit is contained in:
parent
fd07aa0f05
commit
fb49371c6b
1
resources/icons/editor/color-clear.svg
Normal file
1
resources/icons/editor/color-clear.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path d="M800-436q0 36-8 69t-22 63l-62-60q6-17 9-34.5t3-37.5q0-47-17.5-89T650-600L480-768l-88 86-56-56 144-142 226 222q44 42 69 99.5T800-436Zm-8 380L668-180q-41 29-88 44.5T480-120q-133 0-226.5-92.5T160-436q0-51 16-98t48-90L56-792l56-56 736 736-56 56ZM480-200q36 0 68.5-10t61.5-28L280-566q-21 32-30.5 64t-9.5 66q0 98 70 167t170 69Zm-37-204Zm110-116Z"/></svg>
|
After Width: | Height: | Size: 422 B |
@ -11,6 +11,7 @@
|
||||
## Secondary Todo
|
||||
|
||||
- Color picker support in table form color fields
|
||||
- Color picker for color controls
|
||||
- Table caption text support
|
||||
- Support media src conversions (https://github.com/tinymce/tinymce/blob/release/6.6/modules/tinymce/src/plugins/media/main/ts/core/UrlPatterns.ts)
|
||||
|
||||
|
@ -347,6 +347,7 @@ export const deleteColumn: EditorButtonDefinition = {
|
||||
|
||||
export const cellProperties: EditorButtonDefinition = {
|
||||
label: 'Cell properties',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.getEditorState().read(() => {
|
||||
const cell = $getNodeFromSelection($getSelection(), $isCustomTableCellNode);
|
||||
@ -361,6 +362,7 @@ export const cellProperties: EditorButtonDefinition = {
|
||||
|
||||
export const mergeCells: EditorButtonDefinition = {
|
||||
label: 'Merge cells',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
@ -377,6 +379,7 @@ export const mergeCells: EditorButtonDefinition = {
|
||||
|
||||
export const splitCell: EditorButtonDefinition = {
|
||||
label: 'Split cell',
|
||||
format: 'long',
|
||||
action(context: EditorUiContext) {
|
||||
context.editor.update(() => {
|
||||
$unmergeCell();
|
||||
|
@ -3,6 +3,8 @@ import {$getSelection} from "lexical";
|
||||
import {$patchStyleText} from "@lexical/selection";
|
||||
import {el} from "../../../utils/dom";
|
||||
|
||||
import removeIcon from "@icons/editor/color-clear.svg";
|
||||
|
||||
const colorChoices = [
|
||||
'#000000',
|
||||
'#ffffff',
|
||||
@ -52,11 +54,13 @@ export class EditorColorPicker extends EditorUiElement {
|
||||
});
|
||||
});
|
||||
|
||||
colorOptions.push(el('div', {
|
||||
const removeButton = el('div', {
|
||||
class: 'editor-color-select-option',
|
||||
'data-color': '',
|
||||
title: 'Clear color',
|
||||
}, ['x']));
|
||||
}, []);
|
||||
removeButton.innerHTML = removeIcon;
|
||||
colorOptions.push(removeButton);
|
||||
|
||||
const colorRows = [];
|
||||
for (let i = 0; i < colorOptions.length; i+=5) {
|
||||
|
@ -2,6 +2,7 @@ import {handleDropdown} from "../helpers/dropdowns";
|
||||
import {EditorContainerUiElement, EditorUiElement} from "../core";
|
||||
import {EditorBasicButtonDefinition, EditorButton} from "../buttons";
|
||||
import {el} from "../../../utils/dom";
|
||||
import {EditorMenuButton} from "./menu-button";
|
||||
|
||||
export type EditorDropdownButtonOptions = {
|
||||
showOnHover?: boolean;
|
||||
@ -29,7 +30,8 @@ export class EditorDropdownButton extends EditorContainerUiElement {
|
||||
if (options.button instanceof EditorButton) {
|
||||
this.button = options.button;
|
||||
} else {
|
||||
this.button = new EditorButton({
|
||||
const type = options.button.format === 'long' ? EditorMenuButton : EditorButton;
|
||||
this.button = new type({
|
||||
...options.button,
|
||||
action() {
|
||||
return false;
|
||||
|
15
resources/js/wysiwyg/ui/framework/blocks/menu-button.ts
Normal file
15
resources/js/wysiwyg/ui/framework/blocks/menu-button.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {EditorButton} from "../buttons";
|
||||
import {el} from "../../../utils/dom";
|
||||
import arrowIcon from "@icons/chevron-right.svg"
|
||||
|
||||
export class EditorMenuButton extends EditorButton {
|
||||
protected buildDOM(): HTMLButtonElement {
|
||||
const dom = super.buildDOM();
|
||||
|
||||
const icon = el('div', {class: 'editor-menu-button-icon'});
|
||||
icon.innerHTML = arrowIcon;
|
||||
dom.append(icon);
|
||||
|
||||
return dom;
|
||||
}
|
||||
}
|
10
resources/js/wysiwyg/ui/framework/blocks/separator.ts
Normal file
10
resources/js/wysiwyg/ui/framework/blocks/separator.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {EditorUiElement} from "../core";
|
||||
import {el} from "../../../utils/dom";
|
||||
|
||||
export class EditorSeparator extends EditorUiElement {
|
||||
buildDOM(): HTMLElement {
|
||||
return el('div', {
|
||||
class: 'editor-separator',
|
||||
});
|
||||
}
|
||||
}
|
@ -65,6 +65,7 @@ import {
|
||||
} from "./defaults/buttons/objects";
|
||||
import {el} from "../utils/dom";
|
||||
import {EditorButtonWithMenu} from "./framework/blocks/button-with-menu";
|
||||
import {EditorSeparator} from "./framework/blocks/separator";
|
||||
|
||||
export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
return new EditorSimpleClassContainer('editor-toolbar-main', [
|
||||
@ -83,7 +84,7 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
new FormatPreviewButton(el('h5'), h5),
|
||||
new FormatPreviewButton(el('blockquote'), blockquote),
|
||||
new FormatPreviewButton(el('p'), paragraph),
|
||||
new EditorDropdownButton({button: {label: 'Callouts'}, showOnHover: true, direction: 'vertical'}, [
|
||||
new EditorDropdownButton({button: {label: 'Callouts', format: 'long'}, showOnHover: true, direction: 'vertical'}, [
|
||||
new FormatPreviewButton(el('p', {class: 'callout info'}), infoCallout),
|
||||
new FormatPreviewButton(el('p', {class: 'callout success'}), successCallout),
|
||||
new FormatPreviewButton(el('p', {class: 'callout warning'}), warningCallout),
|
||||
@ -125,37 +126,41 @@ export function getMainEditorFullToolbar(): EditorContainerUiElement {
|
||||
]),
|
||||
|
||||
// Insert types
|
||||
new EditorOverflowContainer(8, [
|
||||
new EditorOverflowContainer(4, [
|
||||
new EditorButton(link),
|
||||
|
||||
new EditorDropdownButton({button: table, direction: 'vertical'}, [
|
||||
new EditorDropdownButton({button: {...table, format: 'long'}, showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Insert', format: 'long'}, showOnHover: true}, [
|
||||
new EditorTableCreator(),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Cell'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorSeparator(),
|
||||
new EditorDropdownButton({button: {label: 'Cell', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton(cellProperties),
|
||||
new EditorButton(mergeCells),
|
||||
new EditorButton(splitCell),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Row'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Row', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton({...insertRowAbove, format: 'long'}),
|
||||
new EditorButton({...insertRowBelow, format: 'long'}),
|
||||
new EditorButton({...deleteRow, format: 'long'}),
|
||||
new EditorButton(rowProperties),
|
||||
new EditorSeparator(),
|
||||
new EditorButton(cutRow),
|
||||
new EditorButton(copyRow),
|
||||
new EditorButton(pasteRowBefore),
|
||||
new EditorButton(pasteRowAfter),
|
||||
]),
|
||||
new EditorDropdownButton({button: {label: 'Column'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorDropdownButton({button: {label: 'Column', format: 'long'}, direction: 'vertical', showOnHover: true}, [
|
||||
new EditorButton({...insertColumnBefore, format: 'long'}),
|
||||
new EditorButton({...insertColumnAfter, format: 'long'}),
|
||||
new EditorButton({...deleteColumn, format: 'long'}),
|
||||
new EditorSeparator(),
|
||||
new EditorButton(cutColumn),
|
||||
new EditorButton(copyColumn),
|
||||
new EditorButton(pasteColumnBefore),
|
||||
new EditorButton(pasteColumnAfter),
|
||||
]),
|
||||
new EditorSeparator(),
|
||||
new EditorButton({...tableProperties, format: 'long'}),
|
||||
new EditorButton(clearTableFormatting),
|
||||
new EditorButton(resizeTableToContents),
|
||||
|
@ -70,12 +70,18 @@ body.editor-is-fullscreen {
|
||||
.editor-button-text {
|
||||
font-weight: 400;
|
||||
color: #000;
|
||||
font-size: 12.2px;
|
||||
font-size: 14px;
|
||||
flex: 1;
|
||||
padding-inline-end: 4px;
|
||||
}
|
||||
.editor-button-format-preview {
|
||||
padding: 4px 6px;
|
||||
display: block;
|
||||
}
|
||||
.editor-button-long .editor-button-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.editor-button-icon svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@ -83,6 +89,13 @@ body.editor-is-fullscreen {
|
||||
fill: currentColor;
|
||||
display: block;
|
||||
}
|
||||
.editor-menu-button-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
svg {
|
||||
fill: #888;
|
||||
}
|
||||
}
|
||||
.editor-button-with-menu-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -126,6 +139,7 @@ body.editor-is-fullscreen {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
min-width: 160px;
|
||||
}
|
||||
.editor-dropdown-menu-vertical .editor-button {
|
||||
border-bottom: 0;
|
||||
@ -138,9 +152,17 @@ body.editor-is-fullscreen {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.editor-separator {
|
||||
display: block;
|
||||
height: 1px;
|
||||
background-color: #DDD;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.editor-format-menu-toggle {
|
||||
width: 130px;
|
||||
height: 32px;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
padding-inline: 12px;
|
||||
justify-content: start;
|
||||
@ -154,6 +176,9 @@ body.editor-is-fullscreen {
|
||||
.editor-dropdown-menu {
|
||||
min-width: 220px;
|
||||
}
|
||||
.editor-button-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.editor-format-menu .editor-dropdown-menu .editor-dropdown-menu-container > .editor-button {
|
||||
padding: 8px 10px;
|
||||
@ -259,6 +284,9 @@ body.editor-is-fullscreen {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.editor-color-select-option:hover {
|
||||
border-radius: 3px;
|
||||
@ -266,6 +294,11 @@ body.editor-is-fullscreen {
|
||||
z-index: 3;
|
||||
box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.editor-color-select-option[data-color=""] svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
fill: #888;
|
||||
}
|
||||
.editor-table-creator-row {
|
||||
display: flex;
|
||||
}
|
||||
@ -422,7 +455,9 @@ body.editor-is-fullscreen {
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
// Editor form elements
|
||||
/**
|
||||
* Form elements
|
||||
*/
|
||||
.editor-form-field-wrapper {
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user