From e736ca8bbb90ff19c5355bd832fa8dd1dbfa993e Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 11:40:43 +0200 Subject: [PATCH 01/35] Start using dropdownmenu v2 in block settings dropdown --- .../block-settings-dropdown.js | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index fe3ae0e8bc412a..db0a9e29c4522d 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -6,7 +6,10 @@ import { serialize, store as blocksStore, } from '@wordpress/blocks'; -import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; +import { + Button, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { moreVertical } from '@wordpress/icons'; import { @@ -32,11 +35,14 @@ import __unstableBlockSettingsMenuFirstItem from './block-settings-menu-first-it import BlockSettingsMenuControls from '../block-settings-menu-controls'; import { store as blockEditorStore } from '../../store'; import { useShowMoversGestures } from '../block-toolbar/utils'; +import { unlock } from '../../lock-unlock'; -const POPOVER_PROPS = { - className: 'block-editor-block-settings-menu__popover', - placement: 'bottom-start', -}; +const { + DropdownMenuV2, + DropdownMenuGroupV2, + DropdownMenuItemV2, + DropdownMenuSeparatorV2, +} = unlock( componentsPrivateApis ); function CopyMenuItem( { blocks, onCopy, label } ) { const ref = useCopyToClipboard( () => serialize( blocks ), onCopy ); @@ -51,6 +57,8 @@ export function BlockSettingsDropdown( { __experimentalSelectBlock, children, __unstableDisplayLocation, + toggleProps, + // Investigate which props are usually forwarded to this component ...props } ) { const blockClientIds = Array.isArray( clientIds ) @@ -203,12 +211,18 @@ export function BlockSettingsDropdown( { onMoveTo, blocks, } ) => ( - + } + align="start" + side="bottom" + sideOffset={ 12 } menuProps={ { /** * @param {KeyboardEvent} event @@ -252,6 +266,8 @@ export function BlockSettingsDropdown( { } }, } } + // Missing: onkeydown on the menu + // Missing: pressing esc is not just closing the menu, but also the toolbar? { ...props } > { ( { onClose } ) => ( @@ -378,7 +394,7 @@ export function BlockSettingsDropdown( { ) } ) } - + ) } ); From 6af23dfbbe41cbc42b51cf7d81f282a055cd3676 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 11:42:18 +0200 Subject: [PATCH 02/35] Add Shortcut component --- .../block-settings-dropdown.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index db0a9e29c4522d..c161a74282a483 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -52,6 +52,30 @@ function CopyMenuItem( { blocks, onCopy, label } ) { return { copyMenuItemLabel }; } +const ShortcutItemSuffix = ( { shortcut, className } ) => { + if ( ! shortcut ) { + return null; + } + + let displayText; + let ariaLabel; + + if ( typeof shortcut === 'string' ) { + displayText = shortcut; + } + + if ( shortcut !== null && typeof shortcut === 'object' ) { + displayText = shortcut.display; + ariaLabel = shortcut.ariaLabel; + } + + return ( + + { displayText } + + ); +}; + export function BlockSettingsDropdown( { clientIds, __experimentalSelectBlock, From bb71a235d07bc39c2eeb865f0ef7ad0878dc0efa Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 11:46:41 +0200 Subject: [PATCH 03/35] Refactor block settings dropdown menu items to use dropdownmenu v2 --- .../block-settings-dropdown.js | 247 +++++++++--------- 1 file changed, 129 insertions(+), 118 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index c161a74282a483..dbffc3e239aa24 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -49,7 +49,11 @@ function CopyMenuItem( { blocks, onCopy, label } ) { const copyMenuItemBlocksLabel = blocks.length > 1 ? __( 'Copy blocks' ) : __( 'Copy' ); const copyMenuItemLabel = label ? label : copyMenuItemBlocksLabel; - return { copyMenuItemLabel }; + return ( + + { copyMenuItemLabel } + + ); } const ShortcutItemSuffix = ( { shortcut, className } ) => { @@ -294,128 +298,135 @@ export function BlockSettingsDropdown( { // Missing: pressing esc is not just closing the menu, but also the toolbar? { ...props } > - { ( { onClose } ) => ( - <> - - <__unstableBlockSettingsMenuFirstItem.Slot - fillProps={ { onClose } } - /> - { ! parentBlockIsSelected && - !! firstParentClientId && ( - - } - onClick={ () => - selectBlock( - firstParentClientId - ) - } - > - { sprintf( - /* translators: %s: Name of the block's parent. */ - __( - 'Select parent block (%s)' - ), - parentBlockType.title - ) } - - ) } - { count === 1 && ( - - ) } - - { canDuplicate && ( - - { __( 'Duplicate' ) } - + + <__unstableBlockSettingsMenuFirstItem.Slot + // fillProps={ { onClose } } TODO: onClose missing + /> + { ! parentBlockIsSelected && !! firstParentClientId && ( + + } + onSelect={ () => + selectBlock( firstParentClientId ) + } + > + { sprintf( + /* translators: %s: Name of the block's parent. */ + __( 'Select parent block (%s)' ), + parentBlockType.title ) } - { canInsertDefaultBlock && ( - <> - - { __( 'Add before' ) } - - - { __( 'Add after' ) } - - + + ) } + { count === 1 && ( + + ) } + + { canDuplicate && ( + - { canCopyStyles && ( - - - - { __( 'Paste styles' ) } - - - ) } - + { __( 'Duplicate' ) } + + ) } + { canInsertDefaultBlock && ( + <> + + } + > + { __( 'Add before' ) } + + + } + > + { __( 'Add after' ) } + + + ) } + + + { canCopyStyles && ( + + - { typeof children === 'function' - ? children( { onClose } ) - : Children.map( ( child ) => - cloneElement( child, { onClose } ) - ) } - { canRemove && ( - - - { removeBlockLabel } - - - ) } + + { __( 'Paste styles' ) } + + + ) } + + { typeof children === 'function' + ? children( { + /*onClose*/ + } ) + : Children.map( ( child ) => + cloneElement( child, { + /*onClose*/ + } ) + ) } + { canRemove && ( + <> + + + + } + > + { removeBlockLabel } + + ) } From d80301a5da03aa6253ffda8525edc8d023e50ab6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 11:53:57 +0200 Subject: [PATCH 04/35] Add notes about duplicate implementations/classnames --- .../src/components/block-settings-menu/style.scss | 4 ++++ .../block-library/src/navigation/edit/leaf-more-menu.js | 6 ++++++ .../leaf-more-menu.js | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/packages/block-editor/src/components/block-settings-menu/style.scss b/packages/block-editor/src/components/block-settings-menu/style.scss index bea2242fc59d4e..8dce206a718d2f 100644 --- a/packages/block-editor/src/components/block-settings-menu/style.scss +++ b/packages/block-editor/src/components/block-settings-menu/style.scss @@ -1,3 +1,7 @@ +// TODO: these styles are still probably relevant since they are used by other +// dropdown menus using the same classname. Next steps: +// - consider moving these styles closer to those components +// - consider refactoring those menus too .block-editor-block-settings-menu__popover .components-dropdown-menu__menu { padding: 0; } diff --git a/packages/block-library/src/navigation/edit/leaf-more-menu.js b/packages/block-library/src/navigation/edit/leaf-more-menu.js index 2d35754779ab94..4ae36f12445422 100644 --- a/packages/block-library/src/navigation/edit/leaf-more-menu.js +++ b/packages/block-library/src/navigation/edit/leaf-more-menu.js @@ -14,6 +14,11 @@ import { __, sprintf } from '@wordpress/i18n'; import { BlockTitle, store as blockEditorStore } from '@wordpress/block-editor'; const POPOVER_PROPS = { + // This was using the same class of the block settings dropdown: + // - check if there are no common components that were supposed to be rendered + // in both menus + // - should this dropdown be refactored too? + // - should we restore the deleted styles, otherwise? className: 'block-editor-block-settings-menu__popover', placement: 'bottom-start', }; @@ -117,6 +122,7 @@ export default function LeafMoreMenu( props ) { Date: Mon, 12 Jun 2023 11:57:46 +0200 Subject: [PATCH 05/35] Convert more menu items to use the dropdownmenu v2 components --- .../src/components/block-lock/menu-item.js | 20 ++++++++++++---- .../block-settings-menu-controls/index.js | 23 ++++++++++++------- .../block-convert-button.js | 16 +++++++++++-- .../block-settings-menu/block-mode-toggle.js | 13 +++++++++-- .../convert-to-group-buttons/index.js | 23 +++++++++++-------- 5 files changed, 70 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/block-lock/menu-item.js b/packages/block-editor/src/components/block-lock/menu-item.js index 65607c646e9684..abc556e29ba6f0 100644 --- a/packages/block-editor/src/components/block-lock/menu-item.js +++ b/packages/block-editor/src/components/block-lock/menu-item.js @@ -3,7 +3,10 @@ */ import { __ } from '@wordpress/i18n'; import { useReducer } from '@wordpress/element'; -import { MenuItem } from '@wordpress/components'; +import { + Icon, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { lockOutline, unlock } from '@wordpress/icons'; /** @@ -11,6 +14,9 @@ import { lockOutline, unlock } from '@wordpress/icons'; */ import useBlockLock from './use-block-lock'; import BlockLockModal from './modal'; +import { unlock as unlockPrivateApis } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlockPrivateApis( componentsPrivateApis ); export default function BlockLockMenuItem( { clientId } ) { const { canLock, isLocked } = useBlockLock( clientId ); @@ -28,12 +34,18 @@ export default function BlockLockMenuItem( { clientId } ) { return ( <> - + } onClick={ toggleModal } > { label } - + { isModalOpen && ( ) } diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index ec8fa46d4859d4..dbeda7453ddd78 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -3,9 +3,8 @@ */ import { createSlotFill, - MenuGroup, - MenuItem, __experimentalStyleProvider as StyleProvider, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { pipe } from '@wordpress/compose'; @@ -21,9 +20,14 @@ import { import { BlockLockMenuItem, useBlockLock } from '../block-lock'; import { store as blockEditorStore } from '../../store'; import BlockModeToggle from '../block-settings-menu/block-mode-toggle'; +import { unlock } from '../../lock-unlock'; const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' ); +const { DropdownMenuGroupV2, DropdownMenuItemV2 } = unlock( + componentsPrivateApis +); + const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null, @@ -77,7 +81,9 @@ const BlockSettingsMenuControlsSlot = ( { } return ( - + // TODO: separator? + // TODO: check if this used in other legacy dropdown menus + { showConvertToGroupButton && ( { __( 'Move to' ) } - + ) } { fillProps?.count === 1 && ( ) } - + ); } } diff --git a/packages/block-editor/src/components/block-settings-menu/block-convert-button.js b/packages/block-editor/src/components/block-settings-menu/block-convert-button.js index 130ca47aa47167..5920cd0a6d57bd 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-convert-button.js +++ b/packages/block-editor/src/components/block-settings-menu/block-convert-button.js @@ -2,7 +2,14 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { MenuItem } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); export default function BlockConvertButton( { shouldRender, onClick, small } ) { if ( ! shouldRender ) { @@ -10,5 +17,10 @@ export default function BlockConvertButton( { shouldRender, onClick, small } ) { } const label = __( 'Convert to Blocks' ); - return { ! small && label }; + return ( + /* TODO: check if this used in other legacy dropdown menus */ + + { ! small && label } + + ); } diff --git a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js index 6810a21581f12e..f6e5e374b0e6c8 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js +++ b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { MenuItem } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { getBlockType, hasBlockSupport } from '@wordpress/blocks'; import { withSelect, withDispatch } from '@wordpress/data'; import { compose } from '@wordpress/compose'; @@ -11,6 +11,9 @@ import { compose } from '@wordpress/compose'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); const noop = () => {}; @@ -32,7 +35,13 @@ export function BlockModeToggle( { const label = mode === 'visual' ? __( 'Edit as HTML' ) : __( 'Edit visually' ); - return { ! small && label }; + return ( + // TODO: should prevent default? + // TODO: check if this used in other legacy dropdown menus + + { ! small && label } + + ); } export default compose( [ diff --git a/packages/block-editor/src/components/convert-to-group-buttons/index.js b/packages/block-editor/src/components/convert-to-group-buttons/index.js index c2bb3fb25b8452..64e3919d77e2a9 100644 --- a/packages/block-editor/src/components/convert-to-group-buttons/index.js +++ b/packages/block-editor/src/components/convert-to-group-buttons/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { MenuItem } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { _x } from '@wordpress/i18n'; import { switchToBlockType } from '@wordpress/blocks'; import { useDispatch } from '@wordpress/data'; @@ -12,6 +12,9 @@ import { useDispatch } from '@wordpress/data'; import { store as blockEditorStore } from '../../store'; import useConvertToGroupButtonProps from './use-convert-to-group-button-props'; import BlockGroupToolbar from './toolbar'; +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); function ConvertToGroupButton( { clientIds, @@ -20,7 +23,8 @@ function ConvertToGroupButton( { onUngroup, blocksSelection, groupingBlockName, - onClose = () => {}, + // TODO: onclose + // onClose = () => {}, } ) { const { replaceBlocks } = useDispatch( blockEditorStore ); const onConvertToGroup = () => { @@ -52,30 +56,31 @@ function ConvertToGroupButton( { return null; } + // TODO: check if this used in other legacy dropdown menus return ( <> { isGroupable && ( - { + { onConvertToGroup(); - onClose(); + // onClose(); } } > { _x( 'Group', 'verb' ) } - + ) } { isUngroupable && ( - { onConvertFromGroup(); - onClose(); + // onClose(); } } > { _x( 'Ungroup', 'Ungrouping blocks from within a grouping block back into individual blocks within the Editor ' ) } - + ) } ); From 235a8418d0b7eeb380285f1b56bb8c6f76799868 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 11:58:40 +0200 Subject: [PATCH 06/35] Convert menu items from the reusable-blocks package to use the dropdownmenu v2 components --- packages/private-apis/src/implementation.js | 1 + packages/reusable-blocks/package.json | 1 + .../reusable-block-convert-button.js | 15 ++++++++++----- .../reusable-blocks-manage-button.js | 16 +++++++++++----- packages/reusable-blocks/src/lock-unlock.js | 10 ++++++++++ 5 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 packages/reusable-blocks/src/lock-unlock.js diff --git a/packages/private-apis/src/implementation.js b/packages/private-apis/src/implementation.js index c12b431c4ceefe..e5974672c4e11c 100644 --- a/packages/private-apis/src/implementation.js +++ b/packages/private-apis/src/implementation.js @@ -22,6 +22,7 @@ const CORE_MODULES_USING_PRIVATE_APIS = [ '@wordpress/edit-site', '@wordpress/edit-widgets', '@wordpress/editor', + '@wordpress/reusable-blocks', '@wordpress/router', ]; diff --git a/packages/reusable-blocks/package.json b/packages/reusable-blocks/package.json index 8140ded854efb4..290fffab25f7b3 100644 --- a/packages/reusable-blocks/package.json +++ b/packages/reusable-blocks/package.json @@ -37,6 +37,7 @@ "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", "@wordpress/notices": "file:../notices", + "@wordpress/private-apis": "file:../private-apis", "@wordpress/url": "file:../url" }, "peerDependencies": { diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index 18824b892544a8..beef5f1986c084 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -8,12 +8,13 @@ import { } from '@wordpress/block-editor'; import { useCallback, useState } from '@wordpress/element'; import { - MenuItem, + Icon, Modal, Button, TextControl, __experimentalHStack as HStack, __experimentalVStack as VStack, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { symbol } from '@wordpress/icons'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -25,6 +26,9 @@ import { store as coreStore } from '@wordpress/core-data'; * Internal dependencies */ import { store } from '../../store'; +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); /** * Menu control to convert block(s) to reusable block. @@ -105,18 +109,19 @@ export default function ReusableBlockConvertButton( { return null; } + /* TODO: check if this used in other legacy dropdown menus */ return ( { ( { onClose } ) => ( <> - { + } + onSelect={ () => { setIsModalOpen( true ); } } > { __( 'Create Reusable block' ) } - + { isModalOpen && ( - { __( 'Manage Reusable blocks' ) } - + { canRemove && ( - convertBlockToStatic( clientId ) }> + convertBlockToStatic( clientId ) } + > { innerBlockCount > 1 ? __( 'Convert to regular blocks' ) : __( 'Convert to regular block' ) } - + ) } ); diff --git a/packages/reusable-blocks/src/lock-unlock.js b/packages/reusable-blocks/src/lock-unlock.js new file mode 100644 index 00000000000000..4bffcacba68405 --- /dev/null +++ b/packages/reusable-blocks/src/lock-unlock.js @@ -0,0 +1,10 @@ +/** + * WordPress dependencies + */ +import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/private-apis'; + +export const { lock, unlock } = + __dangerousOptInToUnstableAPIsOnlyForCoreModules( + 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.', + '@wordpress/reusable-blocks' + ); From b933e85d2bb8d22b083a350179167fccb15fe743 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 13:59:30 +0200 Subject: [PATCH 07/35] Add separator to BlockSettingsMenuControls --- .../block-settings-menu-controls/index.js | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index dbeda7453ddd78..5cb797a6604c6e 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -24,9 +24,8 @@ import { unlock } from '../../lock-unlock'; const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' ); -const { DropdownMenuGroupV2, DropdownMenuItemV2 } = unlock( - componentsPrivateApis -); +const { DropdownMenuGroupV2, DropdownMenuItemV2, DropdownMenuSeparatorV2 } = + unlock( componentsPrivateApis ); const BlockSettingsMenuControlsSlot = ( { fillProps, @@ -81,39 +80,42 @@ const BlockSettingsMenuControlsSlot = ( { } return ( - // TODO: separator? - // TODO: check if this used in other legacy dropdown menus - - { showConvertToGroupButton && ( - - ) } - { showLockButton && ( - - ) } - { fills } - { fillProps?.canMove && ! fillProps?.onlyBlock && ( - - { __( 'Move to' ) } - - ) } - { fillProps?.count === 1 && ( - - ) } - + <> + { /* TODO: check if this used in other legacy dropdown + menus */ } + + + { showConvertToGroupButton && ( + + ) } + { showLockButton && ( + + ) } + { fills } + { fillProps?.canMove && ! fillProps?.onlyBlock && ( + + { __( 'Move to' ) } + + ) } + { fillProps?.count === 1 && ( + + ) } + + ); } } From 6f502190c1607b7c50b2dc6048563a7d80dcfb0f Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 14:00:26 +0200 Subject: [PATCH 08/35] Simplify Shortcut suffix component --- .../block-settings-dropdown.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index dbffc3e239aa24..eaa1827ba585b2 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -56,7 +56,7 @@ function CopyMenuItem( { blocks, onCopy, label } ) { ); } -const ShortcutItemSuffix = ( { shortcut, className } ) => { +const Shortcut = ( { shortcut } ) => { if ( ! shortcut ) { return null; } @@ -73,11 +73,7 @@ const ShortcutItemSuffix = ( { shortcut, className } ) => { ariaLabel = shortcut.ariaLabel; } - return ( - - { displayText } - - ); + return { displayText }; }; export function BlockSettingsDropdown( { @@ -335,7 +331,7 @@ export function BlockSettingsDropdown( { updateSelectionAfterDuplicate ) } suffix={ - } @@ -351,7 +347,7 @@ export function BlockSettingsDropdown( { onInsertBefore ) } suffix={ - } @@ -364,7 +360,7 @@ export function BlockSettingsDropdown( { onInsertAfter ) } suffix={ - } @@ -419,7 +415,7 @@ export function BlockSettingsDropdown( { updateSelectionAfterRemove ) } suffix={ - } From d444e01c38d2f8c5ab0176d50170a0a9746bdee5 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 14:42:45 +0200 Subject: [PATCH 09/35] Refactor more menu items rendering inside `BlockSettingsMenuControls` --- .../block-settings-menu-controls/README.md | 6 ++-- .../block-editor/src/hooks/content-lock-ui.js | 23 ++++++++++---- .../src/template-part/edit/index.js | 17 ++++++++--- .../plugin-block-settings-menu-item.js | 30 ++++++++++++++----- .../convert-to-regular.js | 20 +++++++++---- .../convert-to-template-part.js | 18 +++++++---- 6 files changed, 83 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu-controls/README.md b/packages/block-editor/src/components/block-settings-menu-controls/README.md index 4537f4de987a5d..87a7ee5a7df0b2 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/README.md +++ b/packages/block-editor/src/components/block-settings-menu-controls/README.md @@ -6,12 +6,14 @@ Block Settings Menu Controls appear in the block settings dropdown menu when the ```jsx import { BlockSettingsMenuControls } from '@wordress/block-editor'; -import MyButton from './my-toggle-button'; +import MyToggleButton from './my-toggle-button'; function ReusableBlocksMenuItems() { return ( - { ( { onClose } ) => } + {/* Is this a breaking change? */} + {/* Should this use a menu item example? */} + { () => } ); } diff --git a/packages/block-editor/src/hooks/content-lock-ui.js b/packages/block-editor/src/hooks/content-lock-ui.js index c1cf7016bfd443..3e12df05e3ef8f 100644 --- a/packages/block-editor/src/hooks/content-lock-ui.js +++ b/packages/block-editor/src/hooks/content-lock-ui.js @@ -1,7 +1,10 @@ /** * WordPress dependencies */ -import { ToolbarButton, MenuItem } from '@wordpress/components'; +import { + ToolbarButton, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; import { addFilter } from '@wordpress/hooks'; @@ -13,6 +16,9 @@ import { useEffect, useRef, useCallback } from '@wordpress/element'; */ import { store as blockEditorStore } from '../store'; import { BlockControls, BlockSettingsMenuControls } from '../components'; +import { unlock } from '../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); function StopEditingAsBlocksOnOutsideSelect( { clientId, @@ -124,9 +130,14 @@ export const withBlockControls = createHigherOrderComponent( ) } { showStartEditingAsBlocks && ( - { ( { onClose } ) => ( - { + { ( + { + /*onClose*/ + } + ) => ( + /* TODO: check if this used in other legacy dropdown menus */ + { __unstableMarkNextChangeAsNotPersistent(); updateBlockAttributes( props.clientId, { templateLock: undefined, @@ -143,11 +154,11 @@ export const withBlockControls = createHigherOrderComponent( __unstableSetTemporarilyEditingAsBlocks( props.clientId ); - onClose(); + // onClose(); TODO: onClose } } > { __( 'Modify' ) } - + ) } ) } diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index b7ae4f6043afb1..c625eb9960d314 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -11,7 +11,11 @@ import { __experimentalRecursionProvider as RecursionProvider, __experimentalUseHasRecursion as useHasRecursion, } from '@wordpress/block-editor'; -import { Spinner, Modal, MenuItem } from '@wordpress/components'; +import { + Spinner, + Modal, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { __, sprintf } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; import { useState, createInterpolateElement } from '@wordpress/element'; @@ -29,6 +33,9 @@ import { useAlternativeTemplateParts, useTemplatePartArea, } from './utils/hooks'; +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); export default function TemplatePartEdit( { attributes, @@ -157,8 +164,10 @@ export default function TemplatePartEdit( { { canReplace && ( { () => ( - { + /* TODO: check if this used in other legacy dropdown menus */ + { + // TODO: should call preventDefault? setIsTemplatePartSelectionOpen( true ); } } > @@ -173,7 +182,7 @@ export default function TemplatePartEdit( { ), } ) } - + ) } ) } diff --git a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js index f0390267259b66..be9cfa7e4369f8 100644 --- a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js +++ b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js @@ -2,9 +2,19 @@ * WordPress dependencies */ import { BlockSettingsMenuControls } from '@wordpress/block-editor'; -import { MenuItem } from '@wordpress/components'; +import { + Icon, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { compose } from '@wordpress/compose'; +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); + const isEverySelectedBlockAllowed = ( selected, allowed ) => selected.filter( ( id ) => ! allowed.includes( id ) ).length === 0; @@ -87,19 +97,23 @@ const PluginBlockSettingsMenuItem = ( { role, } ) => ( - { ( { selectedBlocks, onClose } ) => { + { ( { selectedBlocks /*onClose*/ } ) => { if ( ! shouldRenderItem( selectedBlocks, allowedBlocks ) ) { return null; } return ( - } + label={ small ? label : undefined } // TODO: should item accept label? It's probably supposed to add an aria-label and potentially even a tooltip + role={ role } // TODO: should item accept role? > { ! small && label } - + ); } } diff --git a/packages/edit-site/src/components/template-part-converter/convert-to-regular.js b/packages/edit-site/src/components/template-part-converter/convert-to-regular.js index b1534ad88a999c..e5ee10d63c0499 100644 --- a/packages/edit-site/src/components/template-part-converter/convert-to-regular.js +++ b/packages/edit-site/src/components/template-part-converter/convert-to-regular.js @@ -3,10 +3,17 @@ */ import { useSelect, useDispatch } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { MenuItem } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -export default function ConvertToRegularBlocks( { clientId, onClose } ) { +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); + +export default function ConvertToRegularBlocks( { clientId /*onClose*/ } ) { const { getBlocks } = useSelect( blockEditorStore ); const { replaceBlocks } = useDispatch( blockEditorStore ); @@ -20,13 +27,14 @@ export default function ConvertToRegularBlocks( { clientId, onClose } ) { } return ( - { + /* TODO: check if this used in other legacy dropdown menus */ + { replaceBlocks( clientId, getBlocks( clientId ) ); - onClose(); + // onClose(); TODO: onClose } } > { __( 'Detach blocks from template part' ) } - + ); } diff --git a/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js b/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js index a671faf756cd40..03634dfe0b6e3f 100644 --- a/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js +++ b/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js @@ -3,7 +3,10 @@ */ import { useDispatch, useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { MenuItem } from '@wordpress/components'; +import { + Icon, + privateApis as componentsPrivateApis, +} from '@wordpress/components'; import { createBlock, serialize } from '@wordpress/blocks'; import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; @@ -21,6 +24,9 @@ import { getUniqueTemplatePartTitle, getCleanTemplatePartSlug, } from '../../utils/template-part-create'; +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); export default function ConvertToTemplatePart( { clientIds, blocks } ) { const [ isModalOpen, setIsModalOpen ] = useState( false ); @@ -75,14 +81,16 @@ export default function ConvertToTemplatePart( { clientIds, blocks } ) { return ( <> - { + { /* TODO: check if this used in other legacy dropdown menus */ } + } + onSelect={ () => { setIsModalOpen( true ); + // TODO: should call prevent default? } } > { __( 'Create Template part' ) } - + { isModalOpen && ( { From 04220d4d11042e6a91823bda891085f3a6c662db Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 18:00:23 +0200 Subject: [PATCH 10/35] Remove onKeyDown menu props (it doesn't seem to be needed?) --- .../block-settings-dropdown.js | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index eaa1827ba585b2..612c682706d56d 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -247,50 +247,6 @@ export function BlockSettingsDropdown( { align="start" side="bottom" sideOffset={ 12 } - menuProps={ { - /** - * @param {KeyboardEvent} event - */ - onKeyDown( event ) { - if ( event.defaultPrevented ) return; - - if ( - isMatch( 'core/block-editor/remove', event ) && - canRemove - ) { - event.preventDefault(); - updateSelectionAfterRemove( onRemove() ); - } else if ( - isMatch( - 'core/block-editor/duplicate', - event - ) && - canDuplicate - ) { - event.preventDefault(); - updateSelectionAfterDuplicate( onDuplicate() ); - } else if ( - isMatch( - 'core/block-editor/insert-after', - event - ) && - canInsertDefaultBlock - ) { - event.preventDefault(); - onInsertAfter(); - } else if ( - isMatch( - 'core/block-editor/insert-before', - event - ) && - canInsertDefaultBlock - ) { - event.preventDefault(); - onInsertBefore(); - } - }, - } } - // Missing: onkeydown on the menu // Missing: pressing esc is not just closing the menu, but also the toolbar? { ...props } > From 44a5cf3f6d672f7775fee8a6498f6d3fa7e61ac6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 12 Jun 2023 18:48:13 +0200 Subject: [PATCH 11/35] Migrate from calling onClose to calling preventDefault() when needing to keep the dropdown open --- .../src/components/block-lock/menu-item.js | 6 +- .../block-settings-menu-controls/index.js | 8 +-- .../block-settings-menu/block-mode-toggle.js | 2 +- .../block-settings-dropdown.js | 55 +++++++------------ .../convert-to-group-buttons/index.js | 3 - .../block-editor/src/hooks/content-lock-ui.js | 7 +-- .../src/template-part/edit/index.js | 5 +- .../block-inspector-button/index.js | 20 ++++--- .../components/sidebar-block-editor/index.js | 7 +-- .../plugin-block-settings-menu-item.js | 5 +- .../visual-editor/block-inspector-button.js | 1 + .../block-editor/block-inspector-button.js | 1 + .../convert-to-regular.js | 3 +- .../convert-to-template-part.js | 5 +- .../template-part-converter/index.js | 12 +--- .../reusable-block-convert-button.js | 13 ++++- 16 files changed, 66 insertions(+), 87 deletions(-) diff --git a/packages/block-editor/src/components/block-lock/menu-item.js b/packages/block-editor/src/components/block-lock/menu-item.js index abc556e29ba6f0..0bce6486fb1c21 100644 --- a/packages/block-editor/src/components/block-lock/menu-item.js +++ b/packages/block-editor/src/components/block-lock/menu-item.js @@ -42,7 +42,11 @@ export default function BlockLockMenuItem( { clientId } ) { size={ 24 } /> } - onClick={ toggleModal } + onSelect={ ( event ) => { + toggleModal(); + // Keep the dropdown menu open + event.preventDefault(); + } } > { label } diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 5cb797a6604c6e..cbe2264ede428f 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -88,7 +88,6 @@ const BlockSettingsMenuControlsSlot = ( { { showConvertToGroupButton && ( ) } { showLockButton && ( @@ -99,11 +98,7 @@ const BlockSettingsMenuControlsSlot = ( { { fills } { fillProps?.canMove && ! fillProps?.onlyBlock && ( { __( 'Move to' ) } @@ -111,7 +106,6 @@ const BlockSettingsMenuControlsSlot = ( { { fillProps?.count === 1 && ( ) } diff --git a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js index f6e5e374b0e6c8..c438559f359442 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js +++ b/packages/block-editor/src/components/block-settings-menu/block-mode-toggle.js @@ -36,9 +36,9 @@ export function BlockModeToggle( { mode === 'visual' ? __( 'Edit as HTML' ) : __( 'Edit visually' ); return ( - // TODO: should prevent default? // TODO: check if this used in other legacy dropdown menus + { /* TODO: what if `small` is true? What contents are displayed? */ } { ! small && label } ); diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 612c682706d56d..46a06d54ced661 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -12,16 +12,11 @@ import { } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { moreVertical } from '@wordpress/icons'; -import { - Children, - cloneElement, - useCallback, - useRef, -} from '@wordpress/element'; +import { useCallback, useRef } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as keyboardShortcutsStore, - __unstableUseShortcutEventMatch, + // __unstableUseShortcutEventMatch, } from '@wordpress/keyboard-shortcuts'; import { pipe, useCopyToClipboard } from '@wordpress/compose'; @@ -50,7 +45,13 @@ function CopyMenuItem( { blocks, onCopy, label } ) { blocks.length > 1 ? __( 'Copy blocks' ) : __( 'Copy' ); const copyMenuItemLabel = label ? label : copyMenuItemBlocksLabel; return ( - + { + // Keep the dropdown menu open. + event.preventDefault(); + } } + > { copyMenuItemLabel } ); @@ -152,7 +153,7 @@ export function BlockSettingsDropdown( { ), }; }, [] ); - const isMatch = __unstableUseShortcutEventMatch(); + // const isMatch = __unstableUseShortcutEventMatch(); const { selectBlock, toggleBlockHighlight } = useDispatch( blockEditorStore ); @@ -251,12 +252,9 @@ export function BlockSettingsDropdown( { { ...props } > - <__unstableBlockSettingsMenuFirstItem.Slot - // fillProps={ { onClose } } TODO: onClose missing - /> + <__unstableBlockSettingsMenuFirstItem.Slot /> { ! parentBlockIsSelected && !! firstParentClientId && ( - + { + onPasteStyles(); + // Keep the dropdown menu open. + event.preventDefault(); + } } + > { __( 'Paste styles' ) } ) } - { typeof children === 'function' - ? children( { - /*onClose*/ - } ) - : Children.map( ( child ) => - cloneElement( child, { - /*onClose*/ - } ) - ) } + { typeof children === 'function' ? children() : children } { canRemove && ( <> {}, } ) { const { replaceBlocks } = useDispatch( blockEditorStore ); const onConvertToGroup = () => { @@ -63,7 +61,6 @@ function ConvertToGroupButton( { { onConvertToGroup(); - // onClose(); } } > { _x( 'Group', 'verb' ) } diff --git a/packages/block-editor/src/hooks/content-lock-ui.js b/packages/block-editor/src/hooks/content-lock-ui.js index 3e12df05e3ef8f..223065da949e45 100644 --- a/packages/block-editor/src/hooks/content-lock-ui.js +++ b/packages/block-editor/src/hooks/content-lock-ui.js @@ -130,11 +130,7 @@ export const withBlockControls = createHigherOrderComponent( ) } { showStartEditingAsBlocks && ( - { ( - { - /*onClose*/ - } - ) => ( + { () => ( /* TODO: check if this used in other legacy dropdown menus */ { @@ -154,7 +150,6 @@ export const withBlockControls = createHigherOrderComponent( __unstableSetTemporarilyEditingAsBlocks( props.clientId ); - // onClose(); TODO: onClose } } > { __( 'Modify' ) } diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index c625eb9960d314..c256f2c67fcdbe 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -166,9 +166,10 @@ export default function TemplatePartEdit( { { () => ( /* TODO: check if this used in other legacy dropdown menus */ { - // TODO: should call preventDefault? + onSelect={ ( event ) => { setIsTemplatePartSelectionOpen( true ); + // Keep the dropdown menu open + event.preventDefault(); } } > { createInterpolateElement( diff --git a/packages/customize-widgets/src/components/block-inspector-button/index.js b/packages/customize-widgets/src/components/block-inspector-button/index.js index c68c2f46c7468c..3ebfa7113ea646 100644 --- a/packages/customize-widgets/src/components/block-inspector-button/index.js +++ b/packages/customize-widgets/src/components/block-inspector-button/index.js @@ -3,11 +3,18 @@ */ import { useMemo } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { MenuItem } from '@wordpress/components'; +import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -function BlockInspectorButton( { inspector, closeMenu, ...props } ) { +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); + +function BlockInspectorButton( { inspector, ...props } ) { const selectedBlockClientId = useSelect( ( select ) => select( blockEditorStore ).getSelectedBlockClientId(), [] @@ -19,19 +26,18 @@ function BlockInspectorButton( { inspector, closeMenu, ...props } ) { ); return ( - { + /* TODO: check if this used in other legacy dropdown menus */ + { // Open the inspector. inspector.open( { returnFocusWhenClose: selectedBlock, } ); - // Then close the dropdown menu. - closeMenu(); } } { ...props } > { __( 'Show more settings' ) } - + ); } diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 6a5a734bef9db1..e4015ae279a70d 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -139,12 +139,7 @@ export default function SidebarBlockEditor( { <__unstableBlockSettingsMenuFirstItem> - { ( { onClose } ) => ( - - ) } + ); diff --git a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js index be9cfa7e4369f8..382344af595867 100644 --- a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js +++ b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js @@ -104,10 +104,7 @@ const PluginBlockSettingsMenuItem = ( { return ( /* TODO: check if this used in other legacy dropdown menus */ } label={ small ? label : undefined } // TODO: should item accept label? It's probably supposed to add an aria-label and potentially even a tooltip role={ role } // TODO: should item accept role? diff --git a/packages/edit-post/src/components/visual-editor/block-inspector-button.js b/packages/edit-post/src/components/visual-editor/block-inspector-button.js index 271580b7ea7cad..b0f2796be8dfcf 100644 --- a/packages/edit-post/src/components/visual-editor/block-inspector-button.js +++ b/packages/edit-post/src/components/visual-editor/block-inspector-button.js @@ -34,6 +34,7 @@ export function BlockInspectorButton( { onClick = noop, small = false } ) { : __( 'Show more settings' ); return ( + // Is this dead code? { if ( areAdvancedSettingsOpened ) { diff --git a/packages/edit-site/src/components/block-editor/block-inspector-button.js b/packages/edit-site/src/components/block-editor/block-inspector-button.js index 758ca50272adeb..c17489073312fe 100644 --- a/packages/edit-site/src/components/block-editor/block-inspector-button.js +++ b/packages/edit-site/src/components/block-editor/block-inspector-button.js @@ -15,6 +15,7 @@ import { store as editSiteStore } from '../../store'; import { STORE_NAME } from '../../store/constants'; import { SIDEBAR_BLOCK } from '../sidebar-edit-mode/constants'; +// Is this dead code? export default function BlockInspectorButton( { onClick = () => {} } ) { const { shortcut, isBlockInspectorOpen } = useSelect( ( select ) => ( { diff --git a/packages/edit-site/src/components/template-part-converter/convert-to-regular.js b/packages/edit-site/src/components/template-part-converter/convert-to-regular.js index e5ee10d63c0499..51393c405dbed2 100644 --- a/packages/edit-site/src/components/template-part-converter/convert-to-regular.js +++ b/packages/edit-site/src/components/template-part-converter/convert-to-regular.js @@ -13,7 +13,7 @@ import { unlock } from '../../lock-unlock'; const { DropdownMenuItemV2 } = unlock( componentsPrivateApis ); -export default function ConvertToRegularBlocks( { clientId /*onClose*/ } ) { +export default function ConvertToRegularBlocks( { clientId } ) { const { getBlocks } = useSelect( blockEditorStore ); const { replaceBlocks } = useDispatch( blockEditorStore ); @@ -31,7 +31,6 @@ export default function ConvertToRegularBlocks( { clientId /*onClose*/ } ) { { replaceBlocks( clientId, getBlocks( clientId ) ); - // onClose(); TODO: onClose } } > { __( 'Detach blocks from template part' ) } diff --git a/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js b/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js index 03634dfe0b6e3f..aa642cec72e467 100644 --- a/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js +++ b/packages/edit-site/src/components/template-part-converter/convert-to-template-part.js @@ -84,9 +84,10 @@ export default function ConvertToTemplatePart( { clientIds, blocks } ) { { /* TODO: check if this used in other legacy dropdown menus */ } } - onSelect={ () => { + onSelect={ ( event ) => { setIsModalOpen( true ); - // TODO: should call prevent default? + // Keep the dropdown menu open + event.preventDefault(); } } > { __( 'Create Template part' ) } diff --git a/packages/edit-site/src/components/template-part-converter/index.js b/packages/edit-site/src/components/template-part-converter/index.js index 7694735cbb3025..e5ec47a62c3533 100644 --- a/packages/edit-site/src/components/template-part-converter/index.js +++ b/packages/edit-site/src/components/template-part-converter/index.js @@ -16,17 +16,16 @@ import ConvertToTemplatePart from './convert-to-template-part'; export default function TemplatePartConverter() { return ( - { ( { selectedClientIds, onClose } ) => ( + { ( { selectedClientIds } ) => ( ) } ); } -function TemplatePartConverterMenuItem( { clientIds, onClose } ) { +function TemplatePartConverterMenuItem( { clientIds } ) { const blocks = useSelect( ( select ) => select( blockEditorStore ).getBlocksByClientId( clientIds ), @@ -35,12 +34,7 @@ function TemplatePartConverterMenuItem( { clientIds, onClose } ) { // Allow converting a single template part to standard blocks. if ( blocks.length === 1 && blocks[ 0 ]?.name === 'core/template-part' ) { - return ( - - ); + return ; } return ; } diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index beef5f1986c084..ac18319fe0c4d6 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -112,12 +112,14 @@ export default function ReusableBlockConvertButton( { /* TODO: check if this used in other legacy dropdown menus */ return ( - { ( { onClose } ) => ( + { () => ( <> } - onSelect={ () => { + onSelect={ ( event ) => { setIsModalOpen( true ); + // Keep the dropdown menu open + event.preventDefault(); } } > { __( 'Create Reusable block' ) } @@ -137,7 +139,12 @@ export default function ReusableBlockConvertButton( { onConvert( title ); setIsModalOpen( false ); setTitle( '' ); - onClose(); + // TODO: the modal is expected to close the dropdown! + // - can we keep it open? + // - can we close the dropdown when the modal is opened instead? + // - otherwise, how do we go about it? We'd need to switch to + // controlled mode at the root, and pass `onClose` around + // onClose(); } } > From dc78e0de36fff422933689032627794772910836 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 11:23:08 +0200 Subject: [PATCH 12/35] Fix broken copy/paste by using native clipboard APIs instead of external library --- .../block-settings-dropdown.js | 103 +++++++++++++++--- 1 file changed, 89 insertions(+), 14 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 46a06d54ced661..74fd86cc2f70f4 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -12,13 +12,13 @@ import { } from '@wordpress/components'; import { useDispatch, useSelect } from '@wordpress/data'; import { moreVertical } from '@wordpress/icons'; -import { useCallback, useRef } from '@wordpress/element'; +import { useCallback, useRef, useEffect, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as keyboardShortcutsStore, // __unstableUseShortcutEventMatch, } from '@wordpress/keyboard-shortcuts'; -import { pipe, useCopyToClipboard } from '@wordpress/compose'; +import { pipe } from '@wordpress/compose'; /** * Internal dependencies @@ -39,15 +39,73 @@ const { DropdownMenuSeparatorV2, } = unlock( componentsPrivateApis ); +const clipboardPermissionCache = { + read: undefined, + write: undefined, +}; + +async function hasClipboardPermission( type ) { + if ( type !== 'write' && type !== 'read' ) { + return false; + } + if ( clipboardPermissionCache[ type ] !== undefined ) { + return clipboardPermissionCache[ type ]; + } + + let hasSupport = false; + try { + const result = await window.navigator.permissions.query( { + name: `clipboard-${ type }`, + } ); + hasSupport = result.state === 'granted' || result.state === 'prompt'; + } catch ( error ) { + // Possibly the permission is denied. + // TODO: show an error notice + } + + clipboardPermissionCache[ type ] = hasSupport; + return hasSupport; +} + +async function writeToClipboard( { text, onSuccess } ) { + try { + // Only available on sites using `https` (and localhost) + if ( ! window.navigator.clipboard ) { + // TODO: show an error notice + return; + } + + await window.navigator.clipboard.writeText( text ); + onSuccess?.(); + } catch ( error ) { + // Possibly the permission is denied. + // TODO: show an error notice + } +} + function CopyMenuItem( { blocks, onCopy, label } ) { - const ref = useCopyToClipboard( () => serialize( blocks ), onCopy ); + const [ supportsClipboard, setSupportsClipboard ] = useState( false ); const copyMenuItemBlocksLabel = blocks.length > 1 ? __( 'Copy blocks' ) : __( 'Copy' ); const copyMenuItemLabel = label ? label : copyMenuItemBlocksLabel; + + useEffect( () => { + async function testSupport() { + const hasPermission = await hasClipboardPermission( 'write' ); + setSupportsClipboard( hasPermission ); + } + + testSupport(); + }, [] ); + return ( { + disabled={ ! supportsClipboard } + onSelect={ async ( event ) => { + await writeToClipboard( { + text: serialize( blocks ), + onSuccess: onCopy, + } ); // Keep the dropdown menu open. event.preventDefault(); } } @@ -57,6 +115,31 @@ function CopyMenuItem( { blocks, onCopy, label } ) { ); } +function PasteStylesMenuItem( { onSelect } ) { + const [ supportsClipboard, setSupportsClipboard ] = useState( false ); + useEffect( () => { + async function testSupport() { + const hasPermission = await hasClipboardPermission( 'read' ); + setSupportsClipboard( hasPermission ); + } + + testSupport(); + }, [] ); + + return ( + { + onSelect?.(); + // Keep the dropdown menu open. + event.preventDefault(); + } } + > + { __( 'Paste styles' ) } + + ); +} + const Shortcut = ( { shortcut } ) => { if ( ! shortcut ) { return null; @@ -325,15 +408,7 @@ export function BlockSettingsDropdown( { onCopy={ onCopy } label={ __( 'Copy styles' ) } /> - { - onPasteStyles(); - // Keep the dropdown menu open. - event.preventDefault(); - } } - > - { __( 'Paste styles' ) } - + ) } Date: Tue, 13 Jun 2023 11:52:26 +0200 Subject: [PATCH 13/35] Remove unnecessary wrapper functions, unused imports, clean up code, onClick => onSelect --- .../block-settings-menu-controls/README.md | 2 +- .../block-settings-menu-controls/index.js | 1 - .../block-settings-dropdown.js | 2 +- .../block-editor/src/hooks/content-lock-ui.js | 46 ++++---- .../src/template-part/edit/index.js | 42 ++++--- .../plugin-block-settings-menu-item.js | 3 +- .../reusable-block-convert-button.js | 110 +++++++++--------- 7 files changed, 98 insertions(+), 108 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu-controls/README.md b/packages/block-editor/src/components/block-settings-menu-controls/README.md index 87a7ee5a7df0b2..cb489120a7e47f 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/README.md +++ b/packages/block-editor/src/components/block-settings-menu-controls/README.md @@ -13,7 +13,7 @@ function ReusableBlocksMenuItems() { {/* Is this a breaking change? */} {/* Should this use a menu item example? */} - { () => } + ); } diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index cbe2264ede428f..46a7fbb9b5c238 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -7,7 +7,6 @@ import { privateApis as componentsPrivateApis, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; -import { pipe } from '@wordpress/compose'; import { __ } from '@wordpress/i18n'; /** diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 74fd86cc2f70f4..193d9e18e0caf6 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -428,7 +428,7 @@ export function BlockSettingsDropdown( { - { () => ( - /* TODO: check if this used in other legacy dropdown menus */ - { - __unstableMarkNextChangeAsNotPersistent(); - updateBlockAttributes( props.clientId, { - templateLock: undefined, - } ); - updateBlockListSettings( props.clientId, { - ...getBlockListSettings( - props.clientId - ), - templateLock: false, - } ); - focusModeToRevert.current = - getSettings().focusMode; - updateSettings( { focusMode: true } ); - __unstableSetTemporarilyEditingAsBlocks( - props.clientId - ); - } } - > - { __( 'Modify' ) } - - ) } + { /* TODO: check if this used in other legacy dropdown menus */ } + { + __unstableMarkNextChangeAsNotPersistent(); + updateBlockAttributes( props.clientId, { + templateLock: undefined, + } ); + updateBlockListSettings( props.clientId, { + ...getBlockListSettings( props.clientId ), + templateLock: false, + } ); + focusModeToRevert.current = + getSettings().focusMode; + updateSettings( { focusMode: true } ); + __unstableSetTemporarilyEditingAsBlocks( + props.clientId + ); + } } + > + { __( 'Modify' ) } + ) } diff --git a/packages/block-library/src/template-part/edit/index.js b/packages/block-library/src/template-part/edit/index.js index c256f2c67fcdbe..b2a4ed546d0ed4 100644 --- a/packages/block-library/src/template-part/edit/index.js +++ b/packages/block-library/src/template-part/edit/index.js @@ -163,28 +163,26 @@ export default function TemplatePartEdit( { ) } { canReplace && ( - { () => ( - /* TODO: check if this used in other legacy dropdown menus */ - { - setIsTemplatePartSelectionOpen( true ); - // Keep the dropdown menu open - event.preventDefault(); - } } - > - { createInterpolateElement( - __( 'Replace ' ), - { - BlockTitle: ( - - ), - } - ) } - - ) } + { /* TODO: check if this used in other legacy dropdown menus */ } + { + setIsTemplatePartSelectionOpen( true ); + // Keep the dropdown menu open + event.preventDefault(); + } } + > + { createInterpolateElement( + __( 'Replace ' ), + { + BlockTitle: ( + + ), + } + ) } + ) } { isEntityAvailable && ( diff --git a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js index 382344af595867..edfcf34ae51988 100644 --- a/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js +++ b/packages/edit-post/src/components/block-settings-menu/plugin-block-settings-menu-item.js @@ -6,7 +6,6 @@ import { Icon, privateApis as componentsPrivateApis, } from '@wordpress/components'; -import { compose } from '@wordpress/compose'; /** * Internal dependencies @@ -97,7 +96,7 @@ const PluginBlockSettingsMenuItem = ( { role, } ) => ( - { ( { selectedBlocks /*onClose*/ } ) => { + { ( { selectedBlocks } ) => { if ( ! shouldRenderItem( selectedBlocks, allowedBlocks ) ) { return null; } diff --git a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js index ac18319fe0c4d6..a7a23dcb1f36c3 100644 --- a/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js +++ b/packages/reusable-blocks/src/components/reusable-blocks-menu-items/reusable-block-convert-button.js @@ -112,69 +112,67 @@ export default function ReusableBlockConvertButton( { /* TODO: check if this used in other legacy dropdown menus */ return ( - { () => ( - <> - } - onSelect={ ( event ) => { - setIsModalOpen( true ); - // Keep the dropdown menu open - event.preventDefault(); + <> + } + onSelect={ ( event ) => { + setIsModalOpen( true ); + // Keep the dropdown menu open + event.preventDefault(); + } } + > + { __( 'Create Reusable block' ) } + + { isModalOpen && ( + { + setIsModalOpen( false ); + setTitle( '' ); } } + overlayClassName="reusable-blocks-menu-items__convert-modal" > - { __( 'Create Reusable block' ) } - - { isModalOpen && ( - { +
{ + event.preventDefault(); + onConvert( title ); setIsModalOpen( false ); setTitle( '' ); + // TODO: the modal is expected to close the dropdown! + // - can we keep it open? + // - can we close the dropdown when the modal is opened instead? + // - otherwise, how do we go about it? We'd need to switch to + // controlled mode at the root, and pass `onClose` around + // onClose(); } } - overlayClassName="reusable-blocks-menu-items__convert-modal" > - { - event.preventDefault(); - onConvert( title ); - setIsModalOpen( false ); - setTitle( '' ); - // TODO: the modal is expected to close the dropdown! - // - can we keep it open? - // - can we close the dropdown when the modal is opened instead? - // - otherwise, how do we go about it? We'd need to switch to - // controlled mode at the root, and pass `onClose` around - // onClose(); - } } - > - - - - + + + + - - - - -
- ) } - - ) } + + + + + + ) } +
); } From d642c706a626393131417dfdf4016c15fb8e9cc3 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 12:26:26 +0200 Subject: [PATCH 14/35] Add default z-index --- packages/components/src/dropdown-menu-v2/styles.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index eb1aec2d8a2d72..77a86c4babed36 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -75,6 +75,8 @@ const baseContent = ( animation-duration: ${ ANIMATION_PARAMS.DURATION }; animation-timing-function: ${ ANIMATION_PARAMS.EASING }; will-change: transform, opacity; + /* Following z-index('.components-popover'), as per base styles */ + z-index: 1000000; &[data-side='top'] { animation-name: ${ slideDownAndFade }; From e0075d56eb55099a567da5464d55b949193d4439 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 12:33:18 +0200 Subject: [PATCH 15/35] Capture pointer events in modals --- packages/components/src/modal/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index acc43de8b7f902..13446f2b4ae320 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -8,6 +8,7 @@ background-color: rgba($black, 0.35); z-index: z-index(".components-modal__screen-overlay"); display: flex; + pointer-events: all; // backdrop-filter: blur($grid-unit); // This animates the appearance of the white background. @include edit-post__fade-in-animation(); From 4a7a0ac8ff75828c26eb6b39510f898171945dca Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 13:49:34 +0200 Subject: [PATCH 16/35] DropdownMenuV2: accept onKeyDown prop --- packages/components/src/dropdown-menu-v2/index.tsx | 3 +++ packages/components/src/dropdown-menu-v2/types.ts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index 02f8322aa6a52f..324ec45009e4ad 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -62,6 +62,8 @@ const UnconnectedDropdownMenu = ( props: DropdownMenuProps ) => { sideOffset = 0, align = 'center', alignOffset = 0, + // Other content props + onKeyDown, // Render props children, trigger, @@ -104,6 +106,7 @@ const UnconnectedDropdownMenu = ( props: DropdownMenuProps ) => { alignOffset={ alignOffset } loop={ true } variant={ variant } + onKeyDown={ onKeyDown } > ; export type DropdownSubMenuTriggerProps = { /** From 40fd83037f6ae03ee82c3dd4a7271877d8556414 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 13:50:05 +0200 Subject: [PATCH 17/35] Restore onKeyDown ev listener on the block settings dropdown --- .../block-settings-dropdown.js | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 193d9e18e0caf6..2d730c5163c5a5 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -16,7 +16,7 @@ import { useCallback, useRef, useEffect, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as keyboardShortcutsStore, - // __unstableUseShortcutEventMatch, + __unstableUseShortcutEventMatch, } from '@wordpress/keyboard-shortcuts'; import { pipe } from '@wordpress/compose'; @@ -236,7 +236,7 @@ export function BlockSettingsDropdown( { ), }; }, [] ); - // const isMatch = __unstableUseShortcutEventMatch(); + const isMatch = __unstableUseShortcutEventMatch(); const { selectBlock, toggleBlockHighlight } = useDispatch( blockEditorStore ); @@ -331,6 +331,41 @@ export function BlockSettingsDropdown( { align="start" side="bottom" sideOffset={ 12 } + onKeyDown={ ( event ) => { + if ( event.defaultPrevented ) return; + + if ( + isMatch( 'core/block-editor/remove', event ) && + canRemove + ) { + event.preventDefault(); + updateSelectionAfterRemove( onRemove() ); + } else if ( + isMatch( 'core/block-editor/duplicate', event ) && + canDuplicate + ) { + event.preventDefault(); + updateSelectionAfterDuplicate( onDuplicate() ); + } else if ( + isMatch( + 'core/block-editor/insert-after', + event + ) && + canInsertDefaultBlock + ) { + event.preventDefault(); + onInsertAfter(); + } else if ( + isMatch( + 'core/block-editor/insert-before', + event + ) && + canInsertDefaultBlock + ) { + event.preventDefault(); + onInsertBefore(); + } + } } // Missing: pressing esc is not just closing the menu, but also the toolbar? { ...props } > From a27962e9cad439b81fdb8e9e0a03a3afbe49dafa Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 13:54:44 +0200 Subject: [PATCH 18/35] Add a few pointer-related props to DropdownMenuItemProps --- packages/components/src/dropdown-menu-v2/types.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/components/src/dropdown-menu-v2/types.ts b/packages/components/src/dropdown-menu-v2/types.ts index 5f9540dfb998a1..3e6458ef44d680 100644 --- a/packages/components/src/dropdown-menu-v2/types.ts +++ b/packages/components/src/dropdown-menu-v2/types.ts @@ -147,7 +147,10 @@ export type DropdownMenuItemProps = { * The contents of the item's suffix */ suffix?: React.ReactNode; -}; +} & Pick< + DropdownMenuPrimitive.DropdownMenuItemProps, + 'onClick' | 'onMouseEnter' | 'onMouseMove' | 'onMouseLeave' +>; export type DropdownMenuCheckboxItemProps = { /** From e5a7b1205a35764332e611a57b9115bc05e95966 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Tue, 13 Jun 2023 15:22:36 +0200 Subject: [PATCH 19/35] Destructure and properly allocate more props in Block settings menu --- .../block-settings-dropdown.js | 23 ++++++++++++++++--- .../src/components/list-view/block.js | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 2d730c5163c5a5..0fd8d9e2bd7e47 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -166,7 +166,15 @@ export function BlockSettingsDropdown( { children, __unstableDisplayLocation, toggleProps, - // Investigate which props are usually forwarded to this component + label, + icon, + disableOpenOnArrowDown, + // Unused (avoid forwarding with rest props) + block, + expand, + expandedState, + setInsertedBlock, + // Rest props ...props } ) { const blockClientIds = Array.isArray( clientIds ) @@ -323,9 +331,18 @@ export function BlockSettingsDropdown( { trigger={ + { + event.preventDefault(); + onConvert( title ); + setIsModalOpen( false ); + setTitle( '' ); + // The dropdown seems to close automatically due to the old + // regular block being replaced by the new block, although + // I've kept this line around for now. + onClose(); + } } + > + + + + - - - - - - ) } - + + + + + + ) } + + ) }
); } From 0425a8100a9270bd7394b9bca30b1442fdc8f1eb Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 14 Jun 2023 12:21:04 +0200 Subject: [PATCH 24/35] Support rendering anchor tags in DropdownMenuItem --- .../components/src/dropdown-menu-v2/index.tsx | 27 ++++++++++--------- .../components/src/dropdown-menu-v2/styles.ts | 8 ++++++ .../components/src/dropdown-menu-v2/types.ts | 15 +++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/components/src/dropdown-menu-v2/index.tsx b/packages/components/src/dropdown-menu-v2/index.tsx index 324ec45009e4ad..eda429d4f51b27 100644 --- a/packages/components/src/dropdown-menu-v2/index.tsx +++ b/packages/components/src/dropdown-menu-v2/index.tsx @@ -210,19 +210,22 @@ export const DropdownMenuItem = forwardRef( { children, prefix, suffix, ...props }: DropdownMenuItemProps, forwardedRef: React.ForwardedRef< any > ) => { + const Component = props.href ? 'a' : 'div'; return ( - - { prefix && ( - - { prefix } - - ) } - { children } - { suffix && ( - - { suffix } - - ) } + + + { prefix && ( + + { prefix } + + ) } + { children } + { suffix && ( + + { suffix } + + ) } + ); } diff --git a/packages/components/src/dropdown-menu-v2/styles.ts b/packages/components/src/dropdown-menu-v2/styles.ts index ba1e15a21db55d..4920b58b74bc29 100644 --- a/packages/components/src/dropdown-menu-v2/styles.ts +++ b/packages/components/src/dropdown-menu-v2/styles.ts @@ -176,6 +176,14 @@ const baseItem = css` outline: none; cursor: pointer; + /* Undo existing base focus/hover/active styles */ + &:focus, + &:hover, + &:active { + color: ${ COLORS.gray[ 900 ] }; + box-shadow: none; + } + &[data-disabled] { /* TODO: diff --git a/packages/components/src/dropdown-menu-v2/types.ts b/packages/components/src/dropdown-menu-v2/types.ts index 3e6458ef44d680..c4757377f42aa0 100644 --- a/packages/components/src/dropdown-menu-v2/types.ts +++ b/packages/components/src/dropdown-menu-v2/types.ts @@ -147,6 +147,21 @@ export type DropdownMenuItemProps = { * The contents of the item's suffix */ suffix?: React.ReactNode; + /** + * If specified, the menu item will render as an anchor tag and allow + * navigation to the provided URL. + */ + href?: HTMLAnchorElement[ 'href' ]; + /** + * Equivalent to the `rel` attribute for an HTML Anchor Tag. It should + * be only specified when passing a non-empty `href` prop. + */ + rel?: HTMLAnchorElement[ 'rel' ]; + /** + * Equivalent to the `target` attribute for an HTML Anchor Tag. It should + * be only specified when passing a non-empty `href` prop. + */ + target?: HTMLAnchorElement[ 'target' ]; } & Pick< DropdownMenuPrimitive.DropdownMenuItemProps, 'onClick' | 'onMouseEnter' | 'onMouseMove' | 'onMouseLeave' From e51fdcf999cd6164d65198e33f15406ccdb69f4f Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 14 Jun 2023 12:21:43 +0200 Subject: [PATCH 25/35] Remove done comment --- .../components/block-settings-menu/block-settings-dropdown.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index 707a6791eb2cc8..a4d42d7e435685 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -407,7 +407,6 @@ export function BlockSettingsDropdown( { onInsertBefore(); } } } - // Missing: pressing esc is not just closing the menu, but also the toolbar? { ...props } > From 7823fc2e256dac1906e49320c94e4b5d36a36030 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 14 Jun 2023 15:08:02 +0200 Subject: [PATCH 26/35] Avoid unnecessary function --- .../components/block-settings-menu/block-settings-dropdown.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js index a4d42d7e435685..498c5d509e511e 100644 --- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js +++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js @@ -340,9 +340,7 @@ export function BlockSettingsDropdown( { } ) => ( { - setIsDropdownOpen( open ); - } } + onOpenChange={ setIsDropdownOpen } trigger={