From b070ce1cd3b8cc29b543db454e28b314b3fe298a Mon Sep 17 00:00:00 2001 From: Thibaud Colas Date: Wed, 13 Jul 2022 01:35:22 +0100 Subject: [PATCH] Add new Draftail toolbars and command palette, with new styles (#8806) --- CHANGELOG.txt | 2 + .../CommentableEditor/CommentableEditor.scss | 35 +++------ .../CommentableEditor/CommentableEditor.tsx | 4 +- client/src/components/Draftail/Draftail.scss | 71 ++++++++++++++----- .../Draftail/__snapshots__/index.test.js.snap | 14 ++-- client/src/components/Draftail/index.js | 30 +++++--- docs/releases/4.0.md | 2 + package-lock.json | 14 ++-- package.json | 2 +- .../templates/wagtailadmin/icons/bold.svg | 4 +- .../icons/comment-large-outline.svg | 5 -- .../icons/comment-large-reversed.svg | 5 -- .../wagtailadmin/icons/comment-large.svg | 4 -- .../admin/templates/wagtailadmin/icons/h1.svg | 1 + .../admin/templates/wagtailadmin/icons/h2.svg | 1 + .../admin/templates/wagtailadmin/icons/h3.svg | 1 + .../admin/templates/wagtailadmin/icons/h4.svg | 1 + .../admin/templates/wagtailadmin/icons/h5.svg | 1 + .../admin/templates/wagtailadmin/icons/h6.svg | 1 + .../templates/wagtailadmin/icons/italic.svg | 4 +- .../templates/wagtailadmin/icons/link.svg | 4 +- .../templates/wagtailadmin/icons/list-ol.svg | 4 +- .../templates/wagtailadmin/icons/list-ul.svg | 4 +- wagtail/admin/wagtail_hooks.py | 21 +++--- wagtail/documents/wagtail_hooks.py | 2 +- 25 files changed, 130 insertions(+), 107 deletions(-) delete mode 100644 wagtail/admin/templates/wagtailadmin/icons/comment-large-outline.svg delete mode 100644 wagtail/admin/templates/wagtailadmin/icons/comment-large-reversed.svg delete mode 100644 wagtail/admin/templates/wagtailadmin/icons/comment-large.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h1.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h2.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h3.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h4.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h5.svg create mode 100644 wagtail/admin/templates/wagtailadmin/icons/h6.svg diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 68f78d4e50..2ea43ff02a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -58,6 +58,8 @@ Changelog * Migrate the dashboard (home) view header to the shared header template and update designs (Paarth Agarwal) * Update classes and styles for the shared header templates to align with UI guidelines (Paarth Agarwal) * Clean up multiple eslint rules usage and configs to align better with the Wagtail coding guidelines (LB (Ben Johnston)) + * Add inline toolbar for Draftail, to avoid clashing with the page’s header (Thibaud Colas) + * Add command palette in rich text editor to change text format with the keyboard only (Thibaud Colas) * Add a live-updating character count to the Draftail rich text editor (Thibaud Colas) * Add rich text editor paste to auto-create links (Thibaud Colas) * Add rich text editor text shortcuts undo, to allow typing text normally detected as a shortcut (Thibaud Colas) diff --git a/client/src/components/Draftail/CommentableEditor/CommentableEditor.scss b/client/src/components/Draftail/CommentableEditor/CommentableEditor.scss index 1e649f8d49..7e93b14eb9 100644 --- a/client/src/components/Draftail/CommentableEditor/CommentableEditor.scss +++ b/client/src/components/Draftail/CommentableEditor/CommentableEditor.scss @@ -1,35 +1,16 @@ -.Draftail-Toolbar { - display: flex; - flex-wrap: wrap; - - .Draftail-ToolbarGroup:last-child { - flex-grow: 1; - } - - .Draftail-CommentControl { - float: right; - color: $color-teal; - } -} - .Draftail-CommentControl .Draftail-ToolbarButton { - .icon-comment-large-outline { - display: block; + color: theme('colors.teal.100'); + + .icon { + width: 1.875rem; + height: 1.875rem; } - .icon-comment-large-reversed { + &:not(:hover) .icon-comment-add-reversed { display: none; } - &:hover { - border-color: transparent; - - .icon-comment-large-outline { - display: none; - } - - .icon-comment-large-reversed { - display: block; - } + &:hover .icon-comment-add { + display: none; } } diff --git a/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx b/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx index db5093849c..2b9ffdbcb7 100644 --- a/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx +++ b/client/src/components/Draftail/CommentableEditor/CommentableEditor.tsx @@ -376,8 +376,8 @@ function getCommentControl( }`} icon={ <> - {' '} - + + } onClick={() => { diff --git a/client/src/components/Draftail/Draftail.scss b/client/src/components/Draftail/Draftail.scss index ed265c2482..90cfbaab55 100644 --- a/client/src/components/Draftail/Draftail.scss +++ b/client/src/components/Draftail/Draftail.scss @@ -1,13 +1,14 @@ $draftail-editor-text: $color-text-input; -$draftail-editor-chrome: $color-white; -$draftail-editor-chrome-text: $color-grey-2; -$draftail-editor-chrome-active: $color-grey-2; +$draftail-editor-chrome: theme('colors.primary.DEFAULT'); +$draftail-editor-chrome-text: $color-white; +$draftail-editor-chrome-active: $color-white; $draftail-editor-chrome-accent: transparent; +$draftail-base-spacing: 0.375rem; $draftail-editor-border: 0; $draftail-editor-padding: 0.75rem; -$draftail-editor-background: transparent; -$draftail-toolbar-radius: 3px; +$draftail-editor-background: $color-white; +$draftail-toolbar-radius: 5px; $draftail-toolbar-icon-size: 1em; $draftail-editor-font-family: $font-sans; @@ -74,10 +75,22 @@ $draftail-editor-font-family: $font-sans; } } -.Draftail-ToolbarButton .icon { - width: $draftail-toolbar-icon-size; - height: $draftail-toolbar-icon-size; - vertical-align: middle; +.Draftail-ToolbarButton, +.Draftail-ComboBox__option { + .icon { + width: $draftail-toolbar-icon-size; + height: $draftail-toolbar-icon-size; + vertical-align: middle; + } + + .icon-h1, + .icon-h2, + .icon-h3, + .icon-h4, + .icon-h5, + .icon-h6 { + width: 1.5 * $draftail-toolbar-icon-size; + } } // When in a .full container, the editor has a specific appearance @@ -108,7 +121,40 @@ $draftail-editor-font-family: $font-sans; border: 1px solid $color-grey-3; } +.Draftail-MetaToolbar { + visibility: hidden; + + .Draftail-Editor:focus-within &, + .Draftail-Editor:hover & { + visibility: visible; + } +} + +.Draftail-ComboBox__option-text { + @apply w-label-3; +} + +.Draftail-ToolbarGroup::before { + display: none; +} + +.Draftail-ToolbarGroup--controls::before { + display: inline-block; + height: 1.875rem; + background-color: $color-white; + opacity: 0.2; +} + .Draftail-ToolbarButton { + height: 1.875rem; + min-width: 1.875rem; + padding: 0; + margin-inline-end: 0.625rem; + + .Draftail-ToolbarGroup:last-of-type &:last-of-type { + margin-inline-end: 0; + } + &[disabled] { opacity: 0.3; } @@ -130,10 +176,3 @@ $draftail-editor-font-family: $font-sans; margin: 1em 0; padding: 1em 2em; } - -// Temporary workaround for Firefox bug where the placeholder hides the list item markers. -@supports (-moz-appearance: none) { - .Draftail-Placeholder { - display: none; - } -} diff --git a/client/src/components/Draftail/__snapshots__/index.test.js.snap b/client/src/components/Draftail/__snapshots__/index.test.js.snap index f73d3102da..b62a2e20a6 100644 --- a/client/src/components/Draftail/__snapshots__/index.test.js.snap +++ b/client/src/components/Draftail/__snapshots__/index.test.js.snap @@ -13,12 +13,12 @@ Object { "autoCorrect": null, "blockTypes": Array [], "bottomToolbar": [Function], + "commandPalette": [Function], "commandToolbar": [Function], - "commands": false, + "commands": true, "controls": Array [ Object { "meta": [Function], - "type": "MaxLength", }, ], "decorators": Array [], @@ -44,16 +44,12 @@ Object { "onChange": null, "onFocus": null, "onSave": [Function], - "placeholder": "Write here…", + "placeholder": "Write something or type ‘/’ to insert a block", "plugins": Array [], "rawContentState": null, "readOnly": false, - "showRedoControl": Object { - "description": "Redo", - }, - "showUndoControl": Object { - "description": "Undo", - }, + "showRedoControl": false, + "showUndoControl": false, "spellCheck": true, "stateSaveInterval": 250, "stripPastedStyles": false, diff --git a/client/src/components/Draftail/index.js b/client/src/components/Draftail/index.js index d07cc27c15..31f5b2c984 100644 --- a/client/src/components/Draftail/index.js +++ b/client/src/components/Draftail/index.js @@ -1,6 +1,11 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { DraftailEditor, MetaToolbar } from 'draftail'; +import { + DraftailEditor, + InlineToolbar, + MetaToolbar, + CommandPalette, +} from 'draftail'; import { Provider } from 'react-redux'; import { gettext } from '../../utils/gettext'; @@ -98,6 +103,7 @@ const initEditor = (selector, originalOptions, currentScript) => { const blockTypes = newOptions.blockTypes || []; const inlineStyles = newOptions.inlineStyles || []; const controls = newOptions.controls || []; + const commands = newOptions.commands || true; let entityTypes = newOptions.entityTypes || []; entityTypes = entityTypes.map(wrapWagtailIcon).map((type) => { @@ -107,30 +113,32 @@ const initEditor = (selector, originalOptions, currentScript) => { return { ...plugin, ...type }; }); - controls.push({ - type: 'MaxLength', - meta: MaxLength, - }); - return { rawContentState: rawContentState, onSave: serialiseInputValue, - placeholder: gettext('Write here…'), + placeholder: gettext('Write something or type ‘/’ to insert a block'), spellCheck: true, enableLineBreak: { description: gettext('Line break'), icon: BR_ICON, }, - bottomToolbar: MetaToolbar, - showUndoControl: { description: gettext('Undo') }, - showRedoControl: { description: gettext('Redo') }, + bottomToolbar: (props) => ( + <> + + + + ), + commandPalette: (props) => ( + + ), maxListNesting: 4, stripPastedStyles: false, ...newOptions, blockTypes: blockTypes.map(wrapWagtailIcon), inlineStyles: inlineStyles.map(wrapWagtailIcon), entityTypes, - controls, + controls: controls.concat([{ meta: MaxLength }]), + commands, enableHorizontalRule, }; }; diff --git a/docs/releases/4.0.md b/docs/releases/4.0.md index ffd7065984..1115538e49 100644 --- a/docs/releases/4.0.md +++ b/docs/releases/4.0.md @@ -17,6 +17,8 @@ When using a queryset to render a list of images, you can now use the `prefetch_ As part of the page editor redesign project sponsored by Google, we have made a number of improvements to our rich text editor: +* Inline toolbar: The toolbar now shows inline, to avoid clashing with the page’s header. +* Command palette: Start a block with a slash ‘/’ to open the palette and change the text format. * Character count: The character count is displayed underneath the editor, live-updating as you type. This counts the length of the text, not of any formatting. * Paste to auto-create links: To add a link from your copy-paste clipboard, select text and paste the URL. * Text shortcuts undo: The editor normally converts text starting with `1. ` to a list item. It’s now possible to un-do this change and keep the text as-is. This works for all Markdown-style shortcuts. diff --git a/package-lock.json b/package-lock.json index 1c32fbc255..93c1f5fd5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@tippyjs/react": "^4.2.6", "a11y-dialog": "^7.4.0", "draft-js": "^0.10.5", - "draftail": "^2.0.0-alpha.1", + "draftail": "^2.0.0-alpha.5", "draftjs-filters": "^2.5.0", "focus-trap-react": "^8.4.2", "immer": "^9.0.6", @@ -17872,9 +17872,9 @@ } }, "node_modules/draftail": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/draftail/-/draftail-2.0.0-alpha.1.tgz", - "integrity": "sha512-D6IEHS3KBFgnPIy4Et+O2SU8hbpZ+jdLyVCVXD7uifavK5c4ZFQ/w/zkVw7/8HJoMTyUIHNNSOHmdbCPnogQRg==", + "version": "2.0.0-alpha.5", + "resolved": "https://registry.npmjs.org/draftail/-/draftail-2.0.0-alpha.5.tgz", + "integrity": "sha512-7wGDH95FpOAMIUKyG41tVS3YybtRoZnIDSnytVoKDqnA0eqbaV6JsQCN9p3wOWuRsTkMCwzYQbBXnyd4FcMZWg==", "dependencies": { "@tippyjs/react": "^4.2.6", "decorate-component-with-props": "^1.0.2", @@ -43801,9 +43801,9 @@ } }, "draftail": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/draftail/-/draftail-2.0.0-alpha.1.tgz", - "integrity": "sha512-D6IEHS3KBFgnPIy4Et+O2SU8hbpZ+jdLyVCVXD7uifavK5c4ZFQ/w/zkVw7/8HJoMTyUIHNNSOHmdbCPnogQRg==", + "version": "2.0.0-alpha.5", + "resolved": "https://registry.npmjs.org/draftail/-/draftail-2.0.0-alpha.5.tgz", + "integrity": "sha512-7wGDH95FpOAMIUKyG41tVS3YybtRoZnIDSnytVoKDqnA0eqbaV6JsQCN9p3wOWuRsTkMCwzYQbBXnyd4FcMZWg==", "requires": { "@tippyjs/react": "^4.2.6", "decorate-component-with-props": "^1.0.2", diff --git a/package.json b/package.json index 5e3b2b2952..69bbac29d1 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@tippyjs/react": "^4.2.6", "a11y-dialog": "^7.4.0", "draft-js": "^0.10.5", - "draftail": "^2.0.0-alpha.1", + "draftail": "^2.0.0-alpha.5", "draftjs-filters": "^2.5.0", "focus-trap-react": "^8.4.2", "immer": "^9.0.6", diff --git a/wagtail/admin/templates/wagtailadmin/icons/bold.svg b/wagtail/admin/templates/wagtailadmin/icons/bold.svg index a9e07e990d..0807f763a7 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/bold.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/bold.svg @@ -1,3 +1,3 @@ - - + + diff --git a/wagtail/admin/templates/wagtailadmin/icons/comment-large-outline.svg b/wagtail/admin/templates/wagtailadmin/icons/comment-large-outline.svg deleted file mode 100644 index 8a36c90edc..0000000000 --- a/wagtail/admin/templates/wagtailadmin/icons/comment-large-outline.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/wagtail/admin/templates/wagtailadmin/icons/comment-large-reversed.svg b/wagtail/admin/templates/wagtailadmin/icons/comment-large-reversed.svg deleted file mode 100644 index 2f50760e56..0000000000 --- a/wagtail/admin/templates/wagtailadmin/icons/comment-large-reversed.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/wagtail/admin/templates/wagtailadmin/icons/comment-large.svg b/wagtail/admin/templates/wagtailadmin/icons/comment-large.svg deleted file mode 100644 index a4fc09d1b2..0000000000 --- a/wagtail/admin/templates/wagtailadmin/icons/comment-large.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/wagtail/admin/templates/wagtailadmin/icons/h1.svg b/wagtail/admin/templates/wagtailadmin/icons/h1.svg new file mode 100644 index 0000000000..df3e744964 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h1.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/h2.svg b/wagtail/admin/templates/wagtailadmin/icons/h2.svg new file mode 100644 index 0000000000..0db1163e25 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h2.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/h3.svg b/wagtail/admin/templates/wagtailadmin/icons/h3.svg new file mode 100644 index 0000000000..6cc62a00c4 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h3.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/h4.svg b/wagtail/admin/templates/wagtailadmin/icons/h4.svg new file mode 100644 index 0000000000..5413a9359f --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h4.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/h5.svg b/wagtail/admin/templates/wagtailadmin/icons/h5.svg new file mode 100644 index 0000000000..467b2ef0fc --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h5.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/h6.svg b/wagtail/admin/templates/wagtailadmin/icons/h6.svg new file mode 100644 index 0000000000..31bedf5c4c --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/h6.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/italic.svg b/wagtail/admin/templates/wagtailadmin/icons/italic.svg index 83c6534fd0..5445186730 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/italic.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/italic.svg @@ -1,3 +1,3 @@ - - + + diff --git a/wagtail/admin/templates/wagtailadmin/icons/link.svg b/wagtail/admin/templates/wagtailadmin/icons/link.svg index 4c60f69557..7ade0b3555 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/link.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/link.svg @@ -1,3 +1,3 @@ - - + + diff --git a/wagtail/admin/templates/wagtailadmin/icons/list-ol.svg b/wagtail/admin/templates/wagtailadmin/icons/list-ol.svg index bdeb720fb4..46f19b7525 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/list-ol.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/list-ol.svg @@ -1,3 +1,3 @@ - - + + diff --git a/wagtail/admin/templates/wagtailadmin/icons/list-ul.svg b/wagtail/admin/templates/wagtailadmin/icons/list-ul.svg index b00abef5d4..47c53ed6d4 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/list-ul.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/list-ul.svg @@ -1,3 +1,3 @@ - - + + diff --git a/wagtail/admin/wagtail_hooks.py b/wagtail/admin/wagtail_hooks.py index 6ac23f854e..6b22363263 100644 --- a/wagtail/admin/wagtail_hooks.py +++ b/wagtail/admin/wagtail_hooks.py @@ -486,7 +486,7 @@ def register_core_features(features): "h1", draftail_features.BlockFeature( { - "label": "H1", + "icon": "h1", "type": "header-one", "description": gettext("Heading %(level)d") % {"level": 1}, } @@ -507,7 +507,7 @@ def register_core_features(features): "h2", draftail_features.BlockFeature( { - "label": "H2", + "icon": "h2", "type": "header-two", "description": gettext("Heading %(level)d") % {"level": 2}, } @@ -528,7 +528,7 @@ def register_core_features(features): "h3", draftail_features.BlockFeature( { - "label": "H3", + "icon": "h3", "type": "header-three", "description": gettext("Heading %(level)d") % {"level": 3}, } @@ -549,7 +549,7 @@ def register_core_features(features): "h4", draftail_features.BlockFeature( { - "label": "H4", + "icon": "h4", "type": "header-four", "description": gettext("Heading %(level)d") % {"level": 4}, } @@ -570,7 +570,7 @@ def register_core_features(features): "h5", draftail_features.BlockFeature( { - "label": "H5", + "icon": "h5", "type": "header-five", "description": gettext("Heading %(level)d") % {"level": 5}, } @@ -591,7 +591,7 @@ def register_core_features(features): "h6", draftail_features.BlockFeature( { - "label": "H6", + "icon": "h6", "type": "header-six", "description": gettext("Heading %(level)d") % {"level": 6}, } @@ -947,9 +947,6 @@ def register_icons(icons): "comment.svg", "comment-add.svg", "comment-add-reversed.svg", - "comment-large.svg", - "comment-large-outline.svg", - "comment-large-reversed.svg", "cross.svg", "cut.svg", "date.svg", @@ -975,6 +972,12 @@ def register_icons(icons): "globe.svg", "grip.svg", "group.svg", + "h1.svg", + "h2.svg", + "h3.svg", + "h4.svg", + "h5.svg", + "h6.svg", "help.svg", "history.svg", "home.svg", diff --git a/wagtail/documents/wagtail_hooks.py b/wagtail/documents/wagtail_hooks.py index 176a2b4366..b99808217b 100644 --- a/wagtail/documents/wagtail_hooks.py +++ b/wagtail/documents/wagtail_hooks.py @@ -87,7 +87,7 @@ def register_document_feature(features): draftail_features.EntityFeature( { "type": "DOCUMENT", - "icon": "doc-full", + "icon": "doc-full-inverse", "description": gettext("Document"), }, js=["wagtaildocs/js/document-chooser-modal.js"],