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 && ( + + { () => ( + <> + + + + { + if ( canResetAll ) { + resetAll(); + speak( + __( 'All options reset' ), + 'assertive' + ); + } + } } + > + { __( 'Reset all' ) } + + + + ) } + + ); + return ( - + + { menuPosition === 'left' && dropdown } { labelText } - { hasMenuItems && ( - - { () => ( - <> - - - - { - if ( canResetAll ) { - resetAll(); - speak( - __( 'All options reset' ), - 'assertive' - ); - } - } } - > - { __( 'Reset all' ) } - - - - ) } - - ) } + { 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