From 1bea96cdeb31591ef1317e003fddb483f855d81b Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 27 Jun 2023 11:59:46 +0100 Subject: [PATCH 1/9] Restore sidebar in focus mode on Pattern click through in Browse Mode Library (#51897) Brings back https://github.com/WordPress/gutenberg/pull/51492 --- packages/edit-site/src/components/page-library/grid-item.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/page-library/grid-item.js b/packages/edit-site/src/components/page-library/grid-item.js index 027e14ca9e9467..586602d1ac05d3 100644 --- a/packages/edit-site/src/components/page-library/grid-item.js +++ b/packages/edit-site/src/components/page-library/grid-item.js @@ -46,7 +46,7 @@ export default function GridItem( { categoryId, composite, icon, item } ) { postId: item.type === USER_PATTERNS ? item.id : item.name, categoryId, categoryType: item.type, - canvas: 'edit', + canvas: 'view', } ); const onKeyDown = ( event ) => { From bdc33c9fdc905994ceb5cb48e53fa75d31555667 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Tue, 27 Jun 2023 17:19:15 +0300 Subject: [PATCH 2/9] [Command center]: Add preferences and keyboard shortcuts commands (#51862) * [Command center]: Add preferences and keyboard shortcuts commands * update labels --- .../data/data-core-edit-post.md | 6 +++ .../header/preferences-menu-item/index.js | 7 +-- .../keyboard-shortcut-help-modal/index.js | 15 ++++-- .../src/components/preferences-modal/index.js | 10 ++-- .../src/hooks/commands/use-common-commands.js | 22 ++++++++ .../index.js | 7 +-- packages/edit-post/src/store/actions.js | 31 +++++++---- packages/edit-post/src/store/reducer.js | 20 ------- packages/edit-post/src/store/selectors.js | 14 +++-- packages/edit-post/src/store/test/reducer.js | 25 --------- .../edit-post/src/store/test/selectors.js | 27 ---------- .../header-edit-mode/more-menu/index.js | 53 +++++++++---------- .../keyboard-shortcut-help-modal/index.js | 28 +++++++--- .../src/components/preferences-modal/index.js | 20 ++++--- .../hooks/commands/use-edit-mode-commands.js | 26 ++++++++- packages/interface/src/store/actions.js | 25 +++++++++ packages/interface/src/store/reducer.js | 20 +++++++ packages/interface/src/store/selectors.js | 12 +++++ packages/interface/src/store/test/reducer.js | 30 +++++++++++ .../interface/src/store/test/selectors.js | 32 +++++++++++ 20 files changed, 288 insertions(+), 142 deletions(-) create mode 100644 packages/interface/src/store/test/reducer.js create mode 100644 packages/interface/src/store/test/selectors.js diff --git a/docs/reference-guides/data/data-core-edit-post.md b/docs/reference-guides/data/data-core-edit-post.md index aee88ce40bc731..b579e7e658007a 100644 --- a/docs/reference-guides/data/data-core-edit-post.md +++ b/docs/reference-guides/data/data-core-edit-post.md @@ -264,6 +264,8 @@ _Returns_ ### isModalActive +> **Deprecated** since WP 6.3 use `core/interface` store's selector with the same name instead. + Returns true if a modal is active, or false otherwise. _Parameters_ @@ -336,6 +338,8 @@ Returns an action object signalling that the user closed the sidebar. ### closeModal +> **Deprecated** since WP 6.3 use `core/interface` store's action with the same name instead. + Returns an action object signalling that the user closed a modal. _Returns_ @@ -388,6 +392,8 @@ _Parameters_ ### openModal +> **Deprecated** since WP 6.3 use `core/interface` store's action with the same name instead. + Returns an action object used in signalling that the user opened a modal. _Parameters_ diff --git a/packages/edit-post/src/components/header/preferences-menu-item/index.js b/packages/edit-post/src/components/header/preferences-menu-item/index.js index bc747ca0afde88..037a896fc7f070 100644 --- a/packages/edit-post/src/components/header/preferences-menu-item/index.js +++ b/packages/edit-post/src/components/header/preferences-menu-item/index.js @@ -4,18 +4,19 @@ import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { MenuItem } from '@wordpress/components'; +import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies */ -import { store as editPostStore } from '../../../store'; +import { PREFERENCES_MODAL_NAME } from '../../../components/preferences-modal'; export default function PreferencesMenuItem() { - const { openModal } = useDispatch( editPostStore ); + const { openModal } = useDispatch( interfaceStore ); return ( { - openModal( 'edit-post/preferences' ); + openModal( PREFERENCES_MODAL_NAME ); } } > { __( 'Preferences' ) } diff --git a/packages/edit-post/src/components/keyboard-shortcut-help-modal/index.js b/packages/edit-post/src/components/keyboard-shortcut-help-modal/index.js index 54565bb5dcd5b5..9a7ce46704d479 100644 --- a/packages/edit-post/src/components/keyboard-shortcut-help-modal/index.js +++ b/packages/edit-post/src/components/keyboard-shortcut-help-modal/index.js @@ -14,6 +14,7 @@ import { } from '@wordpress/keyboard-shortcuts'; import { withSelect, withDispatch, useSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; +import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies @@ -21,9 +22,9 @@ import { compose } from '@wordpress/compose'; import { textFormattingShortcuts } from './config'; import Shortcut from './shortcut'; import DynamicShortcut from './dynamic-shortcut'; -import { store as editPostStore } from '../../store'; -const MODAL_NAME = 'edit-post/keyboard-shortcut-help'; +export const KEYBOARD_SHORTCUT_HELP_MODAL_NAME = + 'edit-post/keyboard-shortcut-help'; const ShortcutList = ( { shortcuts } ) => ( /* @@ -141,14 +142,18 @@ export function KeyboardShortcutHelpModal( { isModalActive, toggleModal } ) { export default compose( [ withSelect( ( select ) => ( { - isModalActive: select( editPostStore ).isModalActive( MODAL_NAME ), + isModalActive: select( interfaceStore ).isModalActive( + KEYBOARD_SHORTCUT_HELP_MODAL_NAME + ), } ) ), withDispatch( ( dispatch, { isModalActive } ) => { - const { openModal, closeModal } = dispatch( editPostStore ); + const { openModal, closeModal } = dispatch( interfaceStore ); return { toggleModal: () => - isModalActive ? closeModal() : openModal( MODAL_NAME ), + isModalActive + ? closeModal() + : openModal( KEYBOARD_SHORTCUT_HELP_MODAL_NAME ), }; } ), ] )( KeyboardShortcutHelpModal ); diff --git a/packages/edit-post/src/components/preferences-modal/index.js b/packages/edit-post/src/components/preferences-modal/index.js index 77c6383b13f32c..bb0c8b5cd12715 100644 --- a/packages/edit-post/src/components/preferences-modal/index.js +++ b/packages/edit-post/src/components/preferences-modal/index.js @@ -18,6 +18,7 @@ import { PreferencesModal, PreferencesModalTabs, PreferencesModalSection, + store as interfaceStore, } from '@wordpress/interface'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -35,17 +36,18 @@ import MetaBoxesSection from './meta-boxes-section'; import { store as editPostStore } from '../../store'; import BlockManager from '../block-manager'; -const MODAL_NAME = 'edit-post/preferences'; +export const PREFERENCES_MODAL_NAME = 'edit-post/preferences'; export default function EditPostPreferencesModal() { const isLargeViewport = useViewportMatch( 'medium' ); - const { closeModal } = useDispatch( editPostStore ); + const { closeModal } = useDispatch( interfaceStore ); const [ isModalActive, showBlockBreadcrumbsOption ] = useSelect( ( select ) => { const { getEditorSettings } = select( editorStore ); const { getEditorMode, isFeatureActive } = select( editPostStore ); - const modalActive = - select( editPostStore ).isModalActive( MODAL_NAME ); + const modalActive = select( interfaceStore ).isModalActive( + PREFERENCES_MODAL_NAME + ); const mode = getEditorMode(); const isRichEditingEnabled = getEditorSettings().richEditingEnabled; const isDistractionFreeEnabled = diff --git a/packages/edit-post/src/hooks/commands/use-common-commands.js b/packages/edit-post/src/hooks/commands/use-common-commands.js index 796e0665fc2fa3..0366e781799856 100644 --- a/packages/edit-post/src/hooks/commands/use-common-commands.js +++ b/packages/edit-post/src/hooks/commands/use-common-commands.js @@ -9,6 +9,7 @@ import { drawerLeft, drawerRight, blockDefault, + keyboardClose, } from '@wordpress/icons'; import { useCommand } from '@wordpress/commands'; import { store as preferencesStore } from '@wordpress/preferences'; @@ -17,11 +18,14 @@ import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies */ +import { KEYBOARD_SHORTCUT_HELP_MODAL_NAME } from '../../components/keyboard-shortcut-help-modal'; +import { PREFERENCES_MODAL_NAME } from '../../components/preferences-modal'; import { store as editPostStore } from '../../store'; export default function useCommonCommands() { const { openGeneralSidebar, closeGeneralSidebar, switchEditorMode } = useDispatch( editPostStore ); + const { openModal } = useDispatch( interfaceStore ); const { editorMode, activeSidebar } = useSelect( ( select ) => ( { activeSidebar: select( interfaceStore ).getActiveComplementaryArea( @@ -100,4 +104,22 @@ export default function useCommonCommands() { close(); }, } ); + + useCommand( { + name: 'core/open-preferences', + label: __( 'Open editor preferences' ), + icon: cog, + callback: () => { + openModal( PREFERENCES_MODAL_NAME ); + }, + } ); + + useCommand( { + name: 'core/open-shortcut-help', + label: __( 'Open keyboard shortcuts' ), + icon: keyboardClose, + callback: () => { + openModal( KEYBOARD_SHORTCUT_HELP_MODAL_NAME ); + }, + } ); } diff --git a/packages/edit-post/src/plugins/keyboard-shortcuts-help-menu-item/index.js b/packages/edit-post/src/plugins/keyboard-shortcuts-help-menu-item/index.js index 69f7b35c3f1167..930f420a241299 100644 --- a/packages/edit-post/src/plugins/keyboard-shortcuts-help-menu-item/index.js +++ b/packages/edit-post/src/plugins/keyboard-shortcuts-help-menu-item/index.js @@ -5,17 +5,18 @@ import { MenuItem } from '@wordpress/components'; import { withDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { displayShortcut } from '@wordpress/keycodes'; +import { store as interfaceStore } from '@wordpress/interface'; /** * Internal dependencies */ -import { store as editPostStore } from '../../store'; +import { KEYBOARD_SHORTCUT_HELP_MODAL_NAME } from '../../components/keyboard-shortcut-help-modal'; export function KeyboardShortcutsHelpMenuItem( { openModal } ) { return ( { - openModal( 'edit-post/keyboard-shortcut-help' ); + openModal( KEYBOARD_SHORTCUT_HELP_MODAL_NAME ); } } shortcut={ displayShortcut.access( 'h' ) } > @@ -25,7 +26,7 @@ export function KeyboardShortcutsHelpMenuItem( { openModal } ) { } export default withDispatch( ( dispatch ) => { - const { openModal } = dispatch( editPostStore ); + const { openModal } = dispatch( interfaceStore ); return { openModal, diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js index 90f29f37b145cf..f938a9837516e0 100644 --- a/packages/edit-post/src/store/actions.js +++ b/packages/edit-post/src/store/actions.js @@ -10,6 +10,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as editorStore } from '@wordpress/editor'; +import deprecated from '@wordpress/deprecated'; /** * Internal dependencies @@ -42,27 +43,39 @@ export const closeGeneralSidebar = /** * Returns an action object used in signalling that the user opened a modal. * + * @deprecated since WP 6.3 use `core/interface` store's action with the same name instead. + * + * * @param {string} name A string that uniquely identifies the modal. * * @return {Object} Action object. */ -export function openModal( name ) { - return { - type: 'OPEN_MODAL', - name, +export const openModal = + ( name ) => + ( { registry } ) => { + deprecated( "select( 'core/edit-post' ).openModal( name )", { + since: '6.3', + alternative: "select( 'core/interface').openModal( name )", + } ); + return registry.dispatch( interfaceStore ).openModal( name ); }; -} /** * Returns an action object signalling that the user closed a modal. * + * @deprecated since WP 6.3 use `core/interface` store's action with the same name instead. + * * @return {Object} Action object. */ -export function closeModal() { - return { - type: 'CLOSE_MODAL', +export const closeModal = + () => + ( { registry } ) => { + deprecated( "select( 'core/edit-post' ).closeModal()", { + since: '6.3', + alternative: "select( 'core/interface').closeModal()", + } ); + return registry.dispatch( interfaceStore ).closeModal(); }; -} /** * Returns an action object used in signalling that the user opened the publish diff --git a/packages/edit-post/src/store/reducer.js b/packages/edit-post/src/store/reducer.js index 8a4031ecf9b098..622b2e2667f7fc 100644 --- a/packages/edit-post/src/store/reducer.js +++ b/packages/edit-post/src/store/reducer.js @@ -22,25 +22,6 @@ export function removedPanels( state = [], action ) { return state; } -/** - * Reducer for storing the name of the open modal, or null if no modal is open. - * - * @param {Object} state Previous state. - * @param {Object} action Action object containing the `name` of the modal - * - * @return {Object} Updated state - */ -export function activeModal( state = null, action ) { - switch ( action.type ) { - case 'OPEN_MODAL': - return action.name; - case 'CLOSE_MODAL': - return null; - } - - return state; -} - export function publishSidebarActive( state = false, action ) { switch ( action.type ) { case 'OPEN_PUBLISH_SIDEBAR': @@ -209,7 +190,6 @@ const metaBoxes = combineReducers( { } ); export default combineReducers( { - activeModal, metaBoxes, publishSidebarActive, removedPanels, diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js index b84e2b6887431a..5ae7d6b4437b71 100644 --- a/packages/edit-post/src/store/selectors.js +++ b/packages/edit-post/src/store/selectors.js @@ -298,14 +298,22 @@ export const isEditorPanelOpened = createRegistrySelector( /** * Returns true if a modal is active, or false otherwise. * + * @deprecated since WP 6.3 use `core/interface` store's selector with the same name instead. + * * @param {Object} state Global application state. * @param {string} modalName A string that uniquely identifies the modal. * * @return {boolean} Whether the modal is active. */ -export function isModalActive( state, modalName ) { - return state.activeModal === modalName; -} +export const isModalActive = createRegistrySelector( + ( select ) => ( state, modalName ) => { + deprecated( `select( 'core/edit-post' ).isModalActive`, { + since: '6.3', + alternative: `select( 'core/interface' ).isModalActive`, + } ); + return !! select( interfaceStore ).isModalActive( modalName ); + } +); /** * Returns whether the given feature is enabled or not. diff --git a/packages/edit-post/src/store/test/reducer.js b/packages/edit-post/src/store/test/reducer.js index 4be7c7cb3ffd80..a083de9c672868 100644 --- a/packages/edit-post/src/store/test/reducer.js +++ b/packages/edit-post/src/store/test/reducer.js @@ -7,7 +7,6 @@ import deepFreeze from 'deep-freeze'; * Internal dependencies */ import { - activeModal, isSavingMetaBoxes, metaBoxLocations, removedPanels, @@ -18,30 +17,6 @@ import { import { setIsInserterOpened, setIsListViewOpened } from '../actions'; describe( 'state', () => { - describe( 'activeModal', () => { - it( 'should default to null', () => { - const state = activeModal( undefined, {} ); - expect( state ).toBeNull(); - } ); - - it( 'should set the activeModal to the provided name', () => { - const state = activeModal( null, { - type: 'OPEN_MODAL', - name: 'test-modal', - } ); - - expect( state ).toEqual( 'test-modal' ); - } ); - - it( 'should set the activeModal to null', () => { - const state = activeModal( 'test-modal', { - type: 'CLOSE_MODAL', - } ); - - expect( state ).toBeNull(); - } ); - } ); - describe( 'isSavingMetaBoxes', () => { it( 'should return default state', () => { const actual = isSavingMetaBoxes( undefined, {} ); diff --git a/packages/edit-post/src/store/test/selectors.js b/packages/edit-post/src/store/test/selectors.js index 5df8456dd8534d..34c66ed7cf8e67 100644 --- a/packages/edit-post/src/store/test/selectors.js +++ b/packages/edit-post/src/store/test/selectors.js @@ -7,7 +7,6 @@ import deepFreeze from 'deep-freeze'; * Internal dependencies */ import { - isModalActive, hasMetaBoxes, isSavingMetaBoxes, getActiveMetaBoxLocations, @@ -18,32 +17,6 @@ import { } from '../selectors'; describe( 'selectors', () => { - describe( 'isModalActive', () => { - it( 'returns true if the provided name matches the value in the preferences activeModal property', () => { - const state = { - activeModal: 'test-modal', - }; - - expect( isModalActive( state, 'test-modal' ) ).toBe( true ); - } ); - - it( 'returns false if the provided name does not match the preferences activeModal property', () => { - const state = { - activeModal: 'something-else', - }; - - expect( isModalActive( state, 'test-modal' ) ).toBe( false ); - } ); - - it( 'returns false if the preferences activeModal property is null', () => { - const state = { - activeModal: null, - }; - - expect( isModalActive( state, 'test-modal' ) ).toBe( false ); - } ); - } ); - describe( 'isEditorPanelRemoved', () => { it( 'should return false by default', () => { const state = deepFreeze( { diff --git a/packages/edit-site/src/components/header-edit-mode/more-menu/index.js b/packages/edit-site/src/components/header-edit-mode/more-menu/index.js index 7fe63a343960ae..4b9d6c40fc6eec 100644 --- a/packages/edit-site/src/components/header-edit-mode/more-menu/index.js +++ b/packages/edit-site/src/components/header-edit-mode/more-menu/index.js @@ -2,13 +2,15 @@ * WordPress dependencies */ import { __, _x } from '@wordpress/i18n'; -import { useReducer } from '@wordpress/element'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; -import { useShortcut } from '@wordpress/keyboard-shortcuts'; import { displayShortcut } from '@wordpress/keycodes'; import { external } from '@wordpress/icons'; import { MenuGroup, MenuItem, VisuallyHidden } from '@wordpress/components'; -import { ActionItem, MoreMenuDropdown } from '@wordpress/interface'; +import { + ActionItem, + MoreMenuDropdown, + store as interfaceStore, +} from '@wordpress/interface'; import { PreferenceToggleMenuItem, store as preferencesStore, @@ -17,8 +19,14 @@ import { /** * Internal dependencies */ -import KeyboardShortcutHelpModal from '../../keyboard-shortcut-help-modal'; -import EditSitePreferencesModal from '../../preferences-modal'; +import { + KEYBOARD_SHORTCUT_HELP_MODAL_NAME, + default as KeyboardShortcutHelpModal, +} from '../../keyboard-shortcut-help-modal'; +import { + PREFERENCES_MODAL_NAME, + default as EditSitePreferencesModal, +} from '../../preferences-modal'; import ToolsMoreMenuGroup from '../tools-more-menu-group'; import SiteExport from './site-export'; import WelcomeGuideMenuItem from './welcome-guide-menu-item'; @@ -27,16 +35,6 @@ import ModeSwitcher from '../mode-switcher'; import { store as siteEditorStore } from '../../../store'; export default function MoreMenu( { showIconLabels } ) { - const [ isModalActive, toggleModal ] = useReducer( - ( isActive ) => ! isActive, - false - ); - - const [ isPreferencesModalActive, togglePreferencesModal ] = useReducer( - ( isActive ) => ! isActive, - false - ); - const registry = useRegistry(); const isDistractionFree = useSelect( ( select ) => @@ -49,6 +47,7 @@ export default function MoreMenu( { showIconLabels } ) { const { setIsInserterOpened, setIsListViewOpened, closeGeneralSidebar } = useDispatch( siteEditorStore ); + const { openModal } = useDispatch( interfaceStore ); const { set: setPreference } = useDispatch( preferencesStore ); const toggleDistractionFree = () => { @@ -60,8 +59,6 @@ export default function MoreMenu( { showIconLabels } ) { } ); }; - useShortcut( 'core/edit-site/keyboard-shortcuts', toggleModal ); - return ( <> + openModal( + KEYBOARD_SHORTCUT_HELP_MODAL_NAME + ) + } shortcut={ displayShortcut.access( 'h' ) } > { __( 'Keyboard shortcuts' ) } @@ -156,21 +157,19 @@ export default function MoreMenu( { showIconLabels } ) { /> - + + openModal( PREFERENCES_MODAL_NAME ) + } + > { __( 'Preferences' ) } ) } - - + + ); } diff --git a/packages/edit-site/src/components/keyboard-shortcut-help-modal/index.js b/packages/edit-site/src/components/keyboard-shortcut-help-modal/index.js index aac95775cf1d0d..1da14a7cccbe77 100644 --- a/packages/edit-site/src/components/keyboard-shortcut-help-modal/index.js +++ b/packages/edit-site/src/components/keyboard-shortcut-help-modal/index.js @@ -8,8 +8,12 @@ import classnames from 'classnames'; */ import { Modal } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts'; -import { useSelect } from '@wordpress/data'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; +import { store as interfaceStore } from '@wordpress/interface'; +import { useSelect, useDispatch } from '@wordpress/data'; /** * Internal dependencies @@ -18,6 +22,9 @@ import { textFormattingShortcuts } from './config'; import Shortcut from './shortcut'; import DynamicShortcut from './dynamic-shortcut'; +export const KEYBOARD_SHORTCUT_HELP_MODAL_NAME = + 'edit-site/keyboard-shortcut-help'; + const ShortcutList = ( { shortcuts } ) => ( /* * Disable reason: The `list` ARIA role is redundant but @@ -82,14 +89,21 @@ const ShortcutCategorySection = ( { ); }; -export default function KeyboardShortcutHelpModal( { - isModalActive, - toggleModal, -} ) { +export default function KeyboardShortcutHelpModal() { + const isModalActive = useSelect( ( select ) => + select( interfaceStore ).isModalActive( + KEYBOARD_SHORTCUT_HELP_MODAL_NAME + ) + ); + const { closeModal, openModal } = useDispatch( interfaceStore ); + const toggleModal = () => + isModalActive + ? closeModal() + : openModal( KEYBOARD_SHORTCUT_HELP_MODAL_NAME ); + useShortcut( 'core/edit-site/keyboard-shortcuts', toggleModal ); if ( ! isModalActive ) { return null; } - return ( + select( interfaceStore ).isModalActive( PREFERENCES_MODAL_NAME ) + ); + const { closeModal, openModal } = useDispatch( interfaceStore ); + const toggleModal = () => + isModalActive ? closeModal() : openModal( PREFERENCES_MODAL_NAME ); const registry = useRegistry(); const { closeGeneralSidebar, setIsListViewOpened, setIsInserterOpened } = - useDispatch( siteEditorStore ); + useDispatch( editSiteStore ); const { set: setPreference } = useDispatch( preferencesStore ); const toggleDistractionFree = () => { diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js index 2466bb2a706c4e..92ccee08592cde 100644 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js @@ -4,8 +4,6 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { __, isRTL } from '@wordpress/i18n'; import { - code, - cog, trash, backup, layout, @@ -13,6 +11,9 @@ import { drawerLeft, drawerRight, blockDefault, + cog, + code, + keyboardClose, } from '@wordpress/icons'; import { useCommandLoader } from '@wordpress/commands'; import { privateApis as routerPrivateApis } from '@wordpress/router'; @@ -26,6 +27,8 @@ import { store as editSiteStore } from '../../store'; import useEditedEntityRecord from '../../components/use-edited-entity-record'; import isTemplateRemovable from '../../utils/is-template-removable'; import isTemplateRevertable from '../../utils/is-template-revertable'; +import { KEYBOARD_SHORTCUT_HELP_MODAL_NAME } from '../../components/keyboard-shortcut-help-modal'; +import { PREFERENCES_MODAL_NAME } from '../../components/preferences-modal'; import { unlock } from '../../lock-unlock'; const { useHistory } = unlock( routerPrivateApis ); @@ -142,6 +145,7 @@ function useEditUICommands() { } ), [] ); + const { openModal } = useDispatch( interfaceStore ); const { toggle } = useDispatch( preferencesStore ); if ( canvasMode !== 'edit' ) { @@ -208,6 +212,24 @@ function useEditUICommands() { }, } ); + commands.push( { + name: 'core/open-preferences', + label: __( 'Open editor preferences' ), + icon: cog, + callback: () => { + openModal( PREFERENCES_MODAL_NAME ); + }, + } ); + + commands.push( { + name: 'core/open-shortcut-help', + label: __( 'Open keyboard shortcuts' ), + icon: keyboardClose, + callback: () => { + openModal( KEYBOARD_SHORTCUT_HELP_MODAL_NAME ); + }, + } ); + return { isLoading: false, commands, diff --git a/packages/interface/src/store/actions.js b/packages/interface/src/store/actions.js index bc51d4fca72202..b7a9935e888b51 100644 --- a/packages/interface/src/store/actions.js +++ b/packages/interface/src/store/actions.js @@ -181,3 +181,28 @@ export function setFeatureDefaults( scope, defaults ) { registry.dispatch( preferencesStore ).setDefaults( scope, defaults ); }; } + +/** + * Returns an action object used in signalling that the user opened a modal. + * + * @param {string} name A string that uniquely identifies the modal. + * + * @return {Object} Action object. + */ +export function openModal( name ) { + return { + type: 'OPEN_MODAL', + name, + }; +} + +/** + * Returns an action object signalling that the user closed a modal. + * + * @return {Object} Action object. + */ +export function closeModal() { + return { + type: 'CLOSE_MODAL', + }; +} diff --git a/packages/interface/src/store/reducer.js b/packages/interface/src/store/reducer.js index 433f71d15bcc57..8317e53cec95bf 100644 --- a/packages/interface/src/store/reducer.js +++ b/packages/interface/src/store/reducer.js @@ -30,6 +30,26 @@ export function complementaryAreas( state = {}, action ) { return state; } +/** + * Reducer for storing the name of the open modal, or null if no modal is open. + * + * @param {Object} state Previous state. + * @param {Object} action Action object containing the `name` of the modal + * + * @return {Object} Updated state + */ +export function activeModal( state = null, action ) { + switch ( action.type ) { + case 'OPEN_MODAL': + return action.name; + case 'CLOSE_MODAL': + return null; + } + + return state; +} + export default combineReducers( { complementaryAreas, + activeModal, } ); diff --git a/packages/interface/src/store/selectors.js b/packages/interface/src/store/selectors.js index c92e45bbd3c590..548cb2f70346ac 100644 --- a/packages/interface/src/store/selectors.js +++ b/packages/interface/src/store/selectors.js @@ -90,3 +90,15 @@ export const isFeatureActive = createRegistrySelector( return !! select( preferencesStore ).get( scope, featureName ); } ); + +/** + * Returns true if a modal is active, or false otherwise. + * + * @param {Object} state Global application state. + * @param {string} modalName A string that uniquely identifies the modal. + * + * @return {boolean} Whether the modal is active. + */ +export function isModalActive( state, modalName ) { + return state.activeModal === modalName; +} diff --git a/packages/interface/src/store/test/reducer.js b/packages/interface/src/store/test/reducer.js new file mode 100644 index 00000000000000..eb9424637bca0f --- /dev/null +++ b/packages/interface/src/store/test/reducer.js @@ -0,0 +1,30 @@ +/** + * Internal dependencies + */ +import { activeModal } from '../reducer'; + +describe( 'state', () => { + describe( 'activeModal', () => { + it( 'should default to null', () => { + const state = activeModal( undefined, {} ); + expect( state ).toBeNull(); + } ); + + it( 'should set the activeModal to the provided name', () => { + const state = activeModal( null, { + type: 'OPEN_MODAL', + name: 'test-modal', + } ); + + expect( state ).toEqual( 'test-modal' ); + } ); + + it( 'should set the activeModal to null', () => { + const state = activeModal( 'test-modal', { + type: 'CLOSE_MODAL', + } ); + + expect( state ).toBeNull(); + } ); + } ); +} ); diff --git a/packages/interface/src/store/test/selectors.js b/packages/interface/src/store/test/selectors.js new file mode 100644 index 00000000000000..a3bea882043d29 --- /dev/null +++ b/packages/interface/src/store/test/selectors.js @@ -0,0 +1,32 @@ +/** + * Internal dependencies + */ +import { isModalActive } from '../selectors'; + +describe( 'selectors', () => { + describe( 'isModalActive', () => { + it( 'returns true if the provided name matches the value in the preferences activeModal property', () => { + const state = { + activeModal: 'test-modal', + }; + + expect( isModalActive( state, 'test-modal' ) ).toBe( true ); + } ); + + it( 'returns false if the provided name does not match the preferences activeModal property', () => { + const state = { + activeModal: 'something-else', + }; + + expect( isModalActive( state, 'test-modal' ) ).toBe( false ); + } ); + + it( 'returns false if the preferences activeModal property is null', () => { + const state = { + activeModal: null, + }; + + expect( isModalActive( state, 'test-modal' ) ).toBe( false ); + } ); + } ); +} ); From af9f28b39f5335ec006ad62b8189ab9c7f225333 Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Fri, 23 Jun 2023 13:48:44 +0300 Subject: [PATCH 3/9] [Site Editor]: Fix `library` command path (#51837) --- packages/core-commands/src/site-editor-navigation-commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-commands/src/site-editor-navigation-commands.js b/packages/core-commands/src/site-editor-navigation-commands.js index a46c8c02d2220f..6331afd058de34 100644 --- a/packages/core-commands/src/site-editor-navigation-commands.js +++ b/packages/core-commands/src/site-editor-navigation-commands.js @@ -203,7 +203,7 @@ function useSiteEditorBasicNavigationCommands() { icon: symbolFilled, callback: ( { close } ) => { const args = { - path: '/wp_template_part', + path: '/library', }; const targetUrl = addQueryArgs( 'site-editor.php', args ); if ( isSiteEditor ) { From 24e9d2ed1b632edb424d52b3109422f744bb6606 Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 28 Jun 2023 14:05:36 +1000 Subject: [PATCH 4/9] Updating social link attributes (#51997) --- packages/block-library/src/social-link/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/social-link/index.php b/packages/block-library/src/social-link/index.php index 51ed9374c9bcdf..1e5c4cf5de6fbd 100644 --- a/packages/block-library/src/social-link/index.php +++ b/packages/block-library/src/social-link/index.php @@ -47,8 +47,8 @@ function render_block_core_social_link( $attributes, $content, $block ) { $icon = block_core_social_link_get_icon( $service ); $wrapper_attributes = get_block_wrapper_attributes( array( - 'class' => 'wp-social-link wp-social-link-' . $service . block_core_social_link_get_color_classes( $block->context ), - 'style' => block_core_social_link_get_color_styles( $block->context ), + 'class' => esc_attr( 'wp-social-link wp-social-link-' . $service . block_core_social_link_get_color_classes( $block->context ) ), + 'style' => esc_attr( block_core_social_link_get_color_styles( $block->context ) ), ) ); From 449ec381d255d1f91f34f528076e0bf386c6870f Mon Sep 17 00:00:00 2001 From: James Koster Date: Tue, 27 Jun 2023 15:54:55 +0100 Subject: [PATCH 5/9] Try: Update template titles (#51428) * Update template titles * Fix typo Co-authored-by: Alex Stine * Revert Index rename * "front page" -> "homepage" * Update 404 Page make more sense given the template appears in the Pages panel too. * Front Page * home title + description * Revert Home name change, and move compat files * separate code for wp versions * update tests --------- Co-authored-by: Alex Stine Co-authored-by: ntsekouras --- .../wordpress-6.2/block-template-utils.php | 145 +---------------- .../wordpress-6.3/block-template-utils.php | 150 ++++++++++++++++++ lib/load.php | 5 +- .../blocks/post-comments-form.test.js | 2 +- .../site-editor/settings-sidebar.test.js | 2 +- .../various/post-editor-template-mode.spec.js | 2 +- 6 files changed, 156 insertions(+), 150 deletions(-) create mode 100644 lib/compat/wordpress-6.3/block-template-utils.php diff --git a/lib/compat/wordpress-6.2/block-template-utils.php b/lib/compat/wordpress-6.2/block-template-utils.php index 7611b9be5cf1bb..db9bf427e6b471 100644 --- a/lib/compat/wordpress-6.2/block-template-utils.php +++ b/lib/compat/wordpress-6.2/block-template-utils.php @@ -1,7 +1,7 @@ _x( 'Index', 'Template name', 'gutenberg' ), - 'description' => __( - 'Used as a fallback template for all pages when a more specific template is not defined.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['home'] ) ) { - $default_template_types['home'] = array( - 'title' => _x( 'Home', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays the latest posts as either the site homepage or a custom page defined under reading settings. If it exists, the Front Page template overrides this template when posts are shown on the front page.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['front-page'] ) ) { - $default_template_types['front-page'] = array( - 'title' => _x( 'Front Page', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays your site's front page, whether it is set to display latest posts or a static page. The Front Page template takes precedence over all templates.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['singular'] ) ) { - $default_template_types['singular'] = array( - 'title' => _x( 'Singular', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays any single entry, such as a post or a page. This template will serve as a fallback when a more specific template (e.g., Single Post, Page, or Attachment) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['single'] ) ) { - $default_template_types['single'] = array( - 'title' => _x( 'Single', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays single posts on your website unless a custom template has been applied to that post or a dedicated template exists.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['page'] ) ) { - $default_template_types['page'] = array( - 'title' => _x( 'Page', 'Template name', 'gutenberg' ), - 'description' => __( 'Display all static pages unless a custom template has been applied or a dedicated template exists.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['archive'] ) ) { - $default_template_types['archive'] = array( - 'title' => _x( 'Archive', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays any archive, including posts by a single author, category, tag, taxonomy, custom post type, and date. This template will serve as a fallback when more specific templates (e.g., Category or Tag) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['author'] ) ) { - $default_template_types['author'] = array( - 'title' => _x( 'Author', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays a single author's post archive. This template will serve as a fallback when a more a specific template (e.g., Author: Admin) cannot be found.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['category'] ) ) { - $default_template_types['category'] = array( - 'title' => _x( 'Category', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a post category archive. This template will serve as a fallback when more specific template (e.g., Category: Recipes) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['taxonomy'] ) ) { - $default_template_types['taxonomy'] = array( - 'title' => _x( 'Taxonomy', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a custom taxonomy archive. Like categories and tags, taxonomies have terms which you use to classify things. For example: a taxonomy named "Art" can have multiple terms, such as "Modern" and "18th Century." This template will serve as a fallback when a more specific template (e.g, Taxonomy: Art) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['date'] ) ) { - $default_template_types['date'] = array( - 'title' => _x( 'Date', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays a post archive when a specific date is visited (e.g., example.com/2023/).', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['tag'] ) ) { - $default_template_types['tag'] = array( - 'title' => _x( 'Tag', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a post tag archive. This template will serve as a fallback when more specific template (e.g., Tag: Pizza) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['attachment'] ) ) { - $default_template_types['attachment'] = array( - 'title' => _x( 'Media', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor views the dedicated page that exists for any media attachment.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['search'] ) ) { - $default_template_types['search'] = array( - 'title' => _x( 'Search', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor performs a search on your website.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['privacy-policy'] ) ) { - $default_template_types['privacy-policy'] = array( - 'title' => _x( 'Privacy Policy', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays your site's Privacy Policy page.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['404'] ) ) { - $default_template_types['404'] = array( - 'title' => _x( '404', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor views a non-existent page, such as a dead link or a mistyped URL.', 'gutenberg' ), - ); - } - - return $default_template_types; -} -add_filter( 'default_template_types', 'gutenberg_get_default_block_template_types', 10 ); diff --git a/lib/compat/wordpress-6.3/block-template-utils.php b/lib/compat/wordpress-6.3/block-template-utils.php new file mode 100644 index 00000000000000..cdd870db2d0813 --- /dev/null +++ b/lib/compat/wordpress-6.3/block-template-utils.php @@ -0,0 +1,150 @@ + _x( 'Index', 'Template name', 'gutenberg' ), + 'description' => __( + 'Used as a fallback template for all pages when a more specific template is not defined.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['home'] ) ) { + $default_template_types['home'] = array( + 'title' => _x( 'Home', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays the latest posts as either the site homepage or as the "Posts page" as defined under reading settings. If it exists, the Front Page template overrides this template when posts are shown on the homepage.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['front-page'] ) ) { + $default_template_types['front-page'] = array( + 'title' => _x( 'Front Page', 'Template name', 'gutenberg' ), + 'description' => __( + "Displays your site's homepage, whether it is set to display latest posts or a static page. The Front Page template takes precedence over all templates.", + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['singular'] ) ) { + $default_template_types['singular'] = array( + 'title' => _x( 'Single Entries', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays any single entry, such as a post or a page. This template will serve as a fallback when a more specific template (e.g., Single Post, Page, or Attachment) cannot be found.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['single'] ) ) { + $default_template_types['single'] = array( + 'title' => _x( 'Single Posts', 'Template name', 'gutenberg' ), + 'description' => __( 'Displays single posts on your website unless a custom template has been applied to that post or a dedicated template exists.', 'gutenberg' ), + ); + } + if ( isset( $default_template_types['page'] ) ) { + $default_template_types['page'] = array( + 'title' => _x( 'Pages', 'Template name', 'gutenberg' ), + 'description' => __( 'Display all static pages unless a custom template has been applied or a dedicated template exists.', 'gutenberg' ), + ); + } + if ( isset( $default_template_types['archive'] ) ) { + $default_template_types['archive'] = array( + 'title' => _x( 'All Archives', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays any archive, including posts by a single author, category, tag, taxonomy, custom post type, and date. This template will serve as a fallback when more specific templates (e.g., Category or Tag) cannot be found.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['author'] ) ) { + $default_template_types['author'] = array( + 'title' => _x( 'Author Archives', 'Template name', 'gutenberg' ), + 'description' => __( + "Displays a single author's post archive. This template will serve as a fallback when a more a specific template (e.g., Author: Admin) cannot be found.", + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['category'] ) ) { + $default_template_types['category'] = array( + 'title' => _x( 'Category Archives', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays a post category archive. This template will serve as a fallback when more specific template (e.g., Category: Recipes) cannot be found.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['taxonomy'] ) ) { + $default_template_types['taxonomy'] = array( + 'title' => _x( 'Taxonomy', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays a custom taxonomy archive. Like categories and tags, taxonomies have terms which you use to classify things. For example: a taxonomy named "Art" can have multiple terms, such as "Modern" and "18th Century." This template will serve as a fallback when a more specific template (e.g, Taxonomy: Art) cannot be found.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['date'] ) ) { + $default_template_types['date'] = array( + 'title' => _x( 'Date Archives', 'Template name', 'gutenberg' ), + 'description' => __( 'Displays a post archive when a specific date is visited (e.g., example.com/2023/).', 'gutenberg' ), + ); + } + if ( isset( $default_template_types['tag'] ) ) { + $default_template_types['tag'] = array( + 'title' => _x( 'Tag Archives', 'Template name', 'gutenberg' ), + 'description' => __( + 'Displays a post tag archive. This template will serve as a fallback when more specific template (e.g., Tag: Pizza) cannot be found.', + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['attachment'] ) ) { + $default_template_types['attachment'] = array( + 'title' => _x( 'Attachment Pages', 'Template name', 'gutenberg' ), + 'description' => __( 'Displays when a visitor views the dedicated page that exists for any media attachment.', 'gutenberg' ), + ); + } + if ( isset( $default_template_types['search'] ) ) { + $default_template_types['search'] = array( + 'title' => _x( 'Search Results', 'Template name', 'gutenberg' ), + 'description' => __( 'Displays when a visitor performs a search on your website.', 'gutenberg' ), + ); + } + if ( isset( $default_template_types['privacy-policy'] ) ) { + $default_template_types['privacy-policy'] = array( + 'title' => _x( 'Privacy Policy', 'Template name', 'gutenberg' ), + 'description' => __( + "Displays your site's Privacy Policy page.", + 'gutenberg' + ), + ); + } + if ( isset( $default_template_types['404'] ) ) { + $default_template_types['404'] = array( + 'title' => _x( 'Page: 404', 'Template name', 'gutenberg' ), + 'description' => __( 'Displays when a visitor views a non-existent page, such as a dead link or a mistyped URL.', 'gutenberg' ), + ); + } + + return $default_template_types; +} +add_filter( 'default_template_types', 'gutenberg_get_default_block_template_types', 10 ); diff --git a/lib/load.php b/lib/load.php index 0fd23fc28f5133..3e5678d280138c 100644 --- a/lib/load.php +++ b/lib/load.php @@ -80,9 +80,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.2/widgets.php'; require __DIR__ . '/compat/wordpress-6.2/menu.php'; -// WordPress 6.3 compat. -require __DIR__ . '/compat/wordpress-6.3/get-global-styles-and-settings.php'; - if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) { require __DIR__ . '/compat/wordpress-6.2/html-api/class-wp-html-attribute-token.php'; require __DIR__ . '/compat/wordpress-6.2/html-api/class-wp-html-span.php'; @@ -91,6 +88,8 @@ function gutenberg_is_experiment_enabled( $name ) { } // WordPress 6.3 compat. +require __DIR__ . '/compat/wordpress-6.3/get-global-styles-and-settings.php'; +require __DIR__ . '/compat/wordpress-6.3/block-template-utils.php'; require __DIR__ . '/compat/wordpress-6.3/html-api/class-gutenberg-html-tag-processor-6-3.php'; require __DIR__ . '/compat/wordpress-6.3/script-loader.php'; require __DIR__ . '/compat/wordpress-6.3/blocks.php'; diff --git a/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js b/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js index 9d395707e382f3..3a561ad1e2cb6c 100644 --- a/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js +++ b/packages/e2e-tests/specs/experiments/blocks/post-comments-form.test.js @@ -37,7 +37,7 @@ describe( 'Post Comments Form', () => { ); await expect( page ).toClick( '.edit-site-sidebar-navigation-item', - { text: /singular/i } + { text: /single entries/i } ); await enterEditMode(); diff --git a/packages/e2e-tests/specs/site-editor/settings-sidebar.test.js b/packages/e2e-tests/specs/site-editor/settings-sidebar.test.js index ae28019cf0d992..8bd33d7138fc95 100644 --- a/packages/e2e-tests/specs/site-editor/settings-sidebar.test.js +++ b/packages/e2e-tests/specs/site-editor/settings-sidebar.test.js @@ -79,7 +79,7 @@ describe( 'Settings sidebar', () => { 'Used as a fallback template for all pages when a more specific template is not defined.', } ); expect( templateCardAfterNavigation ).toMatchObject( { - title: 'Singular', + title: 'Single Entries', description: 'Displays any single entry, such as a post or a page. This template will serve as a fallback when a more specific template (e.g., Single Post, Page, or Attachment) cannot be found.', } ); diff --git a/test/e2e/specs/editor/various/post-editor-template-mode.spec.js b/test/e2e/specs/editor/various/post-editor-template-mode.spec.js index 9bbecb51223fc0..85bf4d3a65ceb7 100644 --- a/test/e2e/specs/editor/various/post-editor-template-mode.spec.js +++ b/test/e2e/specs/editor/various/post-editor-template-mode.spec.js @@ -151,7 +151,7 @@ class PostEditorTemplateMode { await expect( this.editorTopBar.getByRole( 'heading[level=1]' ) - ).toHaveText( 'Editing template: Singular' ); + ).toHaveText( 'Editing template: Single Entries' ); } async createPostAndSaveDraft() { From eb2f0ed4577a18f109cd7abd2ae363c2dd6f70c7 Mon Sep 17 00:00:00 2001 From: James Koster Date: Tue, 27 Jun 2023 11:39:41 +0100 Subject: [PATCH 6/9] Update text color (#51965) --- .../edit-site/src/components/sidebar-navigation-item/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-site/src/components/sidebar-navigation-item/style.scss b/packages/edit-site/src/components/sidebar-navigation-item/style.scss index d032bece171075..d81b6764f7b721 100644 --- a/packages/edit-site/src/components/sidebar-navigation-item/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-item/style.scss @@ -15,6 +15,7 @@ &[aria-current] { background: var(--wp-admin-theme-color); + color: $white; } .edit-site-sidebar-navigation-item__drilldown-indicator { From 4f3599df907555e7d3fdb3f91cf1b9b4b9a541b5 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 27 Jun 2023 17:58:00 +0900 Subject: [PATCH 7/9] Modal: Add small top padding to the content so that avoid cutting off the visible outline when hovering items (#51829) * Site Editor: Fix focus cutoff in add template modal * Add padding-top to the modal content * Remove unnecessary padding-top * Remove unnecessary padding-top * Update changelog * Revert top padding from block patterns list * Revert top padding from block patterns list * Remove unnecessary changes * Remove unnecessary changes * Add CSS inline comment * Change padding metrics --- packages/components/CHANGELOG.md | 1 + packages/components/src/modal/style.scss | 5 +++-- .../edit-post/src/components/start-page-options/style.scss | 3 --- .../sidebar-navigation-screen-navigation-menu/style.scss | 5 ----- .../src/components/start-template-options/style.scss | 3 --- 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 01db98978c1088..6409ce7515646f 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -18,6 +18,7 @@ - `Autocomplete`: Announce how many results are available to screen readers when suggestions list first renders ([#51018](https://github.com/WordPress/gutenberg/pull/51018)). - `ConfirmDialog`: Ensure onConfirm isn't called an extra time when submitting one of the buttons using the keyboard ([#51730](https://github.com/WordPress/gutenberg/pull/51730)). - `ZStack`: ZStack: fix component bounding box to match children ([#51836](https://github.com/WordPress/gutenberg/pull/51836)). +- `Modal`: Add small top padding to the content so that avoid cutting off the visible outline when hovering items ([#51829](https://github.com/WordPress/gutenberg/pull/51829)). ### Internal diff --git a/packages/components/src/modal/style.scss b/packages/components/src/modal/style.scss index 4c210022b8bb6c..d4ca7c311fcf19 100644 --- a/packages/components/src/modal/style.scss +++ b/packages/components/src/modal/style.scss @@ -72,7 +72,7 @@ .components-modal__header { box-sizing: border-box; border-bottom: $border-width solid transparent; - padding: $grid-unit-30 $grid-unit-40 $grid-unit-15; + padding: $grid-unit-30 $grid-unit-40 $grid-unit-10; display: flex; flex-direction: row; justify-content: space-between; @@ -130,7 +130,8 @@ .components-modal__content { flex: 1; margin-top: $header-height + $grid-unit-15; - padding: 0 $grid-unit-40 $grid-unit-40; + // Small top padding required to avoid cutting off the visible outline when the first child element is focusable. + padding: $grid-unit-05 $grid-unit-40 $grid-unit-40; overflow: auto; &.hide-header { diff --git a/packages/edit-post/src/components/start-page-options/style.scss b/packages/edit-post/src/components/start-page-options/style.scss index 0e26c93e386374..52f3f5ff9a8889 100644 --- a/packages/edit-post/src/components/start-page-options/style.scss +++ b/packages/edit-post/src/components/start-page-options/style.scss @@ -3,9 +3,6 @@ column-count: 2; column-gap: $grid-unit-30; - // Small top padding required to avoid cutting off the visible outline when hovering items - padding-top: $border-width-focus-fallback; - @include break-medium() { column-count: 3; } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/style.scss index ae35cb4525b88b..012622f9b1040b 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/style.scss +++ b/packages/edit-site/src/components/sidebar-navigation-screen-navigation-menu/style.scss @@ -8,8 +8,3 @@ } } } - -.sidebar-navigation__rename-modal-form { - // Fix for input focus style being cut off by the modal. - padding-top: 1px; -} diff --git a/packages/edit-site/src/components/start-template-options/style.scss b/packages/edit-site/src/components/start-template-options/style.scss index 7515861099b380..53cd38a8c9bfad 100644 --- a/packages/edit-site/src/components/start-template-options/style.scss +++ b/packages/edit-site/src/components/start-template-options/style.scss @@ -29,9 +29,6 @@ $actions-height: 92px; column-count: 2; column-gap: $grid-unit-30; - // Small top padding required to avoid cutting off the visible outline when hovering items - padding-top: $border-width-focus-fallback; - @include break-medium() { column-count: 3; } From 51c953b871233e5f6ff9c3f7e3f6cd353913b9c8 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 27 Jun 2023 19:24:39 +1000 Subject: [PATCH 8/9] Rest API: rename navigation fallback classes from WP_ to Gutenberg_ (#51959) * The `WP_REST_Navigation_Fallback_Controller` class has been committed to core and therefore results in a naming conflict and unit test failures. Ideally `WP_REST_Navigation_Fallback_Controller` should have been named `WP_REST_Navigation_Fallback_Controller_Gutenberg` and extended `WP_REST_Navigation_Fallback_Controller`. But we can conditionally load the file instead. * Renamed WP_Classic_To_Block_Menu_Converter to Gutenberg_Classic_To_Block_Menu_Converter Load WP_REST_Navigation_Fallback_Controller dependencies in load.php * Renamed all 6.3 classes to have the Gutenberg_ prefix. This should avoid compat errors and hopefully some confusion later. * Also rename test files for completeness * Updated deprecation notices to refer to Gutenberg classes --- ...nberg-classic-to-block-menu-converter.php} | 4 +-- ...> class-gutenberg-navigation-fallback.php} | 11 ++----- ...g-rest-navigation-fallback-controller.php} | 11 ++----- lib/compat/wordpress-6.3/rest-api.php | 10 +++++++ lib/experimental/rest-api.php | 10 ------- lib/load.php | 4 ++- ...-classic-to-block-menu-converter-test.php} | 16 +++++----- ...rg-navigation-fallback-gutenberg-test.php} | 30 +++++++++---------- ...t-navigation-fallback-controller-test.php} | 4 +-- 9 files changed, 46 insertions(+), 54 deletions(-) rename lib/compat/wordpress-6.3/{class-wp-classic-to-block-menu-converter.php => class-gutenberg-classic-to-block-menu-converter.php} (97%) rename lib/compat/wordpress-6.3/{class-wp-navigation-fallback-gutenberg.php => class-gutenberg-navigation-fallback.php} (95%) rename lib/compat/wordpress-6.3/{class-wp-rest-navigation-fallback-controller.php => class-gutenberg-rest-navigation-fallback-controller.php} (94%) rename phpunit/{class-wp-classic-to-block-menu-converter-test.php => class-gutenberg-classic-to-block-menu-converter-test.php} (90%) rename phpunit/{class-wp-navigation-fallback-gutenberg-test.php => class-gutenberg-navigation-fallback-gutenberg-test.php} (91%) rename phpunit/{class-wp-rest-navigation-fallback-controller-test.php => class-gutenberg-rest-navigation-fallback-controller-test.php} (96%) diff --git a/lib/compat/wordpress-6.3/class-wp-classic-to-block-menu-converter.php b/lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php similarity index 97% rename from lib/compat/wordpress-6.3/class-wp-classic-to-block-menu-converter.php rename to lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php index 65c8a6d5bcba74..8677f9abaee170 100644 --- a/lib/compat/wordpress-6.3/class-wp-classic-to-block-menu-converter.php +++ b/lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php @@ -1,6 +1,6 @@ 404 ) ) ); diff --git a/lib/compat/wordpress-6.3/rest-api.php b/lib/compat/wordpress-6.3/rest-api.php index ed6832c3b84119..5a6860ee799c8c 100644 --- a/lib/compat/wordpress-6.3/rest-api.php +++ b/lib/compat/wordpress-6.3/rest-api.php @@ -110,3 +110,13 @@ function gutenberg_register_rest_block_patterns() { $block_patterns->register_routes(); } add_action( 'rest_api_init', 'gutenberg_register_rest_block_patterns' ); + + +/** + * Registers the Navigation Fallbacks REST API routes. + */ +function gutenberg_register_rest_navigation_fallbacks() { + $editor_settings = new Gutenberg_REST_Navigation_Fallback_Controller(); + $editor_settings->register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_rest_navigation_fallbacks' ); diff --git a/lib/experimental/rest-api.php b/lib/experimental/rest-api.php index 4eca4232d3eb57..77f7d091d2655d 100644 --- a/lib/experimental/rest-api.php +++ b/lib/experimental/rest-api.php @@ -29,16 +29,6 @@ function gutenberg_register_block_editor_settings() { add_action( 'rest_api_init', 'gutenberg_register_block_editor_settings' ); -/** - * Registers the Navigation Fallbacks REST API routes. - */ -function gutenberg_register_rest_navigation_fallbacks() { - $editor_settings = new WP_REST_Navigation_Fallback_Controller(); - $editor_settings->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_navigation_fallbacks' ); - - /** * Shim for get_sample_permalink() to add support for auto-draft status. * diff --git a/lib/load.php b/lib/load.php index 3e5678d280138c..1af8177e044841 100644 --- a/lib/load.php +++ b/lib/load.php @@ -48,7 +48,9 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-rest-templates-controller-6-3.php'; require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php'; require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-rest-global-styles-revisions-controller-6-3.php'; - require_once __DIR__ . '/compat/wordpress-6.3/class-wp-rest-navigation-fallback-controller.php'; + require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php'; + require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-navigation-fallback.php'; + require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-rest-navigation-fallback-controller.php'; require_once __DIR__ . '/compat/wordpress-6.3/rest-api.php'; require_once __DIR__ . '/compat/wordpress-6.3/theme-previews.php'; require_once __DIR__ . '/compat/wordpress-6.3/navigation-block-preloading.php'; diff --git a/phpunit/class-wp-classic-to-block-menu-converter-test.php b/phpunit/class-gutenberg-classic-to-block-menu-converter-test.php similarity index 90% rename from phpunit/class-wp-classic-to-block-menu-converter-test.php rename to phpunit/class-gutenberg-classic-to-block-menu-converter-test.php index 0d7670d8ec867e..5f0a8ceee52a10 100644 --- a/phpunit/class-wp-classic-to-block-menu-converter-test.php +++ b/phpunit/class-gutenberg-classic-to-block-menu-converter-test.php @@ -1,20 +1,20 @@ assertTrue( class_exists( 'WP_Classic_To_Block_Menu_Converter' ) ); + $this->assertTrue( class_exists( 'Gutenberg_Classic_To_Block_Menu_Converter' ) ); } /** @@ -23,7 +23,7 @@ public function test_class_exists() { */ public function test_passing_non_menu_object_to_converter_returns_wp_error( $data ) { - $result = WP_Classic_To_Block_Menu_Converter::convert( $data ); + $result = Gutenberg_Classic_To_Block_Menu_Converter::convert( $data ); $this->assertTrue( is_wp_error( $result ), 'Should be a WP_Error instance' ); @@ -88,7 +88,7 @@ public function test_can_convert_classic_menu_to_blocks() { $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - $blocks = WP_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); + $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); $this->assertNotEmpty( $blocks ); @@ -179,7 +179,7 @@ public function test_does_not_convert_menu_items_with_non_publish_status() { $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - $blocks = WP_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); + $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); $this->assertNotEmpty( $blocks ); @@ -204,7 +204,7 @@ public function test_returns_empty_array_for_menus_with_no_items() { $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - $blocks = WP_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); + $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); $this->assertEmpty( $blocks, 'Result should be empty.' ); diff --git a/phpunit/class-wp-navigation-fallback-gutenberg-test.php b/phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php similarity index 91% rename from phpunit/class-wp-navigation-fallback-gutenberg-test.php rename to phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php index fe32e8a640c078..7b0719950df8b5 100644 --- a/phpunit/class-wp-navigation-fallback-gutenberg-test.php +++ b/phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php @@ -1,14 +1,14 @@ assertTrue( class_exists( 'WP_Navigation_Fallback_Gutenberg' ), 'WP_Navigation_Fallback_Gutenberg class should exist.' ); + $this->assertTrue( class_exists( 'Gutenberg_Navigation_Fallback' ), 'Gutenberg_Navigation_Fallback class should exist.' ); } @@ -37,7 +37,7 @@ public function test_it_exists() { * @covers WP_REST_Navigation_Fallback_Controller::get_fallback */ public function test_should_return_a_default_fallback_navigation_menu_in_absence_of_other_fallbacks() { - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -63,7 +63,7 @@ public function test_should_return_a_default_fallback_navigation_menu_with_no_bl unregister_block_type( 'core/page-list' ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -79,11 +79,11 @@ public function test_should_return_a_default_fallback_navigation_menu_with_no_bl */ public function test_should_handle_consecutive_invocations() { // Invoke the method multiple times to ensure that it doesn't create a new fallback menu on each invocation. - WP_Navigation_Fallback_Gutenberg::get_fallback(); - WP_Navigation_Fallback_Gutenberg::get_fallback(); + Gutenberg_Navigation_Fallback::get_fallback(); + Gutenberg_Navigation_Fallback::get_fallback(); // Assert on the final invocation. - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -115,7 +115,7 @@ public function test_should_return_the_most_recently_created_navigation_menu() { ) ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -147,7 +147,7 @@ public function test_should_return_fallback_navigation_from_existing_classic_men ) ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -201,7 +201,7 @@ public function test_should_prioritise_fallback_to_classic_menu_in_primary_locat $locations['header'] = $another_menu_id; set_theme_mod( 'nav_menu_locations', $locations ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -238,7 +238,7 @@ public function test_should_fallback_to_classic_menu_with_primary_slug() { ) ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -275,7 +275,7 @@ public function test_should_fallback_to_most_recently_created_classic_menu() { ) ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); @@ -306,7 +306,7 @@ public function test_should_not_create_fallback_from_classic_menu_if_a_navigatio ) ); - $data = WP_Navigation_Fallback_Gutenberg::get_fallback(); + $data = Gutenberg_Navigation_Fallback::get_fallback(); $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); diff --git a/phpunit/class-wp-rest-navigation-fallback-controller-test.php b/phpunit/class-gutenberg-rest-navigation-fallback-controller-test.php similarity index 96% rename from phpunit/class-wp-rest-navigation-fallback-controller-test.php rename to phpunit/class-gutenberg-rest-navigation-fallback-controller-test.php index 1cdedb568a5cd7..14ab8ee0971dd9 100644 --- a/phpunit/class-wp-rest-navigation-fallback-controller-test.php +++ b/phpunit/class-gutenberg-rest-navigation-fallback-controller-test.php @@ -1,6 +1,6 @@ Date: Tue, 27 Jun 2023 15:01:58 +1000 Subject: [PATCH 9/9] Fix phpunit failures (#51950) * Fix phpunit failures * Add comment * Update comment with actual reason this fix works --- phpunit/block-template-utils-test.php | 6 ++---- phpunit/bootstrap.php | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/phpunit/block-template-utils-test.php b/phpunit/block-template-utils-test.php index ac2e4145cd0ed2..08fb0c2c2c1e3b 100644 --- a/phpunit/block-template-utils-test.php +++ b/phpunit/block-template-utils-test.php @@ -9,9 +9,6 @@ class Tests_Block_Template_Utils extends WP_UnitTestCase { public function set_up() { parent::set_up(); switch_theme( 'emptytheme' ); - } - - public static function wpSetUpBeforeClass() { register_post_type( 'custom_book', array( @@ -22,9 +19,10 @@ public static function wpSetUpBeforeClass() { register_taxonomy( 'book_type', 'custom_book' ); } - public static function wpTearDownAfterClass() { + public function tear_down() { unregister_post_type( 'custom_book' ); unregister_taxonomy( 'book_type' ); + parent::tear_down(); } public function test_get_template_hierarchy() { diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index c11233b1e89525..f64e6fa5c7ef14 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -22,6 +22,12 @@ define( 'LOCAL_WP_ENVIRONMENT_TYPE', 'local' ); } +// Pretend that these are Core unit tests. This is needed so that +// wp_theme_has_theme_json() does not cache its return value between each test. +if ( ! defined( 'WP_RUN_CORE_TESTS' ) ) { + define( 'WP_RUN_CORE_TESTS', true ); +} + // Require composer dependencies. require_once dirname( __DIR__ ) . '/vendor/autoload.php';