diff --git a/packages/block-editor/src/components/block-switcher/style.scss b/packages/block-editor/src/components/block-switcher/style.scss index c6acd359abd2fb..8a2d6cfccdfe2d 100644 --- a/packages/block-editor/src/components/block-switcher/style.scss +++ b/packages/block-editor/src/components/block-switcher/style.scss @@ -89,7 +89,7 @@ } } // We double the max-width for it to fit both the preview & content but we keep the min width the same for the border to work. -.components-popover:not(.is-mobile).block-editor-block-switcher__popover .components-popover__content { +.components-popover.block-editor-block-switcher__popover .components-popover__content { min-width: 300px; max-width: calc(340px * 2); display: flex; diff --git a/packages/block-editor/src/components/inserter/style.scss b/packages/block-editor/src/components/inserter/style.scss index 275091342cf4d4..528c46adb87d75 100644 --- a/packages/block-editor/src/components/inserter/style.scss +++ b/packages/block-editor/src/components/inserter/style.scss @@ -16,7 +16,7 @@ $block-inserter-search-height: 38px; } } -.block-editor-inserter__popover:not(.is-mobile) > .components-popover__content { +.block-editor-inserter__popover > .components-popover__content { @include break-medium { overflow-y: visible; height: $block-inserter-content-height + $block-inserter-tabs-height + $block-inserter-search-height; diff --git a/packages/block-library/src/navigation-link/editor.scss b/packages/block-library/src/navigation-link/editor.scss index 879b231452043c..d1ed945a92ff5c 100644 --- a/packages/block-library/src/navigation-link/editor.scss +++ b/packages/block-library/src/navigation-link/editor.scss @@ -94,7 +94,7 @@ } // Popover styles -.components-popover:not(.is-mobile).wp-block-navigation-link__dropdown-content { +.components-popover.wp-block-navigation-link__dropdown-content { margin-top: -1px; margin-left: -4px; } diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 1b96d18430796f..a0562ad1f0263b 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -167,6 +167,55 @@ function useFocusContentOnMount( focusOnMount, contentRef ) { }, [] ); } +/** + * Sets or removes an element attribute. + * + * @param {Element} element The element to modify. + * @param {string} name The attribute name to set or remove. + * @param {?string} value The value to set. A falsy value will remove the + * attribute. + */ +function setAttribute( element, name, value ) { + if ( ! value ) { + if ( element.hasAttribute( name ) ) { + element.removeAttribute( name ); + } + } else if ( element.getAttribute( name ) !== value ) { + element.setAttribute( name, value ); + } +} + +/** + * Sets or removes an element style property. + * + * @param {Element} element The element to modify. + * @param {string} property The property to set or remove. + * @param {?string} value The value to set. A falsy value will remove the + * property. + */ +function setStyle( element, property, value = '' ) { + if ( element.style[ property ] !== value ) { + element.style[ property ] = value; + } +} + +/** + * Sets or removes an element class. + * + * @param {Element} element The element to modify. + * @param {string} name The class to set or remove. + * @param {boolean} toggle True to set the class, false to remove. + */ +function setClass( element, name, toggle ) { + if ( toggle ) { + if ( ! element.classList.contains( name ) ) { + element.classList.add( name ); + } + } else if ( element.classList.contains( name ) ) { + element.classList.remove( name ); + } +} + const Popover = ( { headerTitle, onClose, @@ -198,9 +247,22 @@ const Popover = ( { const containerRef = useRef(); const isMobileViewport = useViewportMatch( 'medium', '<' ); const [ animateOrigin, setAnimateOrigin ] = useState(); + const isExpanded = expandOnMobile && isMobileViewport; + + noArrow = isExpanded || noArrow; useEffect( () => { - if ( isMobileViewport && expandOnMobile ) { + const containerEl = containerRef.current; + const contentEl = contentRef.current; + + if ( isExpanded ) { + setClass( containerEl, 'is-without-arrow', noArrow ); + setAttribute( containerEl, 'data-x-axis' ); + setAttribute( containerEl, 'data-y-axis' ); + setStyle( containerEl, 'top' ); + setStyle( containerEl, 'left' ); + setStyle( contentEl, 'maxHeight' ); + setStyle( contentEl, 'maxWidth' ); return; } @@ -224,8 +286,8 @@ const Popover = ( { ); const contentSize = { - height: contentRef.current.scrollHeight, - width: contentRef.current.scrollWidth, + height: contentEl.scrollHeight, + width: contentEl.scrollWidth, }; const { popoverTop, @@ -236,6 +298,14 @@ const Popover = ( { contentWidth, } = computePopoverPosition( anchor, contentSize, position ); + setClass( containerEl, 'is-without-arrow', noArrow || ( xAxis === 'center' && yAxis === 'middle' ) ); + setAttribute( containerEl, 'data-x-axis', xAxis ); + setAttribute( containerEl, 'data-y-axis', yAxis ); + setStyle( containerEl, 'top', typeof popoverTop === 'number' ? popoverTop + 'px' : '' ); + setStyle( containerEl, 'left', typeof popoverLeft === 'number' ? popoverLeft + 'px' : '' ); + setStyle( contentEl, 'maxHeight', typeof contentHeight === 'number' ? contentHeight + 'px' : '' ); + setStyle( contentEl, 'maxWidth', typeof contentWidth === 'number' ? contentWidth + 'px' : '' ); + // Compute the animation position const yAxisMapping = { top: 'bottom', @@ -248,19 +318,6 @@ const Popover = ( { const animateYAxis = yAxisMapping[ yAxis ] || 'middle'; const animateXAxis = xAxisMapping[ xAxis ] || 'center'; - containerRef.current.setAttribute( 'data-x-axis', xAxis ); - containerRef.current.setAttribute( 'data-y-axis', yAxis ); - containerRef.current.style.top = popoverTop + 'px'; - containerRef.current.style.left = popoverLeft + 'px'; - contentRef.current.style.maxHeight = contentHeight ? contentHeight + 'px' : ''; - contentRef.current.style.maxWidth = contentWidth ? contentWidth + 'px' : ''; - - if ( xAxis === 'center' && yAxis === 'middle' ) { - contentRef.current.classList.add( 'is-without-arrow' ); - } else { - contentRef.current.classList.remove( 'is-without-arrow' ); - } - setAnimateOrigin( animateXAxis + ' ' + animateYAxis ); }; @@ -283,8 +340,7 @@ const Popover = ( { window.removeEventListener( 'scroll', refresh, true ); }; }, [ - isMobileViewport, - expandOnMobile, + isExpanded, anchorRect, getAnchorRect, anchorRef, @@ -367,7 +423,7 @@ const Popover = ( { className, animateClassName, { - 'is-mobile': isMobileViewport && expandOnMobile, + 'is-expanded': isExpanded, 'is-without-arrow': noArrow, } ) } @@ -375,7 +431,7 @@ const Popover = ( { onKeyDown={ maybeClose } ref={ containerRef } > - { isMobileViewport && expandOnMobile && ( + { isExpanded && (