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 @@
-