Răsfoiți Sursa

Update InlinePanel and StreamField styles for new designs (#8983)

Thibaud Colas 2 ani în urmă
părinte
comite
ca7f23d176
38 a modificat fișierele cu 913 adăugiri și 623 ștergeri
  1. 1 0
      client/scss/_tools.scss
  2. 7 65
      client/scss/components/_button.scss
  3. 0 2
      client/scss/components/_chooser.scss
  4. 93 10
      client/scss/components/_panel.scss
  5. 73 0
      client/scss/components/forms/_nested-panel.scss
  6. 1 0
      client/scss/core.scss
  7. 61 0
      client/scss/tools/_mixins.guide-line.scss
  8. 9 1
      client/src/components/Draftail/Draftail.scss
  9. 2 15
      client/src/components/StreamField/StreamField.scss
  10. 9 3
      client/src/components/StreamField/blocks/BaseSequenceBlock.js
  11. 3 5
      client/src/components/StreamField/blocks/ListBlock.js
  12. 3 4
      client/src/components/StreamField/blocks/StreamBlock.js
  13. 2 3
      client/src/components/StreamField/blocks/StructBlock.js
  14. 168 68
      client/src/components/StreamField/blocks/__snapshots__/ListBlock.test.js.snap
  15. 141 58
      client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap
  16. 4 6
      client/src/components/StreamField/blocks/__snapshots__/StructBlock.test.js.snap
  17. 32 21
      client/src/components/StreamField/scss/components/c-sf-add-button.scss
  18. 0 6
      client/src/components/StreamField/scss/components/c-sf-add-panel.scss
  19. 136 148
      client/src/components/StreamField/scss/components/c-sf-block.scss
  20. 0 2
      client/src/components/StreamField/scss/components/c-sf-button.scss
  21. 5 88
      client/src/components/StreamField/scss/components/c-sf-container.scss
  22. 45 37
      client/src/entrypoints/admin/page-editor.js
  23. 2 3
      client/src/entrypoints/contrib/typed_table_block/__snapshots__/typed_table_block.test.js.snap
  24. 2 3
      client/src/entrypoints/contrib/typed_table_block/typed_table_block.js
  25. 1 1
      docs/advanced_topics/customisation/page_editing_interface.md
  26. 2 2
      docs/reference/pages/panels.md
  27. 1 1
      docs/topics/pages.md
  28. 2 0
      wagtail/admin/forms/workflows.py
  29. 7 1
      wagtail/admin/panels.py
  30. 1 3
      wagtail/admin/templates/wagtailadmin/icons/bin.svg
  31. 9 9
      wagtail/admin/templates/wagtailadmin/panels/inline_panel.html
  32. 22 17
      wagtail/admin/templates/wagtailadmin/panels/inline_panel_child.html
  33. 23 11
      wagtail/admin/templates/wagtailadmin/shared/panel.html
  34. 1 1
      wagtail/admin/templates/wagtailadmin/workflows/create.html
  35. 1 1
      wagtail/admin/templates/wagtailadmin/workflows/edit.html
  36. 27 18
      wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotion_form.html
  37. 15 8
      wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotions_formset.html
  38. 2 2
      wagtail/test/demosite/models.py

+ 1 - 0
client/scss/_tools.scss

@@ -7,3 +7,4 @@ No CSS should be produced by these files.
 @import 'tools/mixins.breakpoints';
 @import 'tools/mixins.general';
 @import 'tools/mixins.grid';
+@import 'tools/mixins.guide-line';

+ 7 - 65
client/scss/components/_button.scss

@@ -379,9 +379,16 @@
 }
 
 .button--icon.text-replace {
+  background-color: transparent;
+  color: $color-grey-2;
+  border-color: transparent;
   font-size: 0;
   text-align: center;
 
+  &:hover {
+    color: $color-grey-1;
+  }
+
   .icon {
     font-size: initial;
     @include svg-icon(1rem, middle);
@@ -506,68 +513,3 @@ button {
     }
   }
 }
-
-.multiple {
-  padding: 0;
-  overflow: hidden;
-
-  > li {
-    @include row(1.5em);
-    border-radius: 2px;
-    position: relative;
-    overflow: hidden;
-    background-color: $color-white;
-    padding: 1em 1.5em;
-    padding-inline-end: 10em; // 10em padding leaves room for controls
-    margin-bottom: 1em;
-    border: 1px solid theme('colors.grey.100');
-  }
-
-  &.moving {
-    position: relative;
-  }
-
-  li.moving {
-    position: absolute;
-    width: 100%;
-  }
-
-  fieldset {
-    padding-top: 0;
-    padding-bottom: 0;
-  }
-
-  // Object controls
-  .controls {
-    position: absolute;
-    z-index: 1;
-    inset-inline-end: 1em;
-    top: 1em;
-    color: $color-white;
-
-    li {
-      float: left;
-      margin-inline-end: 1px;
-
-      &:last-child {
-        margin-inline-end: 0;
-      }
-    }
-
-    .disabled {
-      display: none;
-      visibility: hidden;
-    }
-  }
-}
-
-// wrapper around add button for multiple objects
-.add {
-  font-weight: 700;
-  cursor: pointer;
-  margin-top: 0;
-  margin-bottom: 0;
-  padding-top: 1em;
-  padding-bottom: 2em;
-  clear: both;
-}

+ 0 - 2
client/scss/components/_chooser.scss

@@ -1,6 +1,4 @@
 .chooser {
-  margin-bottom: theme('spacing.[2.5]');
-
   &.blank .chosen {
     display: none;
   }

+ 93 - 10
client/scss/components/_panel.scss

@@ -4,14 +4,12 @@ $header-button-size: theme('spacing.8');
 
 .w-panel {
   margin-bottom: theme('spacing.10');
-  // Legacy code support. Make sure we render correctly enough after a panel that contains un-cleared floats.
-  clear: both;
 }
 
 .w-panel__header {
   display: flex;
   align-items: center;
-  margin-bottom: theme('spacing.4');
+  margin-bottom: theme('spacing.3');
   margin-inline-start: -1 * $mobile-nice-padding;
 
   @include media-breakpoint-up(sm) {
@@ -26,6 +24,11 @@ $header-button-size: theme('spacing.8');
   display: inline-block;
   margin: 0;
   cursor: pointer;
+  padding-inline-end: theme('spacing.2');
+
+  @include media-breakpoint-up(sm) {
+    padding-inline-end: theme('spacing.5');
+  }
 }
 
 .w-panel__heading--label {
@@ -33,15 +36,39 @@ $header-button-size: theme('spacing.8');
 }
 
 .w-panel__anchor,
-.w-panel__toggle {
+.w-panel__toggle,
+.w-panel__controls .button.button--icon,
+.w-panel__controls-cue {
+  @include show-focus-outline-inside();
   display: inline-grid;
   justify-content: center;
   align-content: center;
   color: theme('colors.primary.DEFAULT');
+  border-radius: theme('borderRadius.full');
   padding: 0;
   width: $header-button-size-mobile;
   height: $header-button-size-mobile;
 
+  &:focus-visible,
+  &:hover {
+    background-color: $color-grey-5;
+
+    @media (forced-colors: active) {
+      border: 1px solid currentColor;
+    }
+  }
+
+  &[disabled] {
+    color: $color-grey-3;
+    cursor: not-allowed;
+    // Counter hover styles.
+    background-color: transparent;
+
+    @media (forced-colors: active) {
+      color: GrayText;
+    }
+  }
+
   @include media-breakpoint-up(sm) {
     width: $header-button-size;
     height: $header-button-size;
@@ -51,16 +78,28 @@ $header-button-size: theme('spacing.8');
 .w-panel__anchor {
   // Only hide anchors for devices that support hover interactions.
   @media (hover: hover) {
-    // Hiding with opacity only, so the anchor isn’t skipped in the page’s focus order.
-    opacity: 0;
-
-    .w-panel__header:hover &,
-    .w-panel__header:focus-within & {
-      opacity: 1;
+    .w-panel__header:not(:hover, :focus-within) & {
+      opacity: 0;
     }
   }
 }
 
+// The suffix anchor is intended for small viewports only.
+.w-panel__anchor--suffix {
+  @include media-breakpoint-up(sm) {
+    display: none;
+  }
+}
+
+// The prefix anchor can be used when there is enough space in the margin of the page.
+.w-panel__anchor--prefix {
+  display: none;
+
+  @include media-breakpoint-up(sm) {
+    display: inline-grid;
+  }
+}
+
 .w-panel__toggle {
   appearance: none;
   background: transparent;
@@ -81,6 +120,50 @@ $header-button-size: theme('spacing.8');
   }
 }
 
+.w-panel__divider {
+  flex: 1;
+}
+
+.w-panel__controls {
+  // Add additional invisible padding for a more forgiving hover area.
+  padding: theme('spacing.4');
+  margin: calc(-1 * theme('spacing.4'));
+  margin-inline-end: calc(-1 * theme('spacing.8'));
+  margin-inline-start: 0;
+
+  @include media-breakpoint-up(sm) {
+    margin: calc(-1 * theme('spacing.4'));
+    margin-inline-start: 0;
+  }
+
+  // The cue is meant to be displayed on top of a real button.
+  > .w-panel__controls-cue {
+    position: absolute;
+    visibility: hidden;
+  }
+
+  @media (hover: hover) {
+    // Hiding with opacity only, so the elements can still be focused.
+    > * {
+      opacity: 0;
+    }
+
+    > .w-panel__controls-cue {
+      opacity: 1;
+      visibility: visible;
+    }
+
+    .w-panel__header:is(:hover, :focus-within) & > * {
+      opacity: 1;
+
+      // The cue should be fully hidden, not just transparent.
+      &.w-panel__controls-cue {
+        visibility: hidden;
+      }
+    }
+  }
+}
+
 .w-panel__wrapper {
   @include max-form-width();
 }

+ 73 - 0
client/scss/components/forms/_nested-panel.scss

@@ -0,0 +1,73 @@
+$header-icon-size-sm: theme('spacing.5');
+$header-button-size-sm: theme('spacing.8');
+$header-gap: theme('spacing.1');
+$panel-x-offset: calc($header-button-size-sm / 2 + $header-gap);
+
+/**
+ * Panel styles shared between StreamField and InlinePanel,
+ * for repeating collapsible panels which can be reordered.
+ * Top-level and nested panels have guiding borders to show their start and end,
+ * as well as indentation for nested panels.
+ */
+
+// Styles for the top-level panel, and any panel within.
+.w-panel--nested {
+  @include guide-line-active();
+
+  .w-panel__divider {
+    @include guide-line-horizontal();
+    // Slightly nicer text alignment.
+    margin-top: 1px;
+  }
+
+  .w-panel__content {
+    @include guide-line-vertical();
+    // Center the vertical line.
+    margin-inline-start: calc(-1 * theme('spacing.3'));
+    padding-inline-start: theme('spacing.3');
+
+    @include media-breakpoint-up(sm) {
+      margin-inline-start: calc(-1 * $panel-x-offset);
+      padding-inline-start: $panel-x-offset;
+    }
+  }
+
+  .w-panel__anchor {
+    // Mask the overlap with the parent panel’s guide line.
+    background-color: $color-white;
+  }
+
+  .w-panel__heading--label {
+    // Use smaller labels within nested panels in InlinePanel.
+    @apply w-label-2;
+  }
+}
+
+// Styles for nested panels excluding the top level.
+.w-panel--nested .w-panel {
+  @include guide-line-nested();
+  // Indentation for nested panels.
+  margin-inline-start: theme('spacing.7');
+  margin-bottom: theme('spacing.6');
+
+  // Tighter spacing for nested panel headers so their icons align
+  // with parent panels’ guiding line.
+  .w-panel__header {
+    gap: 0;
+    transform: translateX(calc(-1 * theme('spacing.5')));
+
+    @include media-breakpoint-up(sm) {
+      transform: translateX(theme('spacing.1'));
+    }
+  }
+
+  // For nested panels, there is always enough space for the prefix anchor.
+  .w-panel__anchor--prefix {
+    display: inline-grid;
+  }
+
+  // Nested panels never need the suffix anchor.
+  .w-panel__anchor--suffix {
+    display: none;
+  }
+}

+ 1 - 0
client/scss/core.scss

@@ -124,6 +124,7 @@ These are classes for components.
 @import 'components/forms/field-row';
 @import 'components/forms/field-comment-control';
 @import 'components/forms/form-width';
+@import 'components/forms/nested-panel';
 @import 'components/tabs';
 @import 'components/panel';
 @import 'components/dialog';

+ 61 - 0
client/scss/tools/_mixins.guide-line.scss

@@ -0,0 +1,61 @@
+/**
+ * Vertical and horizontal divider lines to visualise nesting in
+ * StreamField and InlinePanel.
+ */
+
+@mixin guide-line-vertical() {
+  // 3px dash height, 3px space, 1px dash width.
+  background-size: 1px 6px;
+  background-repeat: repeat-y;
+  background-image: linear-gradient(
+    to bottom,
+    var(--guide-line-color, transparent) 50%,
+    rgba(255, 255, 255, 0) 0%
+  );
+
+  @media (forced-colors: active) {
+    border-inline-start: 1px dashed var(--guide-line-color, CanvasText);
+    background: none;
+  }
+}
+
+@mixin guide-line-horizontal() {
+  min-height: 1px;
+  // 3px dash width, 3px space, 1px dash height.
+  background-size: 6px 1px;
+  background-repeat: repeat-x;
+  background-image: linear-gradient(
+    to right,
+    var(--guide-line-color, transparent) 50%,
+    rgba(255, 255, 255, 0) 0%
+  );
+
+  // Guide lines are always shown in forced-colors mode, as it’s
+  // not possible to have transparent borders there.
+  @media (forced-colors: active) {
+    border-top: 1px dashed var(--guide-line-color, CanvasText);
+    background: none;
+  }
+}
+
+// Default guide line color for nested panels.
+@mixin guide-line-active() {
+  @media (hover: none) {
+    --guide-line-color: theme('colors.grey.150');
+  }
+
+  &:is(:hover, :focus-within) {
+    --guide-line-color: theme('colors.grey.150');
+  }
+}
+
+// More visible guide line for nested panels in the currently-active DOM tree.
+@mixin guide-line-nested() {
+  &:is(:hover, :focus-within) {
+    --guide-line-color: theme('colors.primary.DEFAULT');
+
+    @media (forced-colors: active) {
+      --guide-line-color: Highlight;
+    }
+  }
+}

+ 9 - 1
client/src/components/Draftail/Draftail.scss

@@ -126,7 +126,9 @@ $draftail-editor-font-family: $font-sans;
   margin-inline-start: calc(-1 * theme('spacing.5'));
 
   @include media-breakpoint-up(sm) {
-    margin-inline-start: calc(-1 * theme('spacing.6'));
+    margin-inline-start: calc(
+      -1 * (theme('spacing.8') + theme('spacing.[0.5]'))
+    );
   }
 }
 
@@ -148,6 +150,12 @@ $draftail-editor-font-family: $font-sans;
     visibility: hidden !important;
   }
 
+  &:hover,
+  &:focus-visible {
+    color: $color-white;
+    background-color: $color-teal;
+  }
+
   .icon {
     width: theme('spacing.3');
     height: theme('spacing.3');

+ 2 - 15
client/src/components/StreamField/StreamField.scss

@@ -1,28 +1,15 @@
 $grid-gutter-width: 30px;
-$header-padding-horizontal: 4px;
-$header-padding-vertical: 6px;
 $header-gutter: 8px;
-$header-background: $color-grey-5;
-$block-margin-vertical: 4px;
-$block-margin-horizontal: 0;
-$add-button-size: 34px;
-$add-button-font-size: 1.5rem;
+$block-margin-vertical: theme('spacing.1');
+$block-margin-horizontal: theme('spacing.3');
 $type-button-padding-vertical: 10px;
 $type-button-padding-horizontal: 10px;
-$children-container-padding: $add-button-size * 0.5;
 $content-padding-horizontal: 24px;
 $content-padding-vertical: 16px;
 $action-font-size: 1.125rem;
 $add-transition-duration: 0.3s;
 $hover-transition-duration: 0.3s;
-$bounce-transition-timing: cubic-bezier(0.175, 0.885, 0.32, 1.275);
 $border-radius: 3px;
-$header-text-color: $color-grey-2;
-$block-border-color: $color-grey-4;
-$block-border-color-focus: $color-grey-3;
-$block-hover-background: $color-grey-5;
-$error-border-color: theme('colors.critical.100');
-$error-background-color: $color-input-bg;
 $add-panel-gutter: 8px;
 
 @import 'scss/components/c-sf-add-button';

+ 9 - 3
client/src/components/StreamField/blocks/BaseSequenceBlock.js

@@ -148,10 +148,16 @@ export class BaseSequenceChild extends EventEmitter {
                   <use href="#icon-${h(this.blockDef.meta.icon)}"></use>
                 </svg>
                 <h3 data-block-title class="c-sf-block__header__title"></h3>
+                <div class="c-sf-block__type">${h(
+                  this.blockDef.meta.label,
+                )}</div>
+                <div class="c-sf-block__header__divider"></div>
                 <div class="c-sf-block__actions" data-block-actions>
-                  <span class="c-sf-block__type">${h(
-                    this.blockDef.meta.label,
-                  )}</span>
+                  <div class="c-sf-block__actions__cue">
+                    <svg class="icon icon-dots-horizontal" aria-hidden="true">
+                      <use href="#icon-dots-horizontal"></use>
+                    </svg>
+                  </div>
                 </div>
               </div>
               <div data-block-content class="c-sf-block__content" aria-hidden="false">

+ 3 - 5
client/src/components/StreamField/blocks/ListBlock.js

@@ -1,5 +1,4 @@
 /* eslint-disable no-underscore-dangle */
-
 import { v4 as uuidv4 } from 'uuid';
 
 import {
@@ -69,7 +68,7 @@ class InsertPosition extends BaseInsertionControl {
         opts.strings.ADD,
       )}" data-streamfield-list-add
           class="c-sf-add-button c-sf-add-button--visible">
-        <i aria-hidden="true">+</i>
+        <svg class="icon icon-plus" aria-hidden="true"><use href="#icon-plus"></use></svg>
       </button>
     `);
     $(placeholder).replaceWith(button);
@@ -114,12 +113,11 @@ export class ListBlock extends BaseSequenceBlock {
     if (this.blockDef.meta.helpText) {
       // help text is left unescaped as per Django conventions
       $(`
-        <span>
+        <div class="c-sf-help">
           <div class="help">
-            ${this.blockDef.meta.helpIcon}
             ${this.blockDef.meta.helpText}
           </div>
-        </span>
+        </div>
       `).insertBefore(dom);
     }
 

+ 3 - 4
client/src/components/StreamField/blocks/StreamBlock.js

@@ -68,7 +68,7 @@ class StreamBlockMenu extends BaseInsertionControl {
           opts.strings.ADD,
         )}"
             class="c-sf-add-button c-sf-add-button--visible">
-          <i aria-hidden="true">+</i>
+          <svg class="icon icon-plus" aria-hidden="true"><use href="#icon-plus"></use></svg>
         </button>
         <div data-streamblock-menu-outer>
           <div data-streamblock-menu-inner class="c-sf-add-panel"></div>
@@ -221,12 +221,11 @@ export class StreamBlock extends BaseSequenceBlock {
     if (this.blockDef.meta.helpText) {
       // help text is left unescaped as per Django conventions
       $(`
-        <span>
+        <div class="c-sf-help">
           <div class="help">
-            ${this.blockDef.meta.helpIcon}
             ${this.blockDef.meta.helpText}
           </div>
-        </span>
+        </div>
       `).insertBefore(dom);
     }
 

+ 2 - 3
client/src/components/StreamField/blocks/StructBlock.js

@@ -42,12 +42,11 @@ export class StructBlock {
       if (this.blockDef.meta.helpText) {
         // help text is left unescaped as per Django conventions
         dom.append(`
-          <span>
+          <div class="c-sf-help">
             <div class="help">
-              ${this.blockDef.meta.helpIcon}
               ${this.blockDef.meta.helpText}
             </div>
-          </span>
+          </div>
         `);
       }
 

+ 168 - 68
client/src/components/StreamField/blocks/__snapshots__/ListBlock.test.js.snap

@@ -1,16 +1,15 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"3\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -25,8 +24,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -64,7 +69,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"1\\">
@@ -79,8 +84,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -118,7 +129,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath-disabled=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-2-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-2-order\\" value=\\"2\\">
@@ -133,8 +144,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -172,22 +189,21 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be duplicated 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered downward 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"0\\">
@@ -202,8 +218,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered downward 1`]
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -241,7 +263,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered downward 1`]
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"1\\">
@@ -256,8 +278,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered downward 1`]
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -295,22 +323,21 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered downward 1`]
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered upward 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"0\\">
@@ -325,8 +352,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered upward 1`] =
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -364,7 +397,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered upward 1`] =
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"1\\">
@@ -379,8 +412,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered upward 1`] =
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -418,22 +457,21 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be reordered upward 1`] =
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"3\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -448,8 +486,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -487,7 +531,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath-disabled=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-2-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-2-order\\" value=\\"1\\">
@@ -502,8 +546,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -541,7 +591,7 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"2\\">
@@ -556,8 +606,14 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -595,22 +651,21 @@ exports[`telepath: wagtail.blocks.ListBlock blocks can be split 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock deleteBlock() deletes a block 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -625,8 +680,14 @@ exports[`telepath: wagtail.blocks.ListBlock deleteBlock() deletes a block 1`] =
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -664,7 +725,7 @@ exports[`telepath: wagtail.blocks.ListBlock deleteBlock() deletes a block 1`] =
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"true\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\" style=\\"display: none;\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"1\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"1\\">
@@ -679,8 +740,14 @@ exports[`telepath: wagtail.blocks.ListBlock deleteBlock() deletes a block 1`] =
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -718,22 +785,21 @@ exports[`telepath: wagtail.blocks.ListBlock deleteBlock() deletes a block 1`] =
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock it renders correctly 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -748,8 +814,14 @@ exports[`telepath: wagtail.blocks.ListBlock it renders correctly 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -787,7 +859,7 @@ exports[`telepath: wagtail.blocks.ListBlock it renders correctly 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"1\\">
@@ -802,8 +874,14 @@ exports[`telepath: wagtail.blocks.ListBlock it renders correctly 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -841,22 +919,21 @@ exports[`telepath: wagtail.blocks.ListBlock it renders correctly 1`] = `
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock setError passes error messages to children 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -871,8 +948,14 @@ exports[`telepath: wagtail.blocks.ListBlock setError passes error messages to ch
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -910,7 +993,7 @@ exports[`telepath: wagtail.blocks.ListBlock setError passes error messages to ch
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"1\\">
@@ -925,8 +1008,14 @@ exports[`telepath: wagtail.blocks.ListBlock setError passes error messages to ch
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -964,22 +1053,21 @@ exports[`telepath: wagtail.blocks.ListBlock setError passes error messages to ch
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;
 
 exports[`telepath: wagtail.blocks.ListBlock setError renders non-block errors 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>a few</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\"><p class=\\"help-block help-critical\\">At least three blocks are required</p>
+        </div><div class=\\"c-sf-container \\"><p class=\\"help-block help-critical\\">At least three blocks are required</p>
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-list-count=\\"\\" value=\\"2\\">
 
         <div data-streamfield-list-container=\\"\\"><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"11111111-1111-1111-1111-111111111111\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-0-order\\" value=\\"0\\">
@@ -994,8 +1082,14 @@ exports[`telepath: wagtail.blocks.ListBlock setError renders non-block errors 1`
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -1033,7 +1127,7 @@ exports[`telepath: wagtail.blocks.ListBlock setError renders non-block errors 1`
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button><div aria-hidden=\\"false\\" data-contentpath=\\"22222222-2222-2222-2222-222222222222\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-deleted\\" value=\\"\\">
         <input type=\\"hidden\\" name=\\"the-prefix-1-order\\" value=\\"1\\">
@@ -1048,8 +1142,14 @@ exports[`telepath: wagtail.blocks.ListBlock setError renders non-block errors 1`
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\"></div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\"></span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -1087,7 +1187,7 @@ exports[`telepath: wagtail.blocks.ListBlock setError renders non-block errors 1`
           </div>
         </div>
       </div><button type=\\"button\\" title=\\"Add\\" data-streamfield-list-add=\\"\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-        <i aria-hidden=\\"true\\">+</i>
+        <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
       </button></div>
       </div>"
 `;

+ 141 - 58
client/src/components/StreamField/blocks/__snapshots__/StreamBlock.test.js.snap

@@ -1,16 +1,15 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"3\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -29,8 +28,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -69,7 +74,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -88,8 +93,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -128,7 +139,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -147,8 +158,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -187,7 +204,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -197,16 +214,15 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be duplicated 1`] = `
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -225,8 +241,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -265,7 +287,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -284,8 +306,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -324,7 +352,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -334,16 +362,15 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered downward 1
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -362,8 +389,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`]
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -402,7 +435,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`]
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -421,8 +454,14 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`]
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -461,7 +500,7 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`]
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -471,16 +510,15 @@ exports[`telepath: wagtail.blocks.StreamBlock blocks can be reordered upward 1`]
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -499,8 +537,14 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -539,7 +583,7 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -558,8 +602,14 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -598,7 +648,7 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -608,16 +658,15 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders correctly 1`] = `
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -636,8 +685,14 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -676,7 +731,7 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible c-sf-add-button--close\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"\\" aria-hidden=\\"false\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"><div class=\\"c-sf-add-panel__grid\\"><button type=\\"button\\" class=\\"c-sf-button action-add-block-test_block_a\\">
@@ -705,8 +760,14 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -745,7 +806,7 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -755,16 +816,15 @@ exports[`telepath: wagtail.blocks.StreamBlock it renders menus on opening 1`] =
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\"><p class=\\"help-block help-critical\\">At least three blocks are required</p>
+        </div><div class=\\"c-sf-container \\"><p class=\\"help-block help-critical\\">At least three blocks are required</p>
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -783,8 +843,14 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block A</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block A</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -823,7 +889,7 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -842,8 +908,14 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block B</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block B</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -882,7 +954,7 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -892,16 +964,15 @@ exports[`telepath: wagtail.blocks.StreamBlock setError renders error messages 1`
 `;
 
 exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it renders correctly 1`] = `
-"<span>
+"<div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span><div class=\\"c-sf-container \\">
+        </div><div class=\\"c-sf-container \\">
         <input type=\\"hidden\\" name=\\"the-prefix-count\\" data-streamfield-stream-count=\\"\\" value=\\"2\\">
         <div data-streamfield-stream-container=\\"\\"><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible c-sf-add-button--close\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"\\" aria-hidden=\\"false\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"><div class=\\"c-sf-add-panel__grid\\"><button type=\\"button\\" class=\\"c-sf-button action-add-block-test_block_a\\">
@@ -930,8 +1001,14 @@ exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it
                   <use href=\\"#icon-placeholder\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block &lt;A&gt;</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block &lt;A&gt;</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\" disabled=\\"disabled\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -970,7 +1047,7 @@ exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>
@@ -989,8 +1066,14 @@ exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it
                   <use href=\\"#icon-pilcrow\\"></use>
                 </svg>
                 <h3 data-block-title=\\"\\" class=\\"c-sf-block__header__title\\"></h3>
+                <div class=\\"c-sf-block__type\\">Test Block &lt;B&gt;</div>
+                <div class=\\"c-sf-block__header__divider\\"></div>
                 <div class=\\"c-sf-block__actions\\" data-block-actions=\\"\\">
-                  <span class=\\"c-sf-block__type\\">Test Block &lt;B&gt;</span>
+                  <div class=\\"c-sf-block__actions__cue\\">
+                    <svg class=\\"icon icon-dots-horizontal\\" aria-hidden=\\"true\\">
+                      <use href=\\"#icon-dots-horizontal\\"></use>
+                    </svg>
+                  </div>
                 <button type=\\"button\\" class=\\"c-sf-block__actions__single\\" title=\\"Move up\\">
         <svg class=\\"icon icon-arrow-up\\" aria-hidden=\\"true\\">
           <use href=\\"#icon-arrow-up\\"></use>
@@ -1029,7 +1112,7 @@ exports[`telepath: wagtail.blocks.StreamBlock with labels that need escaping it
         </div>
       </div><div>
         <button data-streamblock-menu-open=\\"\\" type=\\"button\\" title=\\"Add\\" class=\\"c-sf-add-button c-sf-add-button--visible\\">
-          <i aria-hidden=\\"true\\">+</i>
+          <svg class=\\"icon icon-plus\\" aria-hidden=\\"true\\"><use href=\\"#icon-plus\\"></use></svg>
         </button>
         <div data-streamblock-menu-outer=\\"\\" style=\\"display: none;\\" aria-hidden=\\"true\\">
           <div data-streamblock-menu-inner=\\"\\" class=\\"c-sf-add-panel\\"></div>

+ 4 - 6
client/src/components/StreamField/blocks/__snapshots__/StructBlock.test.js.snap

@@ -3,12 +3,11 @@
 exports[`telepath: wagtail.blocks.StructBlock it renders correctly 1`] = `
 "<div class=\\"struct-block\\">
         
-          <span>
+          <div class=\\"c-sf-help\\">
             <div class=\\"help\\">
-              <div class=\\"icon-help\\">?</div>
               use <strong>lots</strong> of these
             </div>
-          </span>
+          </div>
         <div data-contentpath=\\"heading_text\\">
           <label class=\\"w-field__label\\" for=\\"the-prefix-heading_text\\">Heading text<span class=\\"w-required-mark\\">*</span></label>
             <div class=\\"w-field__wrapper\\" data-field-wrapper=\\"\\">
@@ -41,12 +40,11 @@ exports[`telepath: wagtail.blocks.StructBlock it renders correctly 1`] = `
 exports[`telepath: wagtail.blocks.StructBlock setError passes error messages to children 1`] = `
 "<div class=\\"struct-block\\">
         
-          <span>
+          <div class=\\"c-sf-help\\">
             <div class=\\"help\\">
-              <div class=\\"icon-help\\">?</div>
               use <strong>lots</strong> of these
             </div>
-          </span>
+          </div>
         <div data-contentpath=\\"heading_text\\">
           <label class=\\"w-field__label\\" for=\\"the-prefix-heading_text\\">Heading text<span class=\\"w-required-mark\\">*</span></label>
             <div class=\\"w-field__wrapper\\" data-field-wrapper=\\"\\">

+ 32 - 21
client/src/components/StreamField/scss/components/c-sf-add-button.scss

@@ -1,44 +1,55 @@
 .c-sf-add-button {
-  width: 100%;
-  height: $add-button-size;
+  display: grid;
+  align-items: center;
+  justify-content: center;
+  width: theme('spacing.5');
+  height: theme('spacing.5');
   appearance: none;
-  border: 0 none;
   color: $color-teal;
-  font-weight: bold;
-  background: none;
+  background-color: $color-white;
   padding: 0;
   cursor: pointer;
-  outline: none;
-  backface-visibility: hidden;
-  overflow: hidden; // Makes the rotated i box not clickable.
-  user-select: none;
   opacity: 0;
   pointer-events: none;
-  transition: opacity 100ms ease-in-out;
+  border: 1px solid currentColor;
+  border-radius: theme('borderRadius.full');
+  margin-inline-start: theme('spacing.[0.5]');
 
-  &:hover {
-    opacity: 1;
+  .icon {
+    width: theme('spacing.3');
+    height: theme('spacing.3');
+    transition: transform $add-transition-duration ease-in-out;
   }
 
-  i {
-    display: block;
-    transition: transform $add-transition-duration $bounce-transition-timing;
-    font-style: normal;
-    font-size: $add-button-font-size;
-    line-height: $add-button-size;
+  &--close .icon {
+    transform: rotate(45deg);
   }
 
   &--visible {
-    opacity: 0.8;
+    opacity: 1;
     pointer-events: unset;
+
+    @media (hover: hover) {
+      opacity: 0;
+
+      .w-panel--nested:is(:hover, :focus-within) & {
+        opacity: 1;
+      }
+    }
   }
 
-  &--close i {
-    transform: rotate(45deg);
+  &:hover,
+  &:focus-visible {
+    color: $color-white;
+    background-color: $color-teal;
   }
 
   &[disabled] {
     opacity: 0.2;
     pointer-events: none;
+
+    @media (forced-colors: active) {
+      color: GrayText;
+    }
   }
 }

+ 0 - 6
client/src/components/StreamField/scss/components/c-sf-add-panel.scss

@@ -3,14 +3,8 @@
 .c-sf-add-panel {
   position: relative;
   padding: $grid-gutter-width * 0.25 0 $grid-gutter-width;
-  border-radius: $border-radius;
   user-select: none;
 
-  @include media-breakpoint-up(lg) {
-    padding: $grid-gutter-width * 0.25 $grid-gutter-width * 2 $add-button-size -
-      math.div($grid-gutter-width, 2);
-  }
-
   &__group-title {
     margin: 5px 0;
     font-weight: 600;

+ 136 - 148
client/src/components/StreamField/scss/components/c-sf-block.scss

@@ -1,186 +1,174 @@
-// TODO: Reduce nesting further by splitting out more components.
-// ---
-// There's quite a lot of nesting in here which makes parsing some segments difficult.
-// Some of this is to deal with the fact that .c-sf-block can contain many .c-sf-block's and so is
-// legitimate. A lot of these would ideally be their own components (eg the actions) however there
-// is a lot of interdependency of the elements which makes this hard
-// without fairly intensive rethinking of the HTML.
-// ---
-// However, the new classes adequately sanitise streamfield only CSS so am leaving this for
-// now to avoid blocking the release of the new Streamfield. -@jonnyscholes
+$header-icon-size: theme('spacing.4');
+$header-button-size-mobile: $mobile-nice-padding;
+$header-button-size: theme('spacing.8');
+
 .c-sf-block {
+  @include guide-line-active();
+  @include guide-line-nested();
   flex: 1 1 auto;
-  margin: $block-margin-vertical $block-margin-horizontal;
-  border: 1px solid $block-border-color;
-  border-radius: $border-radius;
-  background: $color-white;
-  transition: border-color $hover-transition-duration ease-in-out;
-  transition-property: border-color, box-shadow;
-
-  &__header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    padding: $header-padding-vertical $header-padding-horizontal;
-    user-select: none;
-    transition: background-color $hover-transition-duration ease-in-out;
-    cursor: default;
-    // Remove once we drop support for Safari 14.
-    // stylelint-disable-next-line property-disallowed-list
-    border-top-left-radius: $border-radius;
-    border-start-start-radius: $border-radius;
-    // Remove once we drop support for Safari 14.
-    // stylelint-disable-next-line property-disallowed-list
-    border-top-right-radius: $border-radius;
-    border-start-end-radius: $border-radius;
-    min-height: 30px;
-    background: $header-background;
+  margin-top: $block-margin-vertical;
+  margin-inline-start: $block-margin-horizontal;
+}
 
-    @include media-breakpoint-up(sm) {
-      padding-inline-start: $content-padding-horizontal - $header-gutter;
-    }
+.c-sf-block__header {
+  display: flex;
+  align-items: center;
+  min-height: 30px;
 
-    &--collapsible {
-      cursor: pointer;
-    }
+  &--collapsible {
+    cursor: pointer;
+  }
 
-    &--sortable {
-      cursor: grab;
-    }
+  &__title {
+    @apply w-label-2;
+    display: inline-block;
+    margin: 0;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+  }
 
-    &__title,
-    &__icon {
-      color: $header-text-color;
-    }
+  &__icon {
+    color: theme('colors.primary.DEFAULT');
+    width: $header-button-size-mobile;
+    height: $header-button-size-mobile;
+    padding: theme('spacing.[0.5]');
+    margin-inline-start: calc(-1 * $header-button-size-mobile / 2);
+    transition: color $hover-transition-duration ease-in-out;
 
-    &__title {
-      display: inline-block;
-      flex: 1 10 auto;
-      margin: 0;
-      font-size: 12px;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-      overflow: hidden;
+    @include media-breakpoint-up(sm) {
+      width: $header-button-size;
+      height: $header-button-size;
+      padding: theme('spacing.2');
+      margin-inline-start: calc(-1 * $header-button-size / 2);
     }
 
-    &__icon {
-      width: 20px;
-      height: 20px;
-      margin: 0 $header-gutter;
-      transition: color $hover-transition-duration ease-in-out;
+    @media (forced-colors: active) {
+      color: inherit;
     }
   }
+}
 
-  &__content {
-    &-inner {
-      padding: $content-padding-vertical $content-padding-horizontal;
-    }
-  }
+.c-sf-block__header__divider {
+  @include guide-line-horizontal();
+  flex: 1;
+  margin-inline-start: theme('spacing.5');
+  margin-inline-end: theme('spacing.5');
+}
 
-  &__actions {
-    flex: 0 1 auto;
-    display: flex;
-    align-items: center;
-    white-space: nowrap;
-    overflow-x: hidden;
-
-    &__single {
-      appearance: none;
-      border: 0 none;
-      background: none;
-      cursor: pointer;
-      color: $header-text-color;
-      opacity: 1;
-      transition: opacity $hover-transition-duration ease-in-out,
-        color $hover-transition-duration ease-in-out,
-        background-color $hover-transition-duration ease-in-out;
-      border-radius: 50%;
-      width: 30px;
-      height: 30px;
-      line-height: 1;
-      font-size: $action-font-size;
-      text-align: center;
-      padding: 0;
-
-      &:not(:last-of-type) {
-        margin-inline-end: 3px;
-      }
+.c-sf-block__type {
+  @apply w-label-2;
+  overflow-x: hidden;
+  text-overflow: ellipsis;
 
-      &:focus,
-      &:hover {
-        color: $color-grey-1;
-        background-color: $color-grey-4;
-      }
+  // Hide the block type if we are showing the title (in collapsed mode).
+  .c-sf-block__header__title:not(:empty) + & {
+    display: none;
+  }
+}
 
-      svg.icon {
-        width: 1em;
-        height: 1em;
-        vertical-align: middle;
-      }
+.c-sf-block__content {
+  @include guide-line-vertical();
 
-      &[disabled] {
-        opacity: 0.2;
-        pointer-events: none;
-      }
-    }
+  &-inner {
+    padding-top: $content-padding-vertical;
+    padding-inline-start: $content-padding-horizontal;
   }
+}
 
-  &__type {
-    margin: 0 $header-gutter;
-    text-align: end;
-    font-size: 12px;
-    color: $header-text-color;
-    user-select: none;
-    vertical-align: 2px;
-    overflow-x: hidden;
-    text-overflow: ellipsis;
-  }
+.c-sf-block__actions {
+  display: flex;
+  align-items: center;
+  white-space: nowrap;
+  overflow-x: hidden;
+  // Add additional invisible padding for a more forgiving hover area.
+  padding: theme('spacing.4');
+  margin: calc(-1 * theme('spacing.4'));
+
+  &__cue,
+  &__single {
+    display: inline-grid;
+    justify-items: center;
+    align-items: center;
+    width: $header-button-size-mobile;
+    height: $header-button-size-mobile;
 
-  &.c-sf-block--error {
-    border-color: $error-border-color;
+    @include media-breakpoint-up(sm) {
+      width: $header-button-size;
+      height: $header-button-size;
+    }
+  }
 
-    > .c-sf-block__header {
-      background: $error-background-color;
+  &__single {
+    appearance: none;
+    border: 0 none;
+    background: none;
+    cursor: pointer;
+    color: theme('colors.primary.DEFAULT');
+    opacity: 1;
+    border-radius: theme('borderRadius.full');
+    line-height: 1;
+    font-size: $action-font-size;
+    text-align: center;
+    padding: 0;
+
+    &:not(:last-of-type) {
+      margin-inline-end: 3px;
     }
 
-    &:hover,
-    &:focus {
-      border-color: $error-border-color;
+    &:focus,
+    &:hover {
+      background-color: $color-grey-5;
 
-      > .c-sf-block__header {
-        background: $error-background-color;
+      @media (forced-colors: active) {
+        border: 1px solid currentColor;
       }
     }
 
-    // Duplicated because of
-    // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/16651302/
-    &:focus-within {
-      border-color: $error-border-color;
+    &[disabled] {
+      color: $color-grey-3;
+      cursor: not-allowed;
+      // Counter hover styles.
+      background-color: transparent;
 
-      > .c-sf-block__header {
-        background: $error-background-color;
+      @media (forced-colors: active) {
+        color: GrayText;
       }
     }
   }
 
-  &:hover,
-  &:focus {
-    border-color: $block-border-color-focus;
-    box-shadow: 3px 2px 3px -1px theme('colors.black-10');
+  // The cue is meant to be displayed on top of a real button.
+  &__cue {
+    position: absolute;
+    visibility: hidden;
+  }
 
-    > .c-sf-block__header {
-      background: $block-hover-background;
+  @media (hover: hover) {
+    // Hiding with opacity only, so the elements can still be focused.
+    > * {
+      opacity: 0;
+    }
+
+    &__cue {
+      opacity: 1;
+      visibility: visible;
     }
-  }
 
-  // Duplicated because of
-  // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/16651302/
-  &:focus-within {
-    border-color: $block-border-color-focus;
-    box-shadow: 3px 2px 3px -1px theme('colors.black-10');
+    .c-sf-block__header:is(:hover, :focus-within) & {
+      > * {
+        opacity: 1;
+      }
 
-    > .c-sf-block__header {
-      background: $block-hover-background;
+      // The cue should be fully hidden, not just transparent.
+      .c-sf-block__actions__cue {
+        visibility: hidden;
+      }
     }
   }
+
+  svg.icon {
+    width: $header-icon-size;
+    height: $header-icon-size;
+    vertical-align: middle;
+  }
 }

+ 0 - 2
client/src/components/StreamField/scss/components/c-sf-button.scss

@@ -15,8 +15,6 @@
   outline: none;
   cursor: pointer;
   overflow: hidden;
-  transition: background-color $hover-transition-duration ease-in-out,
-    color $hover-transition-duration ease-in-out;
 
   &:hover,
   &:focus {

+ 5 - 88
client/src/components/StreamField/scss/components/c-sf-container.scss

@@ -4,99 +4,16 @@
   position: relative;
   display: flex;
   flex-flow: column nowrap;
-  padding: $children-container-padding 0;
-
-  // TODO: #CSSoverhaul the bse icon style here - the margin - should be reconsidered when
-  // re-building the icon component as part of the CSS  These styles come from global
-  // label styles in css/mixins/_general.scss -@jonnyscholes
-  .c-sf-button__icon {
-    .icon::before {
-      margin: unset;
-    }
-  }
 
   &__block-container {
     position: relative;
     display: flex;
     flex-flow: column nowrap;
   }
+}
 
-  &--add-in-gutter {
-    @include media-breakpoint-up(sm) {
-      padding-inline-start: $add-button-size;
-
-      .c-sf-add-button {
-        width: $add-button-size;
-        height: 0;
-        transform: translate(-100%, math.div(-$add-button-size, 2));
-        overflow: visible;
-      }
-    }
-  }
-
-  // TODO: Remove these references to classes that are styled by core Wagtail CSS. The best
-  // opportunity for this is probably as part of Wagtails general CSS overhaul. -@jonnyscholes
-  .field {
-    + .field {
-      padding-top: math.div($grid-gutter-width, 2);
-    }
-
-    // TODO: #CSSoverhaul global label styles need to be removed. These styles come from global
-    // label styles in css/_grid.scss -@jonnyscholes
-    label {
-      float: unset; // LEGIT
-      width: unset; // LEGIT
-      max-width: unset; // LEGIT
-      padding: 0; // LEGIT
-
-      &::after {
-        content: ''; // LEGIT
-      }
-
-      input[type='radio'] {
-        margin-bottom: 1.1em;
-        vertical-align: middle;
-
-        /* stylelint-disable-next-line max-nesting-depth */
-        &::before {
-          top: unset;
-        }
-      }
-    }
-
-    &__label {
-      display: block;
-      font-weight: bold;
-      margin-bottom: $grid-gutter-width * 0.25;
-    }
-
-    &.required > label::after {
-      content: '*';
-      color: theme('colors.critical.200');
-      font-weight: 700;
-      display: inline-block;
-      margin-inline-start: 0.5em;
-      line-height: 1em;
-      font-size: 13px;
-    }
-  }
-
-  // TODO: #CSSoverhaul This should be fixed as part of Wagtail CSS overhaul. The default
-  // `.field`/`.field-componet` (or whatever they become) should be full width by default.
-  // -@jonnyscholes
-  .field-content {
-    float: unset;
-    display: block;
-    width: unset;
-
-    textarea {
-      max-width: 100%;
-    }
-  }
-
-  // TODO: #CSSoverhaul This should be fixed as part of Wagtail CSS overhaul. Whatever we do with
-  // `.field`/`.field-content` should take into account help text -@jonnyscholes
-  .help {
-    margin: 8px 0;
-  }
+.c-sf-help .help {
+  // StreamField block help text is above the blocks rather than below.
+  margin-top: 0;
+  margin-bottom: theme('spacing.[1.5]');
 }

+ 45 - 37
client/src/entrypoints/admin/page-editor.js

@@ -1,5 +1,6 @@
 import $ from 'jquery';
 import { cleanForSlug } from '../../utils/text';
+import { initCollapsiblePanels } from '../../includes/panels';
 
 function InlinePanel(opts) {
   // lgtm[js/unused-local-variable]
@@ -9,21 +10,21 @@ function InlinePanel(opts) {
   self.initChildControls = function (prefix) {
     const childId = 'inline_child_' + prefix;
     const deleteInputId = 'id_' + prefix + '-DELETE';
+    const currentChild = $('#' + childId);
+    const $up = currentChild.find('[data-inline-panel-child-move-up]');
+    const $down = currentChild.find('[data-inline-panel-child-move-down]');
 
     $('#' + deleteInputId + '-button').on('click', () => {
       /* set 'deleted' form field to true */
       $('#' + deleteInputId).val('1');
-      $('#' + childId)
-        .addClass('deleted')
-        .slideUp(() => {
-          self.updateMoveButtonDisabledStates();
-          self.updateAddButtonState();
-        });
+      currentChild.addClass('deleted').slideUp(() => {
+        self.updateMoveButtonDisabledStates();
+        self.updateAddButtonState();
+      });
     });
 
     if (opts.canOrder) {
-      $('#' + prefix + '-move-up').on('click', () => {
-        const currentChild = $('#' + childId);
+      $up.on('click', () => {
         const currentChildOrderElem = currentChild.children(
           'input[name$="-ORDER"]',
         );
@@ -45,8 +46,7 @@ function InlinePanel(opts) {
         self.updateMoveButtonDisabledStates();
       });
 
-      $('#' + prefix + '-move-down').on('click', () => {
-        const currentChild = $('#' + childId);
+      $down.on('click', () => {
         const currentChildOrderElem = currentChild.children(
           'input[name$="-ORDER"]',
         );
@@ -86,20 +86,17 @@ function InlinePanel(opts) {
     }
   };
 
-  self.formsUl = $('#' + opts.formsetPrefix + '-FORMS');
+  self.formsElt = $('#' + opts.formsetPrefix + '-FORMS');
 
-  // eslint-disable-next-line func-names
-  self.updateMoveButtonDisabledStates = function () {
+  self.updateMoveButtonDisabledStates = function updateMoveButtons() {
     if (opts.canOrder) {
-      const forms = self.formsUl.children('li:not(.deleted)');
-      // eslint-disable-next-line func-names
-      forms.each(function (i) {
-        $('ul.controls .inline-child-move-up', this)
-          .toggleClass('disabled', i === 0)
-          .toggleClass('enabled', i !== 0);
-        $('ul.controls .inline-child-move-down', this)
-          .toggleClass('disabled', i === forms.length - 1)
-          .toggleClass('enabled', i !== forms.length - 1);
+      const forms = self.formsElt.children(':not(.deleted)');
+      forms.each(function updateButtonStates(i) {
+        const isFirst = i === 0;
+        const isLast = i === forms.length - 1;
+        console.log(isFirst, isLast);
+        $('[data-inline-panel-child-move-up]', this).prop('disabled', isFirst);
+        $('[data-inline-panel-child-move-down]', this).prop('disabled', isLast);
       });
     }
   };
@@ -107,34 +104,40 @@ function InlinePanel(opts) {
   // eslint-disable-next-line func-names
   self.updateAddButtonState = function () {
     if (opts.maxForms) {
-      const forms = $('> [data-inline-panel-child]', self.formsUl).not(
+      const forms = $('> [data-inline-panel-child]', self.formsElt).not(
         '.deleted',
       );
       const addButton = $('#' + opts.formsetPrefix + '-ADD');
 
       if (forms.length >= opts.maxForms) {
-        addButton.addClass('disabled');
+        addButton.prop('disabled', true);
       } else {
-        addButton.removeClass('disabled');
+        addButton.prop('disabled', false);
       }
     }
   };
 
   // eslint-disable-next-line func-names
   self.animateSwap = function (item1, item2) {
-    const parent = self.formsUl;
-    const children = parent.children('li:not(.deleted)');
-
-    // Apply moving class to container (ul.multiple) so it can assist absolute positioning of it's children
-    // Also set it's relatively calculated height to be an absolute one,
-    // to prevent the containercollapsing while its children go absolute
-    parent.addClass('moving').css('height', parent.height());
+    const parent = self.formsElt;
+    const children = parent.children(':not(.deleted)');
+
+    // Position children absolutely and add hard-coded height
+    // to prevent scroll jumps when reordering.
+    parent.css({
+      position: 'relative',
+      height: parent.height(),
+    });
 
     children
       .each(function moveChildTop() {
         $(this).css('top', $(this).position().top);
       })
-      .addClass('moving');
+      .css({
+        // Set this after the actual position so the items animate correctly.
+        position: 'absolute',
+        width: '100%',
+      });
 
     // animate swapping around
     item1.animate(
@@ -143,8 +146,8 @@ function InlinePanel(opts) {
       },
       200,
       () => {
-        parent.removeClass('moving').removeAttr('style');
-        children.removeClass('moving').removeAttr('style');
+        parent.removeAttr('style');
+        children.removeAttr('style');
       },
     );
 
@@ -154,8 +157,8 @@ function InlinePanel(opts) {
       },
       200,
       () => {
-        parent.removeClass('moving').removeAttr('style');
-        children.removeClass('moving').removeAttr('style');
+        parent.removeAttr('style');
+        children.removeAttr('style');
       },
     );
   };
@@ -177,6 +180,11 @@ function InlinePanel(opts) {
 
       self.updateMoveButtonDisabledStates();
       self.updateAddButtonState();
+      initCollapsiblePanels(
+        document.querySelectorAll(
+          `#inline_child_${newChildPrefix} [data-panel-toggle]`,
+        ),
+      );
 
       if (opts.onAdd) opts.onAdd();
     },

+ 2 - 3
client/src/entrypoints/contrib/typed_table_block/__snapshots__/typed_table_block.test.js.snap

@@ -82,11 +82,10 @@ exports[`wagtail.contrib.typed_table_block.blocks.TypedTableBlock it renders cor
           </table>
         </div>
       
-        <span>
+        <div class=\\"c-sf-help\\">
           <div class=\\"help\\">
-            <div class=\\"icon-help\\">?</div>
             use <strong>plenty</strong> of these
           </div>
-        </span>
+        </div>
       </div>"
 `;

+ 2 - 3
client/src/entrypoints/contrib/typed_table_block/typed_table_block.js

@@ -105,12 +105,11 @@ export class TypedTableBlock {
     if (this.blockDef.meta.helpText) {
       // help text is left unescaped as per Django conventions
       dom.append(`
-        <span>
+        <div class="c-sf-help">
           <div class="help">
-            ${this.blockDef.meta.helpIcon}
             ${this.blockDef.meta.helpText}
           </div>
-        </span>
+        </div>
       `);
     }
 

+ 1 - 1
docs/advanced_topics/customisation/page_editing_interface.md

@@ -19,7 +19,7 @@ class BlogPage(Page):
     ]
     sidebar_content_panels = [
         FieldPanel('advert'),
-        InlinePanel('related_links', label="Related links"),
+        InlinePanel('related_links', heading="Related links", label="Related link"),
     ]
 
     edit_handler = TabbedInterface([

+ 2 - 2
docs/reference/pages/panels.md

@@ -346,7 +346,7 @@ class BookPage(Page):
     # ...
 
     content_panels = Page.content_panels + [
-        InlinePanel('related_links', label="Related Links"),
+        InlinePanel('related_links', heading="Related Links", label="Related link"),
     ]
 ```
 
@@ -356,7 +356,7 @@ The `RelatedLink` class is a vanilla Django abstract model. The `BookPageRelated
 InlinePanel(relation_name, panels=None, heading='', label='', help_text='', min_num=None, max_num=None)
 ```
 
-The `relation_name` is the `related_name` label given to the cluster's `ParentalKey` relation. You can add the `panels` manually or make them part of the cluster model. `heading` and `help_text` provide a heading and caption, respectively, for the Wagtail editor. `label` sets the text on the add button, and is used as the heading when `heading` is not present. Finally, `min_num` and `max_num` allow you to set the minimum/maximum number of forms that the user must submit.
+The `relation_name` is the `related_name` label given to the cluster's `ParentalKey` relation. You can add the `panels` manually or make them part of the cluster model. `heading` and `help_text` provide a heading and caption, respectively, for the Wagtail editor. `label` sets the text on the add button and child panels, and is used as the heading when `heading` is not present. Finally, `min_num` and `max_num` allow you to set the minimum/maximum number of forms that the user must submit.
 
 For another example of using model clusters, see {ref}`tagging`.
 

+ 1 - 1
docs/topics/pages.md

@@ -54,7 +54,7 @@ class BlogPage(Page):
     content_panels = Page.content_panels + [
         FieldPanel('date'),
         FieldPanel('body'),
-        InlinePanel('related_links', label="Related links"),
+        InlinePanel('related_links', heading="Related links", label="Related link"),
     ]
 
     promote_panels = [

+ 2 - 0
wagtail/admin/forms/workflows.py

@@ -211,6 +211,8 @@ def get_workflow_edit_handler():
                 FieldPanel("task", widget=AdminTaskChooser(show_clear_link=False)),
             ],
             heading=_("Add tasks to your workflow"),
+            label=_("Task"),
+            icon="thumbtack",
         ),
     ]
     edit_handler = ObjectList(panels, base_form_class=WagtailAdminModelForm)

+ 7 - 1
wagtail/admin/panels.py

@@ -730,7 +730,10 @@ class FieldPanel(Panel):
             return self.bound_field.field.required
 
         def classes(self):
-            return self.panel.classes()
+            is_streamfield = isinstance(self.bound_field.field, BlockField)
+            extra_classes = ["w-panel--nested"] if is_streamfield else []
+
+            return self.panel.classes() + extra_classes
 
         @property
         def icon(self):
@@ -959,6 +962,9 @@ class InlinePanel(Panel):
         manager = getattr(self.model, self.relation_name)
         self.db_field = manager.rel
 
+    def classes(self):
+        return super().classes() + ["w-panel--nested"]
+
     class BoundPanel(Panel.BoundPanel):
         template_name = "wagtailadmin/panels/inline_panel.html"
 

+ 1 - 3
wagtail/admin/templates/wagtailadmin/icons/bin.svg

@@ -1,3 +1 @@
-<svg id="icon-bin" viewBox="0 0 16 16">
-    <path d="M6.281 6.563v5.156c0 0.094-0.031 0.156-0.063 0.188-0.063 0.063-0.125 0.094-0.219 0.094h-0.563c-0.094 0-0.156-0.031-0.219-0.094-0.063-0.031-0.063-0.094-0.063-0.188v-5.156c0-0.063 0-0.156 0.063-0.188 0.063-0.063 0.125-0.094 0.219-0.094h0.563c0.094 0 0.156 0.031 0.219 0.094 0.031 0.031 0.063 0.125 0.063 0.188zM8.563 6.563v5.156c0 0.094-0.031 0.156-0.063 0.188-0.063 0.063-0.125 0.094-0.219 0.094h-0.563c-0.094 0-0.156-0.031-0.219-0.094-0.031-0.031-0.063-0.094-0.063-0.188v-5.156c0-0.063 0.031-0.156 0.063-0.188 0.063-0.063 0.125-0.094 0.219-0.094h0.563c0.094 0 0.156 0.031 0.219 0.094 0.031 0.031 0.063 0.125 0.063 0.188zM10.844 6.563v5.156c0 0.094 0 0.156-0.063 0.188-0.063 0.063-0.125 0.094-0.219 0.094h-0.563c-0.094 0-0.156-0.031-0.219-0.094-0.031-0.031-0.063-0.094-0.063-0.188v-5.156c0-0.063 0.031-0.156 0.063-0.188 0.063-0.063 0.125-0.094 0.219-0.094h0.563c0.094 0 0.156 0.031 0.219 0.094 0.063 0.031 0.063 0.125 0.063 0.188zM12 13.031v-8.469h-8v8.469c0 0.125 0.031 0.25 0.063 0.375 0.031 0.094 0.094 0.188 0.125 0.219 0.063 0.063 0.094 0.094 0.094 0.094h7.438c0 0 0.031-0.031 0.094-0.094 0.031-0.031 0.094-0.125 0.125-0.219 0.031-0.125 0.063-0.25 0.063-0.375zM6 3.438h4l-0.438-1.063c-0.031-0.031-0.094-0.063-0.156-0.094h-2.813c-0.063 0.031-0.125 0.063-0.156 0.094zM14.281 3.719v0.563c0 0.094-0.031 0.156-0.063 0.219-0.063 0.031-0.125 0.063-0.219 0.063h-0.844v8.469c0 0.5-0.156 0.938-0.438 1.281-0.281 0.375-0.625 0.531-1 0.531h-7.438c-0.375 0-0.719-0.156-1-0.5s-0.438-0.781-0.438-1.281v-8.5h-0.844c-0.094 0-0.156-0.031-0.219-0.063-0.031-0.063-0.063-0.125-0.063-0.219v-0.563c0-0.094 0.031-0.156 0.063-0.219 0.063-0.031 0.125-0.063 0.219-0.063h2.75l0.625-1.5c0.094-0.219 0.25-0.406 0.5-0.563 0.219-0.156 0.469-0.219 0.688-0.219h2.875c0.219 0 0.469 0.063 0.688 0.219 0.25 0.156 0.406 0.344 0.5 0.563l0.625 1.5h2.75c0.094 0 0.156 0.031 0.219 0.063 0.031 0.063 0.063 0.125 0.063 0.219z"></path>
-</svg>
+<svg id="icon-bin" viewBox="0 0 448 512"><path d="M268 416h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12zM432 80h-82.41l-34-56.7A48 48 0 0 0 274.41 0H173.59a48 48 0 0 0-41.16 23.3L98.41 80H16A16 16 0 0 0 0 96v16a16 16 0 0 0 16 16h16v336a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128h16a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16zM171.84 50.91A6 6 0 0 1 177 48h94a6 6 0 0 1 5.15 2.91L293.61 80H154.39zM368 464H80V128h288zm-212-48h24a12 12 0 0 0 12-12V188a12 12 0 0 0-12-12h-24a12 12 0 0 0-12 12v216a12 12 0 0 0 12 12z"/></svg>

+ 9 - 9
wagtail/admin/templates/wagtailadmin/panels/inline_panel.html

@@ -2,19 +2,19 @@
 
 {{ self.formset.management_form }}
 
-<ul class="multiple" id="id_{{ self.formset.prefix }}-FORMS">
+<div id="id_{{ self.formset.prefix }}-FORMS">
     {% if self.formset.non_form_errors %}
-        <li class="error-message">
+        <div class="error-message">
             {% for error in self.formset.non_form_errors %}
                 <span>{{ error|escape }}</span>
             {% endfor %}
-        </li>
+        </div>
     {% endif %}
 
     {% for child in self.children %}
         {% include "wagtailadmin/panels/inline_panel_child.html" %}
     {% endfor %}
-</ul>
+</div>
 
 <script type="text/django-form-template" id="id_{{ self.formset.prefix }}-EMPTY_FORM_TEMPLATE">
     {% escapescript %}
@@ -22,12 +22,12 @@
     {% endescapescript %}
 </script>
 
-<p class="add">
-    <button type="button" class="button bicolor button--icon" id="id_{{ self.formset.prefix }}-ADD">
-        {% icon name="plus" wrapped=1 %}
-        {% blocktrans trimmed with label=self.label|lower %}Add {{ label }}{% endblocktrans %}
+{# Align with guiding line of the preceding child panel. #}
+<div class="w-mb-4 -w-ml-0.5">
+    <button type="button" class="button button-small button-secondary chooser__choose-button" id="id_{{ self.formset.prefix }}-ADD">
+        {% icon name=icon|default:"plus-inverse" %}{% blocktrans trimmed with label=self.label|lower %}Add {{ label }}{% endblocktrans %}
     </button>
-</p>
+</div>
 
 <script>
     (function() {

+ 22 - 17
wagtail/admin/templates/wagtailadmin/panels/inline_panel_child.html

@@ -1,20 +1,25 @@
 {% load i18n wagtailadmin_tags %}
-<li data-inline-panel-child id="inline_child_{{ child.form.prefix }}" data-contentpath-disabled>
-    {% if child.form.non_field_errors %}
-        <ul>
-            {% for error in child.form.non_field_errors %}
-                <li class="error-message">
-                    <span>{{ error|escape }}</span>
-                </li>
-            {% endfor %}
-        </ul>
-    {% endif %}
-    <ul class="controls">
+
+{% fragment as id %}inline_child_{{ child.form.prefix }}{% endfragment %}
+{% fragment as panel_id %}{{ id }}-panel{% endfragment %}
+<div data-inline-panel-child id="{{ id }}" data-contentpath-disabled>
+    {% fragment as header_controls %}
         {% if can_order %}
-            <li><button type="button" class="button button-small button--icon text-replace white inline-child-move-up" id="{{ child.form.prefix }}-move-up" title="{% trans 'Move up' %}">{% icon name="order-up" %}{% trans "Move up" %}</button></li>
-            <li><button type="button" class="button button-small button--icon text-replace white inline-child-move-down" id="{{ child.form.prefix }}-move-down" title="{% trans 'Move down' %}">{% icon name="order-down" %}{% trans "Move down" %}</button></li>
+            <button type="button" class="button button--icon text-replace white" data-inline-panel-child-move-up title="{% trans 'Move up' %}">{% icon name="arrow-up" %}</button>
+            <button type="button" class="button button--icon text-replace white" data-inline-panel-child-move-down title="{% trans 'Move down' %}">{% icon name="arrow-down" %}</button>
         {% endif %}
-        <li><button type="button" class="button button-small button--icon text-replace white hover-no" id="{{ child.form.DELETE.id_for_label }}-button" title="{% trans 'Delete' %}">{% icon name="bin" %}{% trans "Delete" %}</button></li>
-    </ul>
-    {{ child.render_form_content }}
-</li>
+        <button type="button" class="button button--icon text-replace white" id="{{ child.form.DELETE.id_for_label }}-button" title="{% trans 'Delete' %}">{% icon name="bin" %}</button>
+    {% endfragment %}
+    {% panel id=panel_id heading=self.label heading_size="label" header_controls=header_controls %}
+        {% if child.form.non_field_errors %}
+            <ul>
+                {% for error in child.form.non_field_errors %}
+                    <li class="error-message">
+                        <span>{{ error|escape }}</span>
+                    </li>
+                {% endfor %}
+            </ul>
+        {% endif %}
+        {{ child.render_form_content }}
+    {% endpanel %}
+</div>

+ 23 - 11
wagtail/admin/templates/wagtailadmin/shared/panel.html

@@ -11,6 +11,7 @@
     id_for_label - id of an associated field.
     is_required - If the panel contains a required field.
     children - The panel’s contents.
+    header_controls - Additional panel buttons to display in the header area.
 
 {% endcomment %}
 {% fragment as prefix %}{% if id_prefix %}{{ id_prefix }}-{% endif %}{{ id }}{% endfragment %}
@@ -18,26 +19,37 @@
 {% fragment as heading_id %}{{ prefix }}-heading{% endfragment %}
 {% fragment as content_id %}{{ prefix }}-content{% endfragment %}
 <section class="w-panel {{ classname }}" id="{{ panel_id }}" aria-labelledby="{{ heading_id }}" data-panel>
-    {# If a panel has no heading, we don’t want any of the associated UI. #}
-    {% if heading %}
+    {# If a panel has no heading nor header controls, we don’t want any of the associated UI. #}
+    {% if heading or header_controls %}
         <div class="w-panel__header">
-            <a class="w-panel__anchor w-hidden sm:w-inline-grid" href="#{{ panel_id }}" aria-labelledby="{{ heading_id }}">
+            <a class="w-panel__anchor w-panel__anchor--prefix" href="#{{ panel_id }}" aria-labelledby="{{ heading_id }}">
                 {% icon name="link" class_name="w-panel__icon" %}
             </a>
             <button class="w-panel__toggle" type="button" aria-label="{% trans 'Toggle section' %}" aria-describedby="{{ heading_id }}" data-panel-toggle aria-controls="{{ content_id }}" aria-expanded="true">
                 {% firstof icon "arrow-down-big" as icon_name %}
                 {% icon name=icon_name class_name="w-panel__icon" %}
             </button>
-            <h2 class="w-panel__heading {% if heading_size == "label" %}w-panel__heading--label{% endif %}" id="{{ heading_id }}" data-panel-heading>
-                {% if id_for_label %}
-                    <label for="{{ id_for_label }}" id="{{ id_for_label }}-label">{{ heading }}{% if is_required %}<span class="w-required-mark">*</span>{% endif %}</label>
-                {% else %}
-                    {{ heading }}{% if is_required %}<span class="w-required-mark">*</span>{% endif %}
-                {% endif %}
-            </h2>
-            <a class="w-panel__anchor sm:w-hidden" href="#{{ panel_id }}" aria-labelledby="{{ heading_id }}">
+            {% if heading %}
+                <h2 class="w-panel__heading {% if heading_size == "label" %}w-panel__heading--label{% endif %}" id="{{ heading_id }}" data-panel-heading>
+                    {% if id_for_label %}
+                        <label for="{{ id_for_label }}" id="{{ id_for_label }}-label">{{ heading }}{% if is_required %}<span class="w-required-mark">*</span>{% endif %}</label>
+                    {% else %}
+                        {{ heading }}{% if is_required %}<span class="w-required-mark">*</span>{% endif %}
+                    {% endif %}
+                </h2>
+            {% endif %}
+            <a class="w-panel__anchor w-panel__anchor--suffix" href="#{{ panel_id }}" aria-labelledby="{{ heading_id }}">
                 {% icon name="link" class_name="w-panel__icon" %}
             </a>
+            <div class="w-panel__divider"></div>
+            {% if header_controls %}
+                <div class="w-panel__controls">
+                    <div class="w-panel__controls-cue">
+                        {% icon name="dots-horizontal" class_name="w-panel__icon" %}
+                    </div>
+                    {{ header_controls }}
+                </div>
+            {% endif %}
         </div>
     {% endif %}
 

+ 1 - 1
wagtail/admin/templates/wagtailadmin/workflows/create.html

@@ -24,7 +24,7 @@
             {% block form %}{{ edit_handler.render_form_content }}{% endblock %}
 
             {% trans "Assign your workflow to pages" as heading %}
-            {% panel id="workflow-pages" heading=heading %}
+            {% panel id="workflow-pages" icon="doc-empty-inverse" heading=heading %}
                 {% include "wagtailadmin/workflows/includes/workflow_pages_formset.html" with formset=pages_formset %}
             {% endpanel %}
         </div>

+ 1 - 1
wagtail/admin/templates/wagtailadmin/workflows/edit.html

@@ -25,7 +25,7 @@
             {% block form %}{{ edit_handler.render_form_content }}{% endblock %}
 
             {% trans "Assign your workflow to pages" as heading %}
-            {% panel id="workflow-pages" heading=heading  %}
+            {% panel id="workflow-pages" icon="doc-empty-inverse" heading=heading %}
                 {% if workflow.active %}
                     <p class="help-block help-info">
                         {% icon name='help' %}

+ 27 - 18
wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotion_form.html

@@ -1,23 +1,32 @@
 {% load i18n wagtailadmin_tags %}
-<li id="inline_child_{{ form.prefix }}"{% if form.DELETE.value %} style="display: none;"{% endif %}>
-    <ul class="controls">
-        <li><button type="button" class="button button--icon text-replace inline-child-move-up" id="{{ form.prefix }}-move-up">{% icon name="order-up" %}{% trans "Move up" %}</button></li>
-        <li><button type="button" class="button button--icon text-replace inline-child-move-down" id="{{ form.prefix }}-move-down">{% icon name="order-down" %}{% trans "Move down" %}</button></li>
-        <li><button type="button" class="button button--icon text-replace" id="{{ form.DELETE.id_for_label }}-button">{% icon name="bin" %}{% trans "Delete" %}</button></li>
-    </ul>
 
-    <fieldset>
-        <legend class="w-sr-only">{% trans "Promoted search result" %}</legend>
-        <ul class="fields">
-            <li class="model_choice_field">
-                {% include "wagtailadmin/shared/field.html" with field=form.page only %}
-            </li>
-            <li class="char_field">
-                {% include "wagtailadmin/shared/field.html" with field=form.description only %}
-            </li>
-        </ul>
-    </fieldset>
+{% fragment as id %}inline_child_{{ form.prefix }}{% endfragment %}
+{% fragment as panel_id %}{{ id }}-panel{% endfragment %}
+<div id="{{ id }}"{% if form.DELETE.value %} style="display: none;"{% endif %}>
+
+    {% fragment as header_controls %}
+        <button type="button" class="button button--icon text-replace" data-inline-panel-child-move-up>{% icon name="arrow-up" %}{% trans "Move up" %}</button>
+        <button type="button" class="button button--icon text-replace" data-inline-panel-child-move-down>{% icon name="arrow-down" %}{% trans "Move down" %}</button>
+        <button type="button" class="button button--icon text-replace" id="{{ form.DELETE.id_for_label }}-button">{% icon name="bin" %}{% trans "Delete" %}</button>
+    {% endfragment %}
+
+    {% trans "Recommended page" as heading %}
+    {% panel id=panel_id heading=heading heading_size="label" header_controls=header_controls %}
+        {% if form.non_field_errors %}
+            <ul>
+                {% for error in form.non_field_errors %}
+                    <li class="error-message">
+                        <span>{{ error|escape }}</span>
+                    </li>
+                {% endfor %}
+            </ul>
+        {% endif %}
+
+        {% include "wagtailadmin/shared/field.html" with field=form.page only %}
+        {% include "wagtailadmin/shared/field.html" with field=form.description only %}
+    {% endpanel %}
+
     {{ form.id }}
     {{ form.ORDER }}
     {{ form.DELETE }}
-</li>
+</div>

+ 15 - 8
wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotions_formset.html

@@ -1,10 +1,14 @@
 {% load i18n wagtailadmin_tags %}
 {{ formset.management_form }}
-<ul class="multiple" id="id_{{ formset.prefix }}-FORMS">
-    {% for form in formset.forms %}
-        {% include "wagtailsearchpromotions/includes/searchpromotion_form.html" with form=form only %}
-    {% endfor %}
-</ul>
+
+{% trans "Promoted search results" as heading %}
+{% panel id="promoted-search-results" heading=heading heading_size="label" classname="w-panel--nested" %}
+    <div id="id_{{ formset.prefix }}-FORMS">
+        {% for form in formset.forms %}
+            {% include "wagtailsearchpromotions/includes/searchpromotion_form.html" with form=form only %}
+        {% endfor %}
+    </div>
+{% endpanel %}
 
 <script type="text/django-form-template" id="id_{{ formset.prefix }}-EMPTY_FORM_TEMPLATE">
     {% escapescript %}
@@ -12,6 +16,9 @@
     {% endescapescript %}
 </script>
 
-<p class="add">
-    <a class="button bicolor button--icon" id="id_{{ formset.prefix }}-ADD" value="Add">{% icon name="plus" wrapped=1 %}{% trans "Add recommended page" %}</a>
-</p>
+{# Align with guiding line of the preceding child panel. #}
+<div class="w-mb-4 -w-ml-0.5">
+    <button type="button" class="button button-small button-secondary chooser__choose-button" id="id_{{ formset.prefix }}-ADD" value="Add">
+        {% icon name="plus-inverse" %}{% trans "Add recommended page" %}
+    </button>
+</div>

+ 2 - 2
wagtail/test/demosite/models.py

@@ -231,9 +231,9 @@ class StandardPageRelatedLink(Orderable, AbstractRelatedLink):
 
 StandardPage.content_panels = Page.content_panels + [
     FieldPanel("intro"),
-    InlinePanel("carousel_items", label="Carousel items"),
+    InlinePanel("carousel_items", heading="Carousel items", label="Carousel item"),
     FieldPanel("body"),
-    InlinePanel("related_links", label="Related links"),
+    InlinePanel("related_links", heading="Related links", label="Related link"),
 ]