diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md
index 7b5ec64bd44ca5..dbd1d09fbe690f 100644
--- a/packages/components/CHANGELOG.md
+++ b/packages/components/CHANGELOG.md
@@ -11,6 +11,7 @@
- `TreeSelect`: Deprecate 36px default size ([#67855](https://github.com/WordPress/gutenberg/pull/67855)).
- `SelectControl`: Deprecate 36px default size ([#66898](https://github.com/WordPress/gutenberg/pull/66898)).
- `InputControl`: Deprecate 36px default size ([#66897](https://github.com/WordPress/gutenberg/pull/66897)).
+- Soft deprecate `ButtonGroup` component. Use `ToggleGroupControl` instead ([#65429](https://github.com/WordPress/gutenberg/pull/65429)).
### Bug Fixes
diff --git a/packages/components/src/button-group/README.md b/packages/components/src/button-group/README.md
index 5c0179d6877af9..579103dc70e062 100644
--- a/packages/components/src/button-group/README.md
+++ b/packages/components/src/button-group/README.md
@@ -1,5 +1,9 @@
# ButtonGroup
+
+ This component is deprecated. Use `ToggleGroupControl` instead.
+
+
ButtonGroup can be used to group any related buttons together. To emphasize related buttons, a group should share a common container.

diff --git a/packages/components/src/button-group/index.tsx b/packages/components/src/button-group/index.tsx
index fb2659c2a0d7de..4bdf3a139188b5 100644
--- a/packages/components/src/button-group/index.tsx
+++ b/packages/components/src/button-group/index.tsx
@@ -8,6 +8,7 @@ import type { ForwardedRef } from 'react';
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';
+import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
@@ -22,6 +23,11 @@ function UnforwardedButtonGroup(
const { className, ...restProps } = props;
const classes = clsx( 'components-button-group', className );
+ deprecated( 'wp.components.ButtonGroup', {
+ since: '6.8',
+ alternative: 'wp.components.ToggleGroupControl',
+ } );
+
return (
);
@@ -31,6 +37,8 @@ function UnforwardedButtonGroup(
* ButtonGroup can be used to group any related buttons together. To emphasize
* related buttons, a group should share a common container.
*
+ * @deprecated Use `ToggleGroupControl` instead.
+ *
* ```jsx
* import { Button, ButtonGroup } from '@wordpress/components';
*
diff --git a/packages/components/src/button-group/stories/index.story.tsx b/packages/components/src/button-group/stories/index.story.tsx
index 4b5ab3d5dfdb6b..a2df76004d4385 100644
--- a/packages/components/src/button-group/stories/index.story.tsx
+++ b/packages/components/src/button-group/stories/index.story.tsx
@@ -9,8 +9,15 @@ import type { Meta, StoryObj } from '@storybook/react';
import ButtonGroup from '..';
import Button from '../../button';
+/**
+ * ButtonGroup can be used to group any related buttons together.
+ * To emphasize related buttons, a group should share a common container.
+ *
+ * This component is deprecated. Use `ToggleGroupControl` instead.
+ */
const meta: Meta< typeof ButtonGroup > = {
- title: 'Components/ButtonGroup',
+ title: 'Components (Deprecated)/ButtonGroup',
+ id: 'components-buttongroup',
component: ButtonGroup,
argTypes: {
children: { control: false },
diff --git a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
index 030512a38fab3a..de12bbe466bf3b 100644
--- a/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
+++ b/packages/edit-site/src/components/sidebar-global-styles-wrapper/index.js
@@ -6,7 +6,7 @@ import { useMemo, useState } from '@wordpress/element';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useViewportMatch } from '@wordpress/compose';
import { Button } from '@wordpress/components';
-import { addQueryArgs } from '@wordpress/url';
+import { addQueryArgs, removeQueryArgs } from '@wordpress/url';
import { seen } from '@wordpress/icons';
/**
@@ -15,15 +15,15 @@ import { seen } from '@wordpress/icons';
import GlobalStylesUI from '../global-styles/ui';
import Page from '../page';
import { unlock } from '../../lock-unlock';
-import StyleBook from '../style-book';
-import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants';
const { useLocation, useHistory } = unlock( routerPrivateApis );
const GlobalStylesPageActions = ( {
isStyleBookOpened,
setIsStyleBookOpened,
+ path,
} ) => {
+ const history = useHistory();
return (
{
setIsStyleBookOpened( ! isStyleBookOpened );
+ const updatedPath = ! isStyleBookOpened
+ ? addQueryArgs( path, { preview: 'stylebook' } )
+ : removeQueryArgs( path, 'preview' );
+ // Navigate to the updated path.
+ history.navigate( updatedPath );
} }
size="compact"
/>
);
};
-export default function GlobalStylesUIWrapper() {
+/**
+ * Hook to deal with navigation and location state.
+ *
+ * @return {Array} The current section and a function to update it.
+ */
+export const useSection = () => {
const { path, query } = useLocation();
const history = useHistory();
- const { canvas = 'view' } = query;
- const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( false );
- const isMobileViewport = useViewportMatch( 'medium', '<' );
- const [ section, onChangeSection ] = useMemo( () => {
+ return useMemo( () => {
return [
query.section ?? '/',
( updatedSection ) => {
@@ -55,6 +62,16 @@ export default function GlobalStylesUIWrapper() {
},
];
}, [ path, query.section, history ] );
+};
+
+export default function GlobalStylesUIWrapper() {
+ const { path } = useLocation();
+
+ const [ isStyleBookOpened, setIsStyleBookOpened ] = useState(
+ path.includes( 'preview=stylebook' )
+ );
+ const isMobileViewport = useViewportMatch( 'medium', '<' );
+ const [ section, onChangeSection ] = useSection();
return (
<>
@@ -64,6 +81,7 @@ export default function GlobalStylesUIWrapper() {
) : null
}
@@ -75,45 +93,6 @@ export default function GlobalStylesUIWrapper() {
onPathChange={ onChangeSection }
/>
- { canvas === 'view' && isStyleBookOpened && (
-
- // Match '/blocks/core%2Fbutton' and
- // '/blocks/core%2Fbutton/typography', but not
- // '/blocks/core%2Fbuttons'.
- section ===
- `/blocks/${ encodeURIComponent( blockName ) }` ||
- section.startsWith(
- `/blocks/${ encodeURIComponent( blockName ) }/`
- )
- }
- path={ section }
- onSelect={ ( blockName ) => {
- if (
- STYLE_BOOK_COLOR_GROUPS.find(
- ( group ) => group.slug === blockName
- )
- ) {
- // Go to color palettes Global Styles.
- onChangeSection( '/colors/palette' );
- return;
- }
- if ( blockName === 'typography' ) {
- // Go to typography Global Styles.
- onChangeSection( '/typography' );
- return;
- }
-
- // Now go to the selected block.
- onChangeSection(
- `/blocks/${ encodeURIComponent( blockName ) }`
- );
- } }
- />
- ) }
>
);
}
diff --git a/packages/edit-site/src/components/site-editor-routes/stylebook.js b/packages/edit-site/src/components/site-editor-routes/stylebook.js
index a30c4a7c04945e..cb1e414098ab3f 100644
--- a/packages/edit-site/src/components/site-editor-routes/stylebook.js
+++ b/packages/edit-site/src/components/site-editor-routes/stylebook.js
@@ -22,7 +22,7 @@ export const stylebookRoute = {
) }
/>
),
- preview: ,
- mobile: ,
+ preview: ,
+ mobile: ,
},
};
diff --git a/packages/edit-site/src/components/site-editor-routes/styles.js b/packages/edit-site/src/components/site-editor-routes/styles.js
index cf29dbebea3733..a1827bee763390 100644
--- a/packages/edit-site/src/components/site-editor-routes/styles.js
+++ b/packages/edit-site/src/components/site-editor-routes/styles.js
@@ -10,6 +10,7 @@ import Editor from '../editor';
import { unlock } from '../../lock-unlock';
import SidebarNavigationScreenGlobalStyles from '../sidebar-navigation-screen-global-styles';
import GlobalStylesUIWrapper from '../sidebar-global-styles-wrapper';
+import { StyleBookPreview } from '../style-book';
const { useLocation } = unlock( routerPrivateApis );
@@ -30,7 +31,10 @@ export const stylesRoute = {
areas: {
content: ,
sidebar: ,
- preview: ,
+ preview( { query } ) {
+ const isStylebook = query.preview === 'stylebook';
+ return isStylebook ? : ;
+ },
mobile: ,
},
widths: {
diff --git a/packages/edit-site/src/components/style-book/index.js b/packages/edit-site/src/components/style-book/index.js
index da69ed734166ed..ecbd729ee8a0a2 100644
--- a/packages/edit-site/src/components/style-book/index.js
+++ b/packages/edit-site/src/components/style-book/index.js
@@ -32,6 +32,7 @@ import {
useContext,
useRef,
useLayoutEffect,
+ useEffect,
} from '@wordpress/element';
import { ENTER, SPACE } from '@wordpress/keycodes';
@@ -47,6 +48,8 @@ import {
} from './categories';
import { getExamples } from './examples';
import { store as siteEditorStore } from '../../store';
+import { useSection } from '../sidebar-global-styles-wrapper';
+import { STYLE_BOOK_COLOR_GROUPS } from '../style-book/constants';
const {
ExperimentalBlockEditorProvider,
@@ -346,25 +349,55 @@ function StyleBook( {
/**
* Style Book Preview component renders the stylebook without the Editor dependency.
*
- * @param {Object} props Component props.
- * @param {string} props.path Path to the selected block.
- * @param {Object} props.userConfig User configuration.
- * @param {Function} props.isSelected Function to check if a block is selected.
- * @param {Function} props.onSelect Function to select a block.
+ * @param {Object} props Component props.
+ * @param {Object} props.userConfig User configuration.
+ * @param {boolean} props.isStatic Whether the stylebook is static or clickable.
* @return {Object} Style Book Preview component.
*/
-export const StyleBookPreview = ( {
- path = '',
- userConfig = {},
- isSelected,
- onSelect,
-} ) => {
+export const StyleBookPreview = ( { userConfig = {}, isStatic = false } ) => {
const siteEditorSettings = useSelect(
( select ) => select( siteEditorStore ).getSettings(),
[]
);
+
// Update block editor settings because useMultipleOriginColorsAndGradients fetch colours from there.
- dispatch( blockEditorStore ).updateSettings( siteEditorSettings );
+ useEffect( () => {
+ dispatch( blockEditorStore ).updateSettings( siteEditorSettings );
+ }, [ siteEditorSettings ] );
+
+ const [ section, onChangeSection ] = useSection();
+
+ const isSelected = ( blockName ) => {
+ // Match '/blocks/core%2Fbutton' and
+ // '/blocks/core%2Fbutton/typography', but not
+ // '/blocks/core%2Fbuttons'.
+ return (
+ section === `/blocks/${ encodeURIComponent( blockName ) }` ||
+ section.startsWith(
+ `/blocks/${ encodeURIComponent( blockName ) }/`
+ )
+ );
+ };
+
+ const onSelect = ( blockName ) => {
+ if (
+ STYLE_BOOK_COLOR_GROUPS.find(
+ ( group ) => group.slug === blockName
+ )
+ ) {
+ // Go to color palettes Global Styles.
+ onChangeSection( '/colors/palette' );
+ return;
+ }
+ if ( blockName === 'typography' ) {
+ // Go to typography Global Styles.
+ onChangeSection( '/typography' );
+ return;
+ }
+
+ // Now go to the selected block.
+ onChangeSection( `/blocks/${ encodeURIComponent( blockName ) }` );
+ };
const [ resizeObserver, sizes ] = useResizeObserver();
const colors = useMultiOriginPalettes();
@@ -372,7 +405,7 @@ export const StyleBookPreview = ( {
const examplesForSinglePageUse = getExamplesForSinglePageUse( examples );
const { base: baseConfig } = useContext( GlobalStylesContext );
- const goTo = getStyleBookNavigationFromPath( path );
+ const goTo = getStyleBookNavigationFromPath( section );
const mergedConfig = useMemo( () => {
if ( ! isObjectEmpty( userConfig ) && ! isObjectEmpty( baseConfig ) ) {
@@ -404,8 +437,8 @@ export const StyleBookPreview = ( {
settings={ settings }
goTo={ goTo }
sizes={ sizes }
- isSelected={ isSelected }
- onSelect={ onSelect }
+ isSelected={ ! isStatic ? isSelected : null }
+ onSelect={ ! isStatic ? onSelect : null }
/>
diff --git a/packages/editor/src/components/commands/index.js b/packages/editor/src/components/commands/index.js
index 0040a09fbdc07d..d495dcaaef3379 100644
--- a/packages/editor/src/components/commands/index.js
+++ b/packages/editor/src/components/commands/index.js
@@ -25,6 +25,7 @@ import { store as noticesStore } from '@wordpress/notices';
import { store as blockEditorStore } from '@wordpress/block-editor';
import { store as coreStore, useEntityRecord } from '@wordpress/core-data';
import { store as interfaceStore } from '@wordpress/interface';
+import { getPath } from '@wordpress/url';
import { decodeEntities } from '@wordpress/html-entities';
/**
@@ -90,6 +91,19 @@ const getEditorCommandLoader = () =>
const { openModal, enableComplementaryArea, disableComplementaryArea } =
useDispatch( interfaceStore );
const { getCurrentPostId } = useSelect( editorStore );
+ const { isBlockBasedTheme, canCreateTemplate } = useSelect(
+ ( select ) => {
+ return {
+ isBlockBasedTheme:
+ select( coreStore ).getCurrentTheme()?.is_block_theme,
+ canCreateTemplate: select( coreStore ).canUser( 'create', {
+ kind: 'postType',
+ name: 'wp_template',
+ } ),
+ };
+ },
+ []
+ );
const allowSwitchEditorMode =
isCodeEditingEnabled && isRichEditingEnabled;
@@ -271,6 +285,21 @@ const getEditorCommandLoader = () =>
},
} );
}
+ if ( canCreateTemplate && isBlockBasedTheme ) {
+ const isSiteEditor = getPath( window.location.href )?.includes(
+ 'site-editor.php'
+ );
+ if ( ! isSiteEditor ) {
+ commands.push( {
+ name: 'core/go-to-site-editor',
+ label: __( 'Open Site Editor' ),
+ callback: ( { close } ) => {
+ close();
+ document.location = 'site-editor.php';
+ },
+ } );
+ }
+ }
return {
commands,
diff --git a/packages/editor/src/components/more-menu/index.js b/packages/editor/src/components/more-menu/index.js
index 9e062e5e5adc50..f5eaa45e4ed696 100644
--- a/packages/editor/src/components/more-menu/index.js
+++ b/packages/editor/src/components/more-menu/index.js
@@ -113,7 +113,6 @@ export default function MoreMenu() {
diff --git a/packages/editor/src/components/preview-dropdown/index.js b/packages/editor/src/components/preview-dropdown/index.js
index 6fa35c673430cc..a081564e48ea8d 100644
--- a/packages/editor/src/components/preview-dropdown/index.js
+++ b/packages/editor/src/components/preview-dropdown/index.js
@@ -190,7 +190,6 @@ export default function PreviewDropdown( { forceIsAutosaveable, disabled } ) {
) }
>
diff --git a/packages/interface/CHANGELOG.md b/packages/interface/CHANGELOG.md
index a0ed9cd83525cc..172d70b09fad31 100644
--- a/packages/interface/CHANGELOG.md
+++ b/packages/interface/CHANGELOG.md
@@ -2,6 +2,10 @@
## Unreleased
+### Breaking Changes
+
+- `ActionItem.Slot`: Render as `MenuGroup` by default ([#67985](https://github.com/WordPress/gutenberg/pull/67985)).
+
## 8.3.0 (2024-12-11)
## 8.2.0 (2024-11-27)
diff --git a/packages/interface/src/components/action-item/README.md b/packages/interface/src/components/action-item/README.md
index 15c627adfd3296..5611e044c8a985 100644
--- a/packages/interface/src/components/action-item/README.md
+++ b/packages/interface/src/components/action-item/README.md
@@ -24,11 +24,11 @@ Property used to change the event bubbling behavior, passed to the `Slot` compon
### as
-The component used as the container of the fills. Defaults to the `ButtonGroup` component.
+The component used as the container of the fills. Defaults to the `MenuGroup` component.
- Type: `Component`
- Required: no
-- Default: `ButtonGroup`
+- Default: `MenuGroup`
## ActionItem
diff --git a/packages/interface/src/components/action-item/index.js b/packages/interface/src/components/action-item/index.js
index 4bd5a11e8d71f8..2f3fdd6d3ca301 100644
--- a/packages/interface/src/components/action-item/index.js
+++ b/packages/interface/src/components/action-item/index.js
@@ -1,14 +1,14 @@
/**
* WordPress dependencies
*/
-import { ButtonGroup, Button, Slot, Fill } from '@wordpress/components';
+import { MenuGroup, Button, Slot, Fill } from '@wordpress/components';
import { Children } from '@wordpress/element';
const noop = () => {};
function ActionItemSlot( {
name,
- as: Component = ButtonGroup,
+ as: Component = MenuGroup,
fillProps = {},
bubblesVirtually,
...props