diff --git a/packages/block-editor/src/components/block-preview/README.md b/packages/block-editor/src/components/block-preview/README.md index 0da7348817cd8..6e141fede9104 100644 --- a/packages/block-editor/src/components/block-preview/README.md +++ b/packages/block-editor/src/components/block-preview/README.md @@ -28,6 +28,8 @@ Width of the preview container in pixels. Controls at what size the blocks will `viewportWidth` can be used to simulate how blocks look on different device sizes or to make sure make sure multiple previews will be rendered with the same scale, regardless of their content. +Set `viewportWidth` to `0` to make the viewport the same width as the container. + ### `__experimentalPadding` - **Type** `Int` diff --git a/packages/block-editor/src/components/block-preview/auto.js b/packages/block-editor/src/components/block-preview/auto.js index ddf4ee0ec75ab..54828d3ae64b5 100644 --- a/packages/block-editor/src/components/block-preview/auto.js +++ b/packages/block-editor/src/components/block-preview/auto.js @@ -26,6 +26,10 @@ function ScaledBlockPreview( { __experimentalPadding, __experimentalMinHeight, } ) { + if ( ! viewportWidth ) { + viewportWidth = containerWidth; + } + const [ contentResizeListener, { height: contentHeight } ] = useResizeObserver(); const { styles, assets, duotone } = useSelect( ( select ) => { diff --git a/packages/edit-site/src/components/block-editor/editor-canvas.js b/packages/edit-site/src/components/block-editor/editor-canvas.js new file mode 100644 index 0000000000000..2ab7ee4c66579 --- /dev/null +++ b/packages/edit-site/src/components/block-editor/editor-canvas.js @@ -0,0 +1,69 @@ +/** + * WordPress dependencies + */ +import { + __experimentalUseResizeCanvas as useResizeCanvas, + __unstableEditorStyles as EditorStyles, + __unstableIframe as Iframe, + __unstableUseMouseMoveTypingReset as useMouseMoveTypingReset, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; + +function EditorCanvas( { enableResizing, settings, children, ...props } ) { + const { deviceType, isZoomOutMode } = useSelect( + ( select ) => ( { + deviceType: + select( editSiteStore ).__experimentalGetPreviewDeviceType(), + isZoomOutMode: + select( blockEditorStore ).__unstableGetEditorMode() === + 'zoom-out', + } ), + [] + ); + const deviceStyles = useResizeCanvas( deviceType ); + const mouseMoveTypingRef = useMouseMoveTypingReset(); + return ( + + ); +} + +export default EditorCanvas; diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js index f990ee7f15f69..ea4cf6ef0b764 100644 --- a/packages/edit-site/src/components/block-editor/index.js +++ b/packages/edit-site/src/components/block-editor/index.js @@ -26,7 +26,11 @@ import { store as blockEditorStore, __unstableBlockNameContext, } from '@wordpress/block-editor'; -import { useMergeRefs, useViewportMatch } from '@wordpress/compose'; +import { + useMergeRefs, + useViewportMatch, + useResizeObserver, +} from '@wordpress/compose'; import { ReusableBlocksMenuItems } from '@wordpress/reusable-blocks'; import { listView } from '@wordpress/icons'; import { ToolbarButton, ToolbarGroup } from '@wordpress/components'; @@ -43,6 +47,8 @@ import { store as editSiteStore } from '../../store'; import BlockInspectorButton from './block-inspector-button'; import BackButton from './back-button'; import ResizableEditor from './resizable-editor'; +import EditorCanvas from './editor-canvas'; +import StyleBook from '../style-book'; const LAYOUT = { type: 'default', @@ -59,10 +65,16 @@ export default function BlockEditor( { setIsInserterOpen } ) { templateId, page, isNavigationSidebarOpen, + canvasMode, } = useSelect( ( select ) => { - const { getSettings, getEditedPostType, getEditedPostId, getPage } = - select( editSiteStore ); + const { + getSettings, + getEditedPostType, + getEditedPostId, + getPage, + __unstableGetCanvasMode, + } = select( editSiteStore ); return { storedSettings: getSettings( setIsInserterOpen ), @@ -73,6 +85,7 @@ export default function BlockEditor( { setIsInserterOpen } ) { select( interfaceStore ).getActiveComplementaryArea( editSiteStore.name ) === NAVIGATION_SIDEBAR_NAME, + canvasMode: __unstableGetCanvasMode(), }; }, [ setIsInserterOpen ] @@ -158,9 +171,15 @@ export default function BlockEditor( { setIsInserterOpen } ) { const mergedRefs = useMergeRefs( [ contentRef, useTypingObserver() ] ); const isMobileViewport = useViewportMatch( 'small', '<' ); const { clearSelectedBlock } = useDispatch( blockEditorStore ); + const [ resizeObserver, sizes ] = useResizeObserver(); const isTemplatePart = templateType === 'wp_template_part'; const hasBlocks = blocks.length !== 0; + const enableResizing = + isTemplatePart && + canvasMode !== 'view' && + // Disable resizing in mobile viewport. + ! isMobileViewport; const NavMenuSidebarToggle = () => ( @@ -211,54 +230,71 @@ export default function BlockEditor( { setIsInserterOpen } ) { - { - // Clear selected block when clicking on the gray background. - if ( event.target === event.currentTarget ) { - clearSelectedBlock(); - } - } } - > - - - - - - <__unstableBlockSettingsMenuFirstItem> - { ( { onClose } ) => ( - - ) } - - <__unstableBlockToolbarLastItem> - <__unstableBlockNameContext.Consumer> - { ( blockName ) => - blockName === 'core/navigation' && ( - - ) - } - - - + + { ( [ styleBook ] ) => + styleBook ? ( +
+ + { styleBook } + +
+ ) : ( + { + // Clear selected block when clicking on the gray background. + if ( event.target === event.currentTarget ) { + clearSelectedBlock(); + } + } } + > + + + + + { resizeObserver } + + + + <__unstableBlockSettingsMenuFirstItem> + { ( { onClose } ) => ( + + ) } + + <__unstableBlockToolbarLastItem> + <__unstableBlockNameContext.Consumer> + { ( blockName ) => + blockName === 'core/navigation' && ( + + ) + } + + + + ) + } +
); diff --git a/packages/edit-site/src/components/block-editor/resizable-editor.js b/packages/edit-site/src/components/block-editor/resizable-editor.js index 6cdf3811f729c..20fdd97252843 100644 --- a/packages/edit-site/src/components/block-editor/resizable-editor.js +++ b/packages/edit-site/src/components/block-editor/resizable-editor.js @@ -3,20 +3,10 @@ */ import { useState, useRef, useCallback } from '@wordpress/element'; import { ResizableBox } from '@wordpress/components'; -import { - __experimentalUseResizeCanvas as useResizeCanvas, - __unstableEditorStyles as EditorStyles, - __unstableIframe as Iframe, - __unstableUseMouseMoveTypingReset as useMouseMoveTypingReset, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { useSelect } from '@wordpress/data'; -import { useMergeRefs, useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../store'; import ResizeHandle from './resize-handle'; // Removes the inline styles in the drag handles. @@ -32,37 +22,22 @@ const HANDLE_STYLES_OVERRIDE = { left: undefined, }; -function ResizableEditor( { enableResizing, settings, children, ...props } ) { - const [ resizeObserver, sizes ] = useResizeObserver(); - const { deviceType, isZoomOutMode, canvasMode } = useSelect( - ( select ) => ( { - deviceType: - select( editSiteStore ).__experimentalGetPreviewDeviceType(), - canvasMode: select( editSiteStore ).__unstableGetCanvasMode(), - isZoomOutMode: - select( blockEditorStore ).__unstableGetEditorMode() === - 'zoom-out', - } ), - [] - ); - const deviceStyles = useResizeCanvas( deviceType ); +function ResizableEditor( { enableResizing, height, children } ) { const [ width, setWidth ] = useState( '100%' ); - const iframeRef = useRef(); - const mouseMoveTypingResetRef = useMouseMoveTypingReset(); - const ref = useMergeRefs( [ iframeRef, mouseMoveTypingResetRef ] ); - const isResizingEnabled = enableResizing && canvasMode !== 'view'; + const resizableRef = useRef(); const resizeWidthBy = useCallback( ( deltaPixels ) => { - if ( iframeRef.current ) { - setWidth( iframeRef.current.offsetWidth + deltaPixels ); + if ( resizableRef.current ) { + setWidth( resizableRef.current.offsetWidth + deltaPixels ); } }, [] ); - return ( { + resizableRef.current = api?.resizable; + } } size={ { - width: isResizingEnabled ? width : '100%', - height: - isResizingEnabled && sizes.height ? sizes.height : '100%', + width: enableResizing ? width : '100%', + height: enableResizing && height ? height : '100%', } } onResizeStop={ ( event, direction, element ) => { setWidth( element.style.width ); @@ -71,10 +46,10 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) { maxWidth="100%" maxHeight="100%" enable={ { - right: isResizingEnabled, - left: isResizingEnabled, + right: enableResizing, + left: enableResizing, } } - showHandle={ isResizingEnabled } + showHandle={ enableResizing } // The editor is centered horizontally, resizing it only // moves half the distance. Hence double the ratio to correctly // align the cursor to the resizer handle. @@ -99,42 +74,7 @@ function ResizableEditor( { enableResizing, settings, children, ...props } ) { right: HANDLE_STYLES_OVERRIDE, } } > - + { children } ); } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 1daf72dbf1a88..8f7fa28e93eee 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -4,6 +4,7 @@ import { __experimentalNavigatorProvider as NavigatorProvider, __experimentalNavigatorScreen as NavigatorScreen, + __experimentalUseNavigator as useNavigator, } from '@wordpress/components'; import { getBlockTypes } from '@wordpress/blocks'; @@ -25,6 +26,7 @@ import ScreenButtonColor from './screen-button-color'; import ScreenLayout from './screen-layout'; import ScreenStyleVariations from './screen-style-variations'; import ScreenBorder from './screen-border'; +import StyleBook from '../style-book'; function GlobalStylesNavigationScreen( { className, ...props } ) { return ( @@ -120,9 +122,23 @@ function ContextScreens( { name } ) { ); } -function GlobalStylesUI() { - const blocks = getBlockTypes(); +function GlobalStylesStyleBook( { onClose } ) { + const navigator = useNavigator(); + return ( + + navigator.location.path.startsWith( '/blocks/' + blockName ) + } + onSelect={ ( blockName ) => + navigator.goTo( '/blocks/' + blockName ) + } + onClose={ onClose } + /> + ); +} +function GlobalStylesUI( { isStyleBookOpened, onCloseStyleBook } ) { + const blocks = getBlockTypes(); return ( ) ) } + + { isStyleBookOpened && ( + + ) } ); } diff --git a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js b/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js index 26ca15e70354b..806808e829059 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js +++ b/packages/edit-site/src/components/sidebar-edit-mode/global-styles-sidebar.js @@ -1,11 +1,18 @@ /** * WordPress dependencies */ -import { DropdownMenu, FlexItem, FlexBlock, Flex } from '@wordpress/components'; +import { + DropdownMenu, + FlexItem, + FlexBlock, + Flex, + Button, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { styles, moreVertical } from '@wordpress/icons'; +import { styles, moreVertical, seen } from '@wordpress/icons'; import { useDispatch } from '@wordpress/data'; import { store as preferencesStore } from '@wordpress/preferences'; +import { useState } from '@wordpress/element'; /** * Internal dependencies @@ -16,24 +23,38 @@ import { GlobalStylesUI, useGlobalStylesReset } from '../global-styles'; export default function GlobalStylesSidebar() { const [ canReset, onReset ] = useGlobalStylesReset(); const { toggle } = useDispatch( preferencesStore ); - + const [ isStyleBookOpened, setIsStyleBookOpened ] = useState( false ); return ( { __( 'Styles' ) } + + + ); +} + +StyleBook.Slot = StyleBookSlot; + +export default StyleBook; diff --git a/packages/edit-site/src/components/style-book/style.scss b/packages/edit-site/src/components/style-book/style.scss new file mode 100644 index 0000000000000..88c20d0f226ac --- /dev/null +++ b/packages/edit-site/src/components/style-book/style.scss @@ -0,0 +1,80 @@ +.edit-site-style-book { + background: $white; // Fallback color, overriden by JavaScript. + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + transition: background 0.3s; // Match .block-editor-iframe__body transition. + + &.has-dark-background { + &, + .edit-site-style-book__tab-panel .components-button, + .edit-site-style-book__example-title { + color: $white; + } + } +} + +.edit-site-style-book__close-button { + position: absolute; + right: $grid-unit-10; + top: $grid-unit-10; +} + +.edit-site-style-book__tab-panel .components-tab-panel__tab-content { + bottom: 0; + left: 0; + overflow: auto; + padding: $grid-unit-40; + position: absolute; + right: 0; + top: $grid-unit-60; // Height of tabs. +} + +.edit-site-style-book__examples { + max-width: 900px; + margin: 0 auto; +} + +.edit-site-style-book__example { + background: none; + border-radius: $radius-block-ui; + border: none; + display: flex; + flex-direction: column; + gap: $grid-unit-50; + margin-bottom: $grid-unit-50; + padding: $grid-unit-20; + width: 100%; + + &:hover { + box-shadow: 0 0 0 1px $gray-300; + } + + &.is-selected { + box-shadow: 0 0 0 1px var(--wp-admin-theme-color); + } + + .edit-site-style-book.is-wide & { + flex-direction: row; + } +} + +.edit-site-style-book__example-title { + color: $gray-700; + font-size: $editor-font-size; + font-weight: 400; + margin: 0; + text-align: left; + + .edit-site-style-book.is-wide & { + margin-top: $grid-unit-40; + text-align: right; + width: 120px; + } +} + +.edit-site-style-book__example-preview { + width: 100%; +} diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss index efc6187a39a6b..9b871cff4f2d5 100644 --- a/packages/edit-site/src/style.scss +++ b/packages/edit-site/src/style.scss @@ -23,6 +23,7 @@ @import "./components/sidebar-navigation-root/style.scss"; @import "./components/sidebar-navigation-title/style.scss"; @import "./components/site-icon/style.scss"; +@import "./components/style-book/style.scss"; html #wpadminbar { display: none; diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 80bdc23994c4b..92bc48c185cc9 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -199,6 +199,7 @@ export { default as rotateLeft } from './library/rotate-left'; export { default as rotateRight } from './library/rotate-right'; export { default as rss } from './library/rss'; export { default as search } from './library/search'; +export { default as seen } from './library/seen'; export { default as separator } from './library/separator'; export { default as settings } from './library/settings'; export { default as shadow } from './library/shadow'; diff --git a/packages/icons/src/library/seen.js b/packages/icons/src/library/seen.js new file mode 100644 index 0000000000000..4bb328271f834 --- /dev/null +++ b/packages/icons/src/library/seen.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const seen = ( + + + +); + +export default seen;