From e45b09c01ee7caef541aad5d730dfbfa6460a1a2 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 3 Jun 2022 13:00:17 +1000
Subject: [PATCH] Try out moving the toolspanel menu off the sidebar to improve
UX
---
.../panel-color-gradient-settings.js | 3 +
.../block-support-tools-panel.js | 3 +
.../tools-panel/tools-panel-header/README.md | 14 +++
.../tools-panel-header/component.tsx | 97 +++++++++++--------
.../src/tools-panel/tools-panel/README.md | 20 +++-
.../src/tools-panel/tools-panel/component.tsx | 4 +
.../src/tools-panel/tools-panel/hook.ts | 8 ++
packages/components/src/tools-panel/types.ts | 26 +++++
8 files changed, 132 insertions(+), 43 deletions(-)
diff --git a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js
index 797a6c9463697d..cc43516271353f 100644
--- a/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js
+++ b/packages/block-editor/src/components/colors-gradients/panel-color-gradient-settings.js
@@ -89,7 +89,10 @@ export const PanelColorGradientSettingsInner = ( {
);
} );
} }
+ menuPosition="left"
panelId={ panelId }
+ popoverOffset={ 48 }
+ popoverPlacement="left-start"
__experimentalFirstVisibleItemClass="first"
__experimentalLastVisibleItemClass="last"
>
diff --git a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js
index d582548b5d64ef..fcb82691307dcc 100644
--- a/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js
+++ b/packages/block-editor/src/components/inspector-controls/block-support-tools-panel.js
@@ -67,7 +67,10 @@ export default function BlockSupportToolsPanel( { children, group, label } ) {
label={ label }
resetAll={ resetAll }
key={ panelId }
+ menuPosition="left"
panelId={ panelId }
+ popoverOffset={ 48 }
+ popoverPlacement="left-start"
hasInnerWrapper={ true }
shouldRenderPlaceholderItems={ true } // Required to maintain fills ordering.
__experimentalFirstVisibleItemClass="first"
diff --git a/packages/components/src/tools-panel/tools-panel-header/README.md b/packages/components/src/tools-panel/tools-panel-header/README.md
index 07a7544b6b1435..2c07a88dc7270a 100644
--- a/packages/components/src/tools-panel/tools-panel-header/README.md
+++ b/packages/components/src/tools-panel/tools-panel-header/README.md
@@ -25,6 +25,20 @@ Text to be displayed within the panel header. It is also passed along as the
- Required: Yes
+### `menuPosition`: `left` | `right`
+
+Whether the menu toggle is positioned to the left or right of the panel's
+title.
+
+- Required: No
+- Default: `right`
+
+### `popoverProps`: `Record< string, unknown >`
+
+An internal prop used to control the visibility of the dropdown.
+
+- Required: No
+
### `resetAll`: `() => void`
The `resetAll` prop provides the callback to execute when the "Reset all" menu
diff --git a/packages/components/src/tools-panel/tools-panel-header/component.tsx b/packages/components/src/tools-panel/tools-panel-header/component.tsx
index 62a40a966dcb7d..c439209c5bb073 100644
--- a/packages/components/src/tools-panel/tools-panel-header/component.tsx
+++ b/packages/components/src/tools-panel/tools-panel-header/component.tsx
@@ -152,6 +152,8 @@ const ToolsPanelHeader = (
headingClassName,
label: labelText,
menuItems,
+ menuPosition = 'right',
+ popoverProps,
resetAll,
toggleItem,
...headerProps
@@ -177,52 +179,63 @@ const ToolsPanelHeader = (
( [ , isSelected ] ) => isSelected
);
+ const menuJustification =
+ menuPosition === 'right' ? 'space-between' : 'flex-start';
+
+ const dropdown = hasMenuItems && (
+
+ { () => (
+ <>
+
+
+
+
+
+ >
+ ) }
+
+ );
+
return (
-
+
+ { menuPosition === 'left' && dropdown }
{ labelText }
- { hasMenuItems && (
-
- { () => (
- <>
-
-
-
-
-
- >
- ) }
-
- ) }
+ { menuPosition === 'right' && dropdown }
);
};
diff --git a/packages/components/src/tools-panel/tools-panel/README.md b/packages/components/src/tools-panel/tools-panel/README.md
index 23581f90d75469..7cabf165a6fc84 100644
--- a/packages/components/src/tools-panel/tools-panel/README.md
+++ b/packages/components/src/tools-panel/tools-panel/README.md
@@ -88,7 +88,25 @@ wrapper element allowing the panel to lay them out accordingly.
Text to be displayed within the panel's header and as the `aria-label` for the
panel's dropdown menu.
-- Required: Yes
+### `menuPosition`: `left` | `right`
+
+Whether the menu toggle is positioned to the left or right of the panel's
+header.
+
+- Required: No
+- Default: `right`
+
+### `popoverOffset`: `number`
+
+The space between the popover and the menu toggle.
+
+- Required: No
+
+### `popoverPlacement`: `string`
+
+The position of the menu popover compared to the menu toggle.
+
+- Required: No
### `panelId`: `string`
diff --git a/packages/components/src/tools-panel/tools-panel/component.tsx b/packages/components/src/tools-panel/tools-panel/component.tsx
index fcfa353a0210d7..fe4b3795472a44 100644
--- a/packages/components/src/tools-panel/tools-panel/component.tsx
+++ b/packages/components/src/tools-panel/tools-panel/component.tsx
@@ -20,7 +20,9 @@ const ToolsPanel = (
const {
children,
label,
+ menuPosition,
panelContext,
+ popoverProps,
resetAllItems,
toggleItem,
...toolsPanelProps
@@ -33,6 +35,8 @@ const ToolsPanel = (
label={ label }
resetAll={ resetAllItems }
toggleItem={ toggleItem }
+ menuPosition={ menuPosition }
+ popoverProps={ popoverProps }
/>
{ children }
diff --git a/packages/components/src/tools-panel/tools-panel/hook.ts b/packages/components/src/tools-panel/tools-panel/hook.ts
index 670bb08c17d284..d47966eeb71e46 100644
--- a/packages/components/src/tools-panel/tools-panel/hook.ts
+++ b/packages/components/src/tools-panel/tools-panel/hook.ts
@@ -59,6 +59,8 @@ export function useToolsPanel(
className,
resetAll,
panelId,
+ popoverOffset,
+ popoverPlacement,
hasInnerWrapper,
shouldRenderPlaceholderItems,
__experimentalFirstVisibleItemClass,
@@ -276,6 +278,11 @@ export function useToolsPanel(
[ ...panelItems ].reverse()
);
+ const popoverProps =
+ popoverPlacement || popoverOffset
+ ? { placement: popoverPlacement, offset: popoverOffset }
+ : undefined;
+
const panelContext = useMemo(
() => ( {
areAllOptionalControlsHidden,
@@ -312,6 +319,7 @@ export function useToolsPanel(
return {
...otherProps,
panelContext,
+ popoverProps,
resetAllItems,
toggleItem,
className: classes,
diff --git a/packages/components/src/tools-panel/types.ts b/packages/components/src/tools-panel/types.ts
index 3290b9fe497fc7..bd559a26211866 100644
--- a/packages/components/src/tools-panel/types.ts
+++ b/packages/components/src/tools-panel/types.ts
@@ -21,12 +21,27 @@ export type ToolsPanelProps = {
* for the panel's dropdown menu.
*/
label: string;
+ /**
+ * Whether the menu toggle is positioned to the left or right of the panel's
+ * header.
+ *
+ * @default 'right'
+ */
+ menuPosition?: 'left' | 'right';
/**
* If a `panelId` is set, it is passed through the `ToolsPanelContext` and
* used to restrict panel items. Only items with a matching `panelId` will
* be able to register themselves with this panel.
*/
panelId: string;
+ /**
+ * The space between the popover and the menu toggle.
+ */
+ popoverOffset?: number;
+ /**
+ * The position of the menu popover compared to the menu toggle.
+ */
+ popoverPlacement?: string;
/**
* A function to call when the `Reset all` menu option is selected. This is
* passed through to the panel's header component.
@@ -55,6 +70,17 @@ export type ToolsPanelHeaderProps = {
* the `label` for the panel header's `DropdownMenu`.
*/
label: string;
+ /**
+ * Whether the menu toggle is positioned to the left or right of the panel's
+ * header.
+ *
+ * @default true
+ */
+ menuPosition?: 'left' | 'right';
+ /**
+ * An internal prop used to control the visibility of the dropdown.
+ */
+ popoverProps?: Record< string, unknown >;
/**
* The `resetAll` prop provides the callback to execute when the "Reset all"
* menu item is selected. Its purpose is to facilitate resetting any control