diff --git a/docs/getting-started/faq.md b/docs/getting-started/faq.md
index 57a379a9fafe1..2bc7fc8f0bf8b 100644
--- a/docs/getting-started/faq.md
+++ b/docs/getting-started/faq.md
@@ -224,6 +224,11 @@ This is the canonical list of keyboard shortcuts:
/ |
/ |
+
+ Create a group block from the selected multiple blocks. |
+ Ctrl+G |
+ ⌘⇧G |
+
Remove multiple selected blocks. |
delbackspace |
diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js
index 3606a8f757cfd..dba0adbbd8325 100644
--- a/packages/block-editor/src/components/block-tools/index.js
+++ b/packages/block-editor/src/components/block-tools/index.js
@@ -6,6 +6,9 @@ import { isTextField } from '@wordpress/dom';
import { Popover } from '@wordpress/components';
import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
+import { switchToBlockType, store as blocksStore } from '@wordpress/blocks';
+import { speak } from '@wordpress/a11y';
+import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
@@ -64,9 +67,13 @@ export default function BlockTools( {
[]
);
const isMatch = useShortcutEventMatch();
- const { getSelectedBlockClientIds, getBlockRootClientId } =
- useSelect( blockEditorStore );
-
+ const {
+ getBlocksByClientId,
+ getSelectedBlockClientIds,
+ getBlockRootClientId,
+ isGroupable,
+ } = useSelect( blockEditorStore );
+ const { getGroupingBlockName } = useSelect( blocksStore );
const {
showEmptyBlockSideInserter,
showBreadcrumb,
@@ -76,6 +83,7 @@ export default function BlockTools( {
const {
duplicateBlocks,
removeBlocks,
+ replaceBlocks,
insertAfterBlock,
insertBeforeBlock,
selectBlock,
@@ -159,6 +167,19 @@ export default function BlockTools( {
}
event.preventDefault();
expandBlock( clientId );
+ } else if ( isMatch( 'core/block-editor/group', event ) ) {
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length > 1 && isGroupable( clientIds ) ) {
+ event.preventDefault();
+ const blocks = getBlocksByClientId( clientIds );
+ const groupingBlockName = getGroupingBlockName();
+ const newBlocks = switchToBlockType(
+ blocks,
+ groupingBlockName
+ );
+ replaceBlocks( clientIds, newBlocks );
+ speak( __( 'Selected blocks are grouped.' ) );
+ }
}
}
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 c2bb3fb25b845..2a015d569e85b 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
@@ -4,7 +4,8 @@
import { MenuItem } from '@wordpress/components';
import { _x } from '@wordpress/i18n';
import { switchToBlockType } from '@wordpress/blocks';
-import { useDispatch } from '@wordpress/data';
+import { useSelect, useDispatch } from '@wordpress/data';
+import { displayShortcut } from '@wordpress/keycodes';
/**
* Internal dependencies
@@ -22,6 +23,7 @@ function ConvertToGroupButton( {
groupingBlockName,
onClose = () => {},
} ) {
+ const { getSelectedBlockClientIds } = useSelect( blockEditorStore );
const { replaceBlocks } = useDispatch( blockEditorStore );
const onConvertToGroup = () => {
// Activate the `transform` on the Grouping Block which does the conversion.
@@ -52,10 +54,17 @@ function ConvertToGroupButton( {
return null;
}
+ const selectedBlockClientIds = getSelectedBlockClientIds();
+
return (
<>
{ isGroupable && (