diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index 06e486739ed74a..a7b8add9dd54fe 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -2,10 +2,11 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { edit } from '@wordpress/icons'; +import { edit, seen } from '@wordpress/icons'; import { useSelect, useDispatch } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { __experimentalNavigatorButton as NavigatorButton } from '@wordpress/components'; +import { useViewportMatch } from '@wordpress/compose'; /** * Internal dependencies @@ -16,6 +17,7 @@ import { unlock } from '../../private-apis'; import { store as editSiteStore } from '../../store'; import SidebarButton from '../sidebar-button'; import SidebarNavigationItem from '../sidebar-navigation-item'; +import StyleBook from '../style-book'; export function SidebarNavigationItemGlobalStyles( props ) { const { openGeneralSidebar } = useDispatch( editSiteStore ); @@ -51,26 +53,74 @@ export function SidebarNavigationItemGlobalStyles( props ) { export default function SidebarNavigationScreenGlobalStyles() { const { openGeneralSidebar } = useDispatch( editSiteStore ); - const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); + const isMobileViewport = useViewportMatch( 'medium', '<' ); + const { setCanvasMode, setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); + + const isStyleBookOpened = useSelect( + ( select ) => + 'style-book' === + unlock( select( editSiteStore ) ).getEditorCanvasContainerView(), + [] + ); + + const openGlobalStyles = async () => + Promise.all( [ + setCanvasMode( 'edit' ), + openGeneralSidebar( 'edit-site/global-styles' ), + ] ); + + const openStyleBook = async () => { + await openGlobalStyles(); + // Open the Style Book once the canvas mode is set to edit, + // and the global styles sidebar is open. This ensures that + // the Style Book is not prematurely closed. + setEditorCanvasContainerView( 'style-book' ); + }; + return ( - } - actions={ - { - // switch to edit mode. - setCanvasMode( 'edit' ); - // open global styles sidebar. - openGeneralSidebar( 'edit-site/global-styles' ); - } } + <> + } + actions={ +
+ { ! isMobileViewport && ( + + setEditorCanvasContainerView( + ! isStyleBookOpened + ? 'style-book' + : undefined + ) + } + isPressed={ isStyleBookOpened } + /> + ) } + await openGlobalStyles() } + /> +
+ } + /> + { isStyleBookOpened && ! isMobileViewport && ( + false } + onClick={ openStyleBook } + onSelect={ openStyleBook } + showCloseButton={ false } + showTabs={ false } /> - } - /> + ) } + ); } diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js index 7c9e4b3bf91968..7ad0dc07ae0f0e 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-main/index.js @@ -7,8 +7,9 @@ import { } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { layout, symbol, navigation, styles, page } from '@wordpress/icons'; -import { useSelect } from '@wordpress/data'; +import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies @@ -16,6 +17,8 @@ import { store as coreStore } from '@wordpress/core-data'; import SidebarNavigationScreen from '../sidebar-navigation-screen'; import SidebarNavigationItem from '../sidebar-navigation-item'; import { SidebarNavigationItemGlobalStyles } from '../sidebar-navigation-screen-global-styles'; +import { unlock } from '../../private-apis'; +import { store as editSiteStore } from '../../store'; export default function SidebarNavigationScreenMain() { const hasNavigationMenus = useSelect( ( select ) => { @@ -36,6 +39,22 @@ export default function SidebarNavigationScreenMain() { const showNavigationScreen = process.env.IS_GUTENBERG_PLUGIN ? hasNavigationMenus : false; + + const editorCanvasContainerView = useSelect( ( select ) => { + return unlock( select( editSiteStore ) ).getEditorCanvasContainerView(); + }, [] ); + + const { setEditorCanvasContainerView } = unlock( + useDispatch( editSiteStore ) + ); + + // Clear the editor canvas container view when accessing the main navigation screen. + useEffect( () => { + if ( editorCanvasContainerView ) { + setEditorCanvasContainerView( undefined ); + } + }, [ editorCanvasContainerView, setEditorCanvasContainerView ] ); + return (
600, + 'is-button': !! onClick, } ) } style={ { color: textColor, @@ -206,53 +218,125 @@ function StyleBook( { isSelected, onSelect } ) { } } > { resizeObserver } - - { ( tab ) => ( - - ) } - + ) } + + ) : ( + + ) }
); } +const StyleBookBody = ( { + category, + examples, + isSelected, + onClick, + onSelect, + settings, + sizes, + title, +} ) => { + const [ isFocused, setIsFocused ] = useState( false ); + + // The presence of an `onClick` prop indicates that the Style Book is being used as a button. + // In this case, add additional props to the iframe to make it behave like a button. + const buttonModeProps = { + role: 'button', + onFocus: () => setIsFocused( true ), + onBlur: () => setIsFocused( false ), + onKeyDown: ( event ) => { + if ( event.defaultPrevented ) { + return; + } + const { keyCode } = event; + if ( onClick && ( keyCode === ENTER || keyCode === SPACE ) ) { + event.preventDefault(); + onClick( event ); + } + }, + onClick: ( event ) => { + if ( event.defaultPrevented ) { + return; + } + if ( onClick ) { + event.preventDefault(); + onClick( event ); + } + }, + readonly: true, + }; + + const buttonModeStyles = onClick + ? 'body { cursor: pointer; } body * { pointer-events: none; }' + : ''; + + return ( + + ); +}; + const Examples = memo( ( { className, examples, category, label, isSelected, onSelect } ) => { const composite = useCompositeState( { orientation: 'vertical' } ); @@ -263,7 +347,9 @@ const Examples = memo( aria-label={ label } > { examples - .filter( ( example ) => example.category === category ) + .filter( ( example ) => + category ? example.category === category : true + ) .map( ( example ) => ( { - onSelect( example.name ); + onSelect?.( example.name ); } } /> ) ) } diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss index 6dcc1fec328abc..0ddefb055a8d8d 100644 --- a/packages/edit-site/src/components/style-book/style.scss +++ b/packages/edit-site/src/components/style-book/style.scss @@ -1,3 +1,22 @@ +.edit-site-style-book { + // Ensure the style book fills the available vertical space. + // This is useful when the style book is used to fill a frame. + height: 100%; + &.is-button { + border-radius: $radius-block-ui * 4; + } +} + +.edit-site-style-book__iframe { + &.is-button { + border-radius: $radius-block-ui * 4; + } + &.is-focused { + outline: calc(2 * var(--wp-admin-border-width-focus)) solid var(--wp-admin-theme-color); + outline-offset: calc(-2 * var(--wp-admin-border-width-focus)); + } +} + .edit-site-style-book__tab-panel { .components-tab-panel__tabs { background: $white;