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

Components: Refactor DropdownMenu to stop using unstable props #15968

Merged
merged 5 commits into from Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -25,6 +25,11 @@ import BlockUnknownConvertButton from './block-unknown-convert-button';
import __experimentalBlockSettingsMenuFirstItem from './block-settings-menu-first-item';
import __experimentalBlockSettingsMenuPluginsExtension from './block-settings-menu-plugins-extension';

const POPOVER_PROPS = {
className: 'block-editor-block-settings-menu__popover editor-block-settings-menu__popover',
position: 'bottom right',
};

export function BlockSettingsMenu( { clientIds } ) {
const blockClientIds = castArray( clientIds );
const count = blockClientIds.length;
Expand All @@ -45,11 +50,8 @@ export function BlockSettingsMenu( { clientIds } ) {
<DropdownMenu
icon="ellipsis"
label={ __( 'More options' ) }
position="bottom right"
className="block-editor-block-settings-menu"
__unstableToggleClassName="block-editor-block-settings-menu__toggle editor-block-settings-menu__toggle"
__unstableMenuClassName="block-editor-block-settings-menu__content editor-block-settings-menu__content"
__unstablePopoverClassName="block-editor-block-settings-menu__popover editor-block-settings-menu__popover"
popoverProps={ POPOVER_PROPS }
>
{ ( { onClose } ) => (
<>
Expand Down
@@ -1,7 +1,7 @@
.block-editor-block-settings-menu__content {
padding: 0;
.block-editor-block-settings-menu .components-dropdown-menu__toggle .dashicon {
transform: rotate(90deg);
}

.block-editor-block-settings-menu__toggle .dashicon {
transform: rotate(90deg);
.block-editor-block-settings-menu__popover .components-dropdown-menu__menu {
padding: 0;
}
Expand Up @@ -11,6 +11,10 @@ import { orderBy } from 'lodash';
import { __ } from '@wordpress/i18n';
import { Toolbar, Slot, DropdownMenu } from '@wordpress/components';

const POPOVER_PROPS = {
position: 'bottom left',
};

const FormatToolbar = () => {
return (
<div className="editor-format-toolbar block-editor-format-toolbar">
Expand All @@ -22,9 +26,9 @@ const FormatToolbar = () => {
{ ( fills ) => fills.length !== 0 &&
<DropdownMenu
icon={ false }
position="bottom left"
label={ __( 'More Rich Text Controls' ) }
controls={ orderBy( fills.map( ( [ { props } ] ) => props ), 'title' ) }
popoverProps={ POPOVER_PROPS }
/>
}
</Slot>
Expand Down
10 changes: 9 additions & 1 deletion packages/components/CHANGELOG.md
Expand Up @@ -2,8 +2,16 @@

### New Features

- Added a new `popoverProps` prop to the `Dropdown` component which allows users of the `Dropdown` component to pass props directly to the `PopOver` component.
- Added a new `popoverProps` prop to the `Dropdown` component which allows users of the `Dropdown` component to pass props directly to the `Popover` component.
- Added and documented `hideLabelFromVision` prop to `BaseControl` used by `SelectControl`, `TextControl`, and `TextareaControl`.
- Added a new `popoverProps` prop to the `DropdownMenu` component which allows to pass props directly to the nested `Popover` component.
- Added a new `toggleProps` prop to the `DropdownMenu` component which allows to pass props directly to the nested `IconButton` component.
- Added a new `menuProps` prop to the `DropdownMenu` component which allows to pass props directly to the nested `NavigableMenu` component.

### Deprecations

- `menuLabel` prop in `DropdownComponent` has been deprecated. Consider using `menuProps` object and its `aria-label` property instead.
- `position` prop in `DropdownComponent` has been deprecated. Consider using `popoverProps` object and its `position` property instead.

### Bug Fixes

Expand Down
41 changes: 25 additions & 16 deletions packages/components/src/dropdown-menu/README.md
Expand Up @@ -163,21 +163,6 @@ A human-readable label to present as accessibility text on the focused collapsed
- Type: `String`
- Required: Yes

#### menuLabel

A human-readable label to present as accessibility text on the expanded menu container.

- Type: `String`
- Required: No

#### position

The direction in which the menu should open. Specify y- and x-axis as a space-separated string. Supports `"top"`, `"middle"`, `"bottom"` y axis, and `"left"`, `"center"`, `"right"` x axis.

- Type: `String`
- Required: No
- Default: `"top center"`

#### controls

An array of objects describing the options to be shown in the expanded menu.
Expand All @@ -202,7 +187,31 @@ See also: [https://developer.wordpress.org/resource/dashicons/](https://develope

#### className

A class name to apply to the dropdown wrapper element.
A class name to apply to the dropdown menu's toggle element wrapper.

- Type: `String`
- Required: No

#### popoverProps

Properties of `popoverProps` object will be passed as props to the nested `Popover` component.
Use this object to modify props available for the `Popover` component that are not already exposed in the `DropdownMenu` component, e.g.: the direction in which the popover should open relative to its parent node set with `position` prop.

- Type: `Object`
- Required: No

#### toggleProps

Properties of `toggleProps` object will be passed as props to the nested `IconButton` component in the `renderToggle` implementation of the `Dropdown` component used internally.
Use this object to modify props available for the `IconButton` component that are not already exposed in the `DropdownMenu` component, e.g.: the tooltip text displayed on hover set with `tooltip` prop.

- Type: `Object`
- Required: No

#### menuProps

Properties of `menuProps` object will be passed as props to the nested `NavigableMenu` component in the `renderContent` implementation of the `Dropdown` component used internally.
Use this object to modify props available for the `NavigableMenu` component that are not already exposed in the `DropdownMenu` component, e.g.: the orientation of the menu set with `orientation` prop.

- Type: `Object`
- Required: No
63 changes: 50 additions & 13 deletions packages/components/src/dropdown-menu/index.js
Expand Up @@ -8,6 +8,7 @@ import { flatMap, isEmpty, isFunction } from 'lodash';
* WordPress dependencies
*/
import { DOWN } from '@wordpress/keycodes';
import deprecated from '@wordpress/deprecated';

/**
* Internal dependencies
Expand All @@ -16,20 +17,47 @@ import IconButton from '../icon-button';
import Dropdown from '../dropdown';
import { NavigableMenu } from '../navigable-container';

function mergeProps( defaultProps = {}, props = {} ) {
const mergedProps = {
...defaultProps,
...props,
};

if ( props.className && defaultProps.className ) {
mergedProps.className = classnames( props.className, defaultProps.className );
}

return mergedProps;
}

function DropdownMenu( {
children,
className,
controls,
hasArrowIndicator = false,
icon = 'menu',
label,
popoverProps,
toggleProps,
menuProps,
// The following props exist for backward compatibility.
menuLabel,
position,
__unstableLabelPosition,
__unstableMenuClassName,
__unstablePopoverClassName,
__unstableToggleClassName,
} ) {
if ( menuLabel ) {
deprecated( '`menuLabel` prop in `DropdownComponent`', {
alternative: '`menuProps` object and its `aria-label` property',
plugin: 'Gutenberg',
} );
}

if ( position ) {
deprecated( '`position` prop in `DropdownComponent`', {
alternative: '`popoverProps` object and its `position` property',
plugin: 'Gutenberg',
} );
}

if ( isEmpty( controls ) && ! isFunction( children ) ) {
return null;
}
Expand All @@ -42,12 +70,15 @@ function DropdownMenu( {
controlSets = [ controlSets ];
}
}
const mergedPopoverProps = mergeProps( {
className: 'components-dropdown-menu__popover',
position,
}, popoverProps );

return (
<Dropdown
className={ classnames( 'components-dropdown-menu', className ) }
contentClassName={ classnames( 'components-dropdown-menu__popover', __unstablePopoverClassName ) }
position={ position }
popoverProps={ mergedPopoverProps }
renderToggle={ ( { isOpen, onToggle } ) => {
const openOnArrowDown = ( event ) => {
if ( ! isOpen && event.keyCode === DOWN ) {
Expand All @@ -56,31 +87,37 @@ function DropdownMenu( {
onToggle();
}
};
const mergedToggleProps = mergeProps( {
className: classnames( 'components-dropdown-menu__toggle', {
'is-opened': isOpen,
} ),
tooltip: label,
}, toggleProps );

return (
<IconButton
className={ classnames( 'components-dropdown-menu__toggle', __unstableToggleClassName, {
'is-opened': isOpen,
} ) }
{ ...mergedToggleProps }
icon={ icon }
onClick={ onToggle }
onKeyDown={ openOnArrowDown }
aria-haspopup="true"
aria-expanded={ isOpen }
label={ label }
labelPosition={ __unstableLabelPosition }
tooltip={ label }
>
{ ( ! icon || hasArrowIndicator ) && <span className="components-dropdown-menu__indicator" /> }
</IconButton>
);
} }
renderContent={ ( props ) => {
const mergedMenuProps = mergeProps( {
'aria-label': menuLabel || label,
className: 'components-dropdown-menu__menu',
}, menuProps );

return (
<NavigableMenu
className={ classnames( 'components-dropdown-menu__menu', __unstableMenuClassName ) }
{ ...mergedMenuProps }
role="menu"
aria-label={ menuLabel || label }
>
{
isFunction( children ) ?
Expand Down
2 changes: 1 addition & 1 deletion packages/e2e-tests/specs/block-grouping.test.js
Expand Up @@ -146,7 +146,7 @@ describe( 'Block Grouping', () => {
it( 'does not show group option in the options toolbar if Grouping block is disabled ', async () => {
await clickBlockToolbarButton( 'More options' );

const blockOptionsDropdownHTML = await page.evaluate( () => document.querySelector( '.block-editor-block-settings-menu__content' ).innerHTML );
const blockOptionsDropdownHTML = await page.evaluate( () => document.querySelector( '.block-editor-block-settings-menu__popover' ).innerHTML );

expect( blockOptionsDropdownHTML ).not.toContain( 'Group' );
} );
Expand Down
13 changes: 10 additions & 3 deletions packages/edit-post/src/components/header/more-menu/index.js
Expand Up @@ -13,14 +13,21 @@ import ToolsMoreMenuGroup from '../tools-more-menu-group';
import OptionsMenuItem from '../options-menu-item';
import WritingMenu from '../writing-menu';

const POPOVER_PROPS = {
className: 'edit-post-more-menu__content',
position: 'bottom left',
};
const TOGGLE_PROPS = {
labelPosition: 'bottom',
};

const MoreMenu = () => (
<DropdownMenu
className="edit-post-more-menu"
position="bottom left"
icon="ellipsis"
label={ __( 'More tools & options' ) }
__unstableLabelPosition="bottom"
__unstablePopoverClassName="edit-post-more-menu__content"
popoverProps={ POPOVER_PROPS }
toggleProps={ TOGGLE_PROPS }
>
{ ( { onClose } ) => (
<>
Expand Down
Expand Up @@ -3,17 +3,29 @@
exports[`MoreMenu should match snapshot 1`] = `
<MoreMenu>
<DropdownMenu
__unstableLabelPosition="bottom"
__unstablePopoverClassName="edit-post-more-menu__content"
className="edit-post-more-menu"
icon="ellipsis"
label="More tools & options"
position="bottom left"
popoverProps={
Object {
"className": "edit-post-more-menu__content",
"position": "bottom left",
}
}
toggleProps={
Object {
"labelPosition": "bottom",
}
}
>
<Dropdown
className="components-dropdown-menu edit-post-more-menu"
contentClassName="components-dropdown-menu__popover edit-post-more-menu__content"
position="bottom left"
popoverProps={
Object {
"className": "edit-post-more-menu__content components-dropdown-menu__popover",
"position": "bottom left",
}
}
renderContent={[Function]}
renderToggle={[Function]}
>
Expand Down