Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment: ToolsPanel: Try moving the menu off the sidebar to improve UX #41523

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ export const PanelColorGradientSettingsInner = ( {
);
} );
} }
menuPosition="left"
panelId={ panelId }
popoverOffset={ 48 }
popoverPlacement="left-start"
__experimentalFirstVisibleItemClass="first"
__experimentalLastVisibleItemClass="last"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ const ToolsPanelHeader = (
headingClassName,
label: labelText,
menuItems,
menuPosition = 'right',
popoverProps,
resetAll,
toggleItem,
...headerProps
Expand All @@ -177,52 +179,63 @@ const ToolsPanelHeader = (
( [ , isSelected ] ) => isSelected
);

const menuJustification =
menuPosition === 'right' ? 'space-between' : 'flex-start';

const dropdown = hasMenuItems && (
<DropdownMenu
icon={ dropDownMenuIcon }
label={ dropDownMenuLabelText }
menuProps={ { className: dropdownMenuClassName } }
toggleProps={ {
isSmall: true,
describedBy: dropdownMenuDescriptionText,
} }
popoverProps={ popoverProps }
>
{ () => (
<>
<DefaultControlsGroup
items={ defaultItems }
toggleItem={ toggleItem }
/>
<OptionalControlsGroup
items={ optionalItems }
toggleItem={ toggleItem }
/>
<MenuGroup>
<MenuItem
aria-disabled={ ! canResetAll }
variant={ 'tertiary' }
onClick={ () => {
if ( canResetAll ) {
resetAll();
speak(
__( 'All options reset' ),
'assertive'
);
}
} }
>
{ __( 'Reset all' ) }
</MenuItem>
</MenuGroup>
</>
) }
</DropdownMenu>
);

return (
<HStack { ...headerProps } ref={ forwardedRef }>
<HStack
{ ...headerProps }
justify={ menuJustification }
ref={ forwardedRef }
>
{ menuPosition === 'left' && dropdown }
<Heading level={ 2 } className={ headingClassName }>
{ labelText }
</Heading>
{ hasMenuItems && (
<DropdownMenu
icon={ dropDownMenuIcon }
label={ dropDownMenuLabelText }
menuProps={ { className: dropdownMenuClassName } }
toggleProps={ {
isSmall: true,
describedBy: dropdownMenuDescriptionText,
} }
>
{ () => (
<>
<DefaultControlsGroup
items={ defaultItems }
toggleItem={ toggleItem }
/>
<OptionalControlsGroup
items={ optionalItems }
toggleItem={ toggleItem }
/>
<MenuGroup>
<MenuItem
aria-disabled={ ! canResetAll }
variant={ 'tertiary' }
onClick={ () => {
if ( canResetAll ) {
resetAll();
speak(
__( 'All options reset' ),
'assertive'
);
}
} }
>
{ __( 'Reset all' ) }
</MenuItem>
</MenuGroup>
</>
) }
</DropdownMenu>
) }
{ menuPosition === 'right' && dropdown }
</HStack>
);
};
Expand Down
20 changes: 19 additions & 1 deletion packages/components/src/tools-panel/tools-panel/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ const ToolsPanel = (
const {
children,
label,
menuPosition,
panelContext,
popoverProps,
resetAllItems,
toggleItem,
...toolsPanelProps
Expand All @@ -33,6 +35,8 @@ const ToolsPanel = (
label={ label }
resetAll={ resetAllItems }
toggleItem={ toggleItem }
menuPosition={ menuPosition }
popoverProps={ popoverProps }
/>
{ children }
</ToolsPanelContext.Provider>
Expand Down
8 changes: 8 additions & 0 deletions packages/components/src/tools-panel/tools-panel/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export function useToolsPanel(
className,
resetAll,
panelId,
popoverOffset,
popoverPlacement,
hasInnerWrapper,
shouldRenderPlaceholderItems,
__experimentalFirstVisibleItemClass,
Expand Down Expand Up @@ -276,6 +278,11 @@ export function useToolsPanel(
[ ...panelItems ].reverse()
);

const popoverProps =
popoverPlacement || popoverOffset
? { placement: popoverPlacement, offset: popoverOffset }
: undefined;

const panelContext = useMemo(
() => ( {
areAllOptionalControlsHidden,
Expand Down Expand Up @@ -312,6 +319,7 @@ export function useToolsPanel(
return {
...otherProps,
panelContext,
popoverProps,
resetAllItems,
toggleItem,
className: classes,
Expand Down
26 changes: 26 additions & 0 deletions packages/components/src/tools-panel/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down