From c79eae46726881be09af2072432c16e8fb0ce0d8 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:08:38 +1300 Subject: [PATCH 01/23] Make sidebar container scroll internally --- .../sidebar-container/postcss/style.pcss | 42 +++++++--- .../blocks/sidebar-container/src/view.js | 83 ++++--------------- 2 files changed, 43 insertions(+), 82 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 20d7aedfb..f7615047d 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -14,6 +14,7 @@ @media (min-width: 1200px) { .wp-block-wporg-sidebar-container { --local--block-end-sidebar--width: 340px; + --local--top-offset: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); position: absolute; top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); @@ -23,32 +24,47 @@ width: var(--local--block-end-sidebar--width); margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); margin-bottom: 0 !important; + padding-top: var(--wp--preset--spacing--20); + + &:not(.is-fixed-sidebar) { + + /* Match width of custom scrollbar when fixed, stops content width changing */ + padding-right: 16px; + } &.is-fixed-sidebar { position: fixed; top: 0; + height: calc(100vh - var(--local--top-offset)); + margin-top: var(--local--top-offset); + overflow-y: scroll; - /* Make the space above the sidebar the same as the height of the local nav. */ - margin-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px) * 2); - } + /* Custom scrollbar so that it can be made visible on hover */ + &::-webkit-scrollbar, + &::-webkit-scrollbar-thumb { + background-color: transparent; + } - &.is-bottom-sidebar { - position: absolute; - } + &:hover::-webkit-scrollbar-thumb { + background-color: var(--wp--preset--color--charcoal-4); + border: 4.5px solid transparent; + background-clip: content-box; + border-radius: 10px; + } - &.is-fixed-sidebar .is-link-to-top, - &.is-bottom-sidebar .is-link-to-top { - display: block; - margin-top: 0; + .is-link-to-top { + display: block; + padding-top: var(--wp--preset--spacing--20); - & a { - color: var(--wp--preset--color--charcoal-4); + & a { + color: var(--wp--preset--color--charcoal-4); + } } } .wp-block-wporg-table-of-contents + .is-link-to-top { border-top: 1px solid var(--wp--preset--color--light-grey-1); - padding-top: var(--wp--preset--spacing--20); + padding-bottom: var(--wp--preset--spacing--20); } } } diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 04f7ff705..fb3d2cde3 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -1,17 +1,14 @@ /** * Fallback values for custom properties match CSS defaults. */ -const globalNavHeight = 90; -const LOCAL_NAV_HEIGHT = getCustomPropValue( '--wp--custom--local-navigation-bar--spacing--height' ) || 60; +const GLOBAL_NAV_HEIGHT = getCustomPropValue( '--wp-global-header-height' ) || 90; const ADMIN_BAR_HEIGHT = parseInt( window.getComputedStyle( document.documentElement ).getPropertyValue( 'margin-top' ), 10 ); -const SPACE_FROM_BOTTOM = getCustomPropValue( '--wp--preset--spacing--edge-space' ) || 80; const SPACE_TO_TOP = getCustomPropValue( '--wp--custom--wporg-sidebar-container--spacing--margin--top' ) || 80; -const FIXED_HEADER_HEIGHT = globalNavHeight + LOCAL_NAV_HEIGHT + ADMIN_BAR_HEIGHT; -const SCROLL_POSITION_TO_FIX = globalNavHeight + SPACE_TO_TOP - LOCAL_NAV_HEIGHT - ADMIN_BAR_HEIGHT; +const SCROLL_POSITION_TO_FIX = GLOBAL_NAV_HEIGHT + SPACE_TO_TOP - ADMIN_BAR_HEIGHT; let container; let mainEl; @@ -36,59 +33,28 @@ function getCustomPropValue( name, element = document.body ) { * Check the position of the sidebar vs the height of the viewport & page * container, and toggle the "bottom" class to position the sidebar without * overlapping the footer. - * - * @return {boolean} True if the sidebar is at the bottom of the page. */ function onScroll() { // Only run the scroll code if the sidebar is floating on a wide screen. - if ( ! mainEl || ! container || ! window.matchMedia( '(min-width: 1200px)' ).matches ) { - return false; + if ( ! window.matchMedia( '(min-width: 1200px)' ).matches ) { + return; } - const scrollPosition = window.scrollY - ADMIN_BAR_HEIGHT; - - if ( ! container.classList.contains( 'is-bottom-sidebar' ) ) { - const footerStart = mainEl.offsetTop + mainEl.offsetHeight; - // The pixel location of the bottom of the sidebar, relative to the top of the page. - const sidebarBottom = scrollPosition + container.offsetHeight + container.offsetTop - ADMIN_BAR_HEIGHT; - - // Is the sidebar bottom crashing into the footer? - if ( footerStart - SPACE_FROM_BOTTOM < sidebarBottom ) { - container.classList.add( 'is-bottom-sidebar' ); - - // Bottom sidebar is absolutely positioned, so we need to set the top relative to the page origin. - // The pixel location of the top of the sidebar, relative to the footer. - const sidebarTop = - footerStart - container.offsetHeight - LOCAL_NAV_HEIGHT * 2 + ADMIN_BAR_HEIGHT - SPACE_FROM_BOTTOM; - container.style.setProperty( 'top', `${ sidebarTop }px` ); - - return true; - } - } else if ( container.getBoundingClientRect().top > LOCAL_NAV_HEIGHT * 2 + ADMIN_BAR_HEIGHT ) { - // If the top of the sidebar is above the top fixing position, switch back to just a fixed sidebar. - container.classList.remove( 'is-bottom-sidebar' ); - container.style.removeProperty( 'top' ); - } + const { scrollY, innerHeight: windowHeight } = window; + // const footerTop = footer.getBoundingClientRect().top; + const scrollPosition = scrollY - ADMIN_BAR_HEIGHT; // Toggle the fixed position based on whether the scrollPosition is greater than the initial gap from the top. container.classList.toggle( 'is-fixed-sidebar', scrollPosition > SCROLL_POSITION_TO_FIX ); - return false; -} + const footerStart = mainEl.offsetTop + mainEl.offsetHeight; -function isSidebarWithinViewport() { - if ( ! container ) { - return false; + // Is footerStart visible in the viewport? + if ( footerStart < scrollPosition + windowHeight ) { + container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); + } else { + container.style.removeProperty( 'height' ); } - // Usable viewport height. - const viewHeight = window.innerHeight - LOCAL_NAV_HEIGHT + ADMIN_BAR_HEIGHT; - // Get the height of the sidebar, plus the top offset and 60px for the - // "Back to top" link, which isn't visible until `is-fixed-sidebar` is - // added, therefore not included in the offsetHeight value. - const sidebarHeight = container.offsetHeight + LOCAL_NAV_HEIGHT + 60; - // If the sidebar is shorter than the view area, apply the class so - // that it's fixed and scrolls with the page content. - return sidebarHeight < viewHeight; } function init() { @@ -109,30 +75,9 @@ function init() { } ); } - if ( isSidebarWithinViewport() ) { + if ( mainEl && container ) { onScroll(); // Run once to avoid footer collisions on load (ex, when linked to #reply-title). window.addEventListener( 'scroll', onScroll ); - - const observer = new window.ResizeObserver( () => { - // If the sidebar is positioned at the bottom and mainEl resizes, - // it will remain fixed at the previous bottom position, leading to a broken page layout. - // In this case manually trigger the scroll handler to reposition. - if ( container.classList.contains( 'is-bottom-sidebar' ) ) { - container.classList.remove( 'is-bottom-sidebar' ); - container.style.removeProperty( 'top' ); - const isBottom = onScroll(); - // After the sidebar is repositioned, also adjusts the scroll position - // to a point where the sidebar is visible. - if ( isBottom ) { - window.scrollTo( { - top: container.offsetTop - FIXED_HEADER_HEIGHT, - behavior: 'instant', - } ); - } - } - } ); - - observer.observe( mainEl ); } // If there is no table of contents, hide the heading. From 1fd41c15478f50d8af98b97ea0ec9251be5d8257 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:43:52 +1300 Subject: [PATCH 02/23] Decouple sidebar container from ToC --- .../sidebar-container/postcss/style.pcss | 2 +- .../blocks/sidebar-container/src/view.js | 14 ----------- .../blocks/table-of-contents/src/block.json | 3 ++- .../blocks/table-of-contents/src/view.js | 24 +++++++++++++++++++ 4 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 mu-plugins/blocks/table-of-contents/src/view.js diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index f7615047d..76e8658ab 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -62,7 +62,7 @@ } } - .wp-block-wporg-table-of-contents + .is-link-to-top { + * + .is-link-to-top { border-top: 1px solid var(--wp--preset--color--light-grey-1); padding-bottom: var(--wp--preset--spacing--20); } diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index fb3d2cde3..7ac7d4243 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -60,20 +60,6 @@ function onScroll() { function init() { container = document.querySelector( '.wp-block-wporg-sidebar-container' ); mainEl = document.getElementById( 'wp--skip-link--target' ); - const toggleButton = container?.querySelector( '.wporg-table-of-contents__toggle' ); - const list = container?.querySelector( '.wporg-table-of-contents__list' ); - - if ( toggleButton && list ) { - toggleButton.addEventListener( 'click', function () { - if ( toggleButton.getAttribute( 'aria-expanded' ) === 'true' ) { - toggleButton.setAttribute( 'aria-expanded', false ); - list.removeAttribute( 'style' ); - } else { - toggleButton.setAttribute( 'aria-expanded', true ); - list.setAttribute( 'style', 'display:block;' ); - } - } ); - } if ( mainEl && container ) { onScroll(); // Run once to avoid footer collisions on load (ex, when linked to #reply-title). diff --git a/mu-plugins/blocks/table-of-contents/src/block.json b/mu-plugins/blocks/table-of-contents/src/block.json index 5cfe99478..77e164600 100644 --- a/mu-plugins/blocks/table-of-contents/src/block.json +++ b/mu-plugins/blocks/table-of-contents/src/block.json @@ -26,5 +26,6 @@ } }, "editorScript": "file:./index.js", - "style": "file:./style.css" + "style": "file:./style.css", + "viewScript": "file:./view.js" } diff --git a/mu-plugins/blocks/table-of-contents/src/view.js b/mu-plugins/blocks/table-of-contents/src/view.js new file mode 100644 index 000000000..67ac55992 --- /dev/null +++ b/mu-plugins/blocks/table-of-contents/src/view.js @@ -0,0 +1,24 @@ +function init() { + const container = document.querySelector( '.wp-block-wporg-table-of-contents' ); + + if ( ! container ) { + return; + } + + const toggleButton = container.querySelector( '.wporg-table-of-contents__toggle' ); + const list = container.querySelector( '.wporg-table-of-contents__list' ); + + if ( toggleButton && list ) { + toggleButton.addEventListener( 'click', function () { + if ( toggleButton.getAttribute( 'aria-expanded' ) === 'true' ) { + toggleButton.setAttribute( 'aria-expanded', false ); + list.removeAttribute( 'style' ); + } else { + toggleButton.setAttribute( 'aria-expanded', true ); + list.setAttribute( 'style', 'display:block;' ); + } + } ); + } +} + +window.addEventListener( 'load', init ); From b05e9334a55aa4fe679cc08f39bb28e5c7dee662 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:01:40 +1300 Subject: [PATCH 03/23] Allow multiple sidebar containers --- .../sidebar-container/postcss/style.pcss | 16 ++++++++++------ .../blocks/sidebar-container/src/view.js | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 76e8658ab..fbc148aa4 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -16,15 +16,19 @@ --local--block-end-sidebar--width: 340px; --local--top-offset: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); - position: absolute; - top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); - - /* Right offset should be "edge spacing" at minimum, otherwise calculate it to be centered. */ - right: max(var(--wp--preset--spacing--edge-space), calc((100% - var(--wp--style--global--wide-size)) / 2)); width: var(--local--block-end-sidebar--width); - margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); margin-bottom: 0 !important; padding-top: var(--wp--preset--spacing--20); + background: red; + + main & { + position: absolute; + top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); + margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); + + /* Right offset should be "edge spacing" at minimum, otherwise calculate it to be centered. */ + right: max(var(--wp--preset--spacing--edge-space), calc((100% - var(--wp--style--global--wide-size)) / 2)); + } &:not(.is-fixed-sidebar) { diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 7ac7d4243..27198b1f5 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -10,7 +10,7 @@ const ADMIN_BAR_HEIGHT = parseInt( const SPACE_TO_TOP = getCustomPropValue( '--wp--custom--wporg-sidebar-container--spacing--margin--top' ) || 80; const SCROLL_POSITION_TO_FIX = GLOBAL_NAV_HEIGHT + SPACE_TO_TOP - ADMIN_BAR_HEIGHT; -let container; +let containers; let mainEl; /** @@ -45,23 +45,29 @@ function onScroll() { const scrollPosition = scrollY - ADMIN_BAR_HEIGHT; // Toggle the fixed position based on whether the scrollPosition is greater than the initial gap from the top. - container.classList.toggle( 'is-fixed-sidebar', scrollPosition > SCROLL_POSITION_TO_FIX ); + containers.forEach( ( container ) => { + container.classList.toggle( 'is-fixed-sidebar', scrollPosition > SCROLL_POSITION_TO_FIX ); + } ); const footerStart = mainEl.offsetTop + mainEl.offsetHeight; // Is footerStart visible in the viewport? if ( footerStart < scrollPosition + windowHeight ) { - container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); + containers.forEach( ( container ) => { + container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); + } ); } else { - container.style.removeProperty( 'height' ); + containers.forEach( ( container ) => { + container.style.removeProperty( 'height' ); + } ); } } function init() { - container = document.querySelector( '.wp-block-wporg-sidebar-container' ); + containers = document.querySelectorAll( '.wp-block-wporg-sidebar-container' ); mainEl = document.getElementById( 'wp--skip-link--target' ); - if ( mainEl && container ) { + if ( mainEl && containers.length ) { onScroll(); // Run once to avoid footer collisions on load (ex, when linked to #reply-title). window.addEventListener( 'scroll', onScroll ); } From 769f18eb64a98e67d0525274bd0e862616ea9fe8 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:06:20 +1300 Subject: [PATCH 04/23] Remove debug color --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 1 - 1 file changed, 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index fbc148aa4..c9e1b45cc 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -19,7 +19,6 @@ width: var(--local--block-end-sidebar--width); margin-bottom: 0 !important; padding-top: var(--wp--preset--spacing--20); - background: red; main & { position: absolute; From 49d1facbe9b5b7ebc4d326148b0472e0f5c9e1f7 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:15:37 +1300 Subject: [PATCH 05/23] Make back to top link optional --- mu-plugins/blocks/sidebar-container/index.php | 10 ++++++---- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 3 +-- mu-plugins/blocks/sidebar-container/src/block.json | 7 ++++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/index.php b/mu-plugins/blocks/sidebar-container/index.php index 248c386b2..08edf085d 100644 --- a/mu-plugins/blocks/sidebar-container/index.php +++ b/mu-plugins/blocks/sidebar-container/index.php @@ -39,10 +39,12 @@ function init() { * @return string Returns the block markup. */ function render( $attributes, $content, $block ) { - $back_to_top = sprintf( - '', - esc_html__( '↑ Back to top', 'wporg' ) - ); + $back_to_top = $attributes['hasBackToTop'] + ? sprintf( + '', + esc_html__( '↑ Back to top', 'wporg' ) + ) + : ''; $wrapper_attributes = get_block_wrapper_attributes(); return sprintf( diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index c9e1b45cc..b1a05dd91 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -18,7 +18,7 @@ width: var(--local--block-end-sidebar--width); margin-bottom: 0 !important; - padding-top: var(--wp--preset--spacing--20); + padding: var(--wp--preset--spacing--20) 0; main & { position: absolute; @@ -67,7 +67,6 @@ * + .is-link-to-top { border-top: 1px solid var(--wp--preset--color--light-grey-1); - padding-bottom: var(--wp--preset--spacing--20); } } } diff --git a/mu-plugins/blocks/sidebar-container/src/block.json b/mu-plugins/blocks/sidebar-container/src/block.json index 90d9b5ede..c07a7574d 100644 --- a/mu-plugins/blocks/sidebar-container/src/block.json +++ b/mu-plugins/blocks/sidebar-container/src/block.json @@ -7,7 +7,12 @@ "category": "layout", "description": "A sticky container to be used in 2-column layouts.", "textdomain": "wporg", - "attributes": {}, + "attributes": { + "hasBackToTop": { + "type": "boolean", + "default": true + } + }, "supports": { "inserter": false, "__experimentalLayout": true, From 0eb7deac7d84f20fc5296503d1d266b3f9bcba22 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:17:33 +1300 Subject: [PATCH 06/23] Update docs --- mu-plugins/blocks/sidebar-container/src/view.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 27198b1f5..1274c42bc 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -30,9 +30,9 @@ function getCustomPropValue( name, element = document.body ) { } /** - * Check the position of the sidebar vs the height of the viewport & page - * container, and toggle the "bottom" class to position the sidebar without - * overlapping the footer. + * Check the position of each sidebar relative to the scroll position, + * and toggle the "fixed" class at a certain point. + * Reduce the height of each sidebar to stop them overlapping the footer. */ function onScroll() { // Only run the scroll code if the sidebar is floating on a wide screen. @@ -41,7 +41,6 @@ function onScroll() { } const { scrollY, innerHeight: windowHeight } = window; - // const footerTop = footer.getBoundingClientRect().top; const scrollPosition = scrollY - ADMIN_BAR_HEIGHT; // Toggle the fixed position based on whether the scrollPosition is greater than the initial gap from the top. @@ -51,7 +50,7 @@ function onScroll() { const footerStart = mainEl.offsetTop + mainEl.offsetHeight; - // Is footerStart visible in the viewport? + // Is the footer visible in the viewport? if ( footerStart < scrollPosition + windowHeight ) { containers.forEach( ( container ) => { container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); From 08191e060201c3bcbe8f76f5ae360cb2c1559771 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:15:36 +1300 Subject: [PATCH 07/23] Fix postcss selector nesting Co-authored-by: Kelly Dwan --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index b1a05dd91..8a66e11a2 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -65,7 +65,7 @@ } } - * + .is-link-to-top { + & * + .is-link-to-top { border-top: 1px solid var(--wp--preset--color--light-grey-1); } } From c9145709d146a494f1a6749f34e556b5efd690f1 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:16:06 +1300 Subject: [PATCH 08/23] Fix postcss selector nesting Co-authored-by: Kelly Dwan --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 8a66e11a2..78fb30d09 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -55,7 +55,7 @@ border-radius: 10px; } - .is-link-to-top { + & .is-link-to-top { display: block; padding-top: var(--wp--preset--spacing--20); From f1a29d93621739c02ae4e4e47ff8a14c29059fef Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:19:58 +1300 Subject: [PATCH 09/23] Fix postcss selector nesting --- .../sidebar-container/postcss/style.pcss | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 78fb30d09..567c3eea1 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -20,15 +20,6 @@ margin-bottom: 0 !important; padding: var(--wp--preset--spacing--20) 0; - main & { - position: absolute; - top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); - margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); - - /* Right offset should be "edge spacing" at minimum, otherwise calculate it to be centered. */ - right: max(var(--wp--preset--spacing--edge-space), calc((100% - var(--wp--style--global--wide-size)) / 2)); - } - &:not(.is-fixed-sidebar) { /* Match width of custom scrollbar when fixed, stops content width changing */ @@ -69,6 +60,15 @@ border-top: 1px solid var(--wp--preset--color--light-grey-1); } } + + main .wp-block-wporg-sidebar-container { + position: absolute; + top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); + margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); + + /* Right offset should be "edge spacing" at minimum, otherwise calculate it to be centered. */ + right: max(var(--wp--preset--spacing--edge-space), calc((100% - var(--wp--style--global--wide-size)) / 2)); + } } @media (min-width: 890px) { From f291ec105a67c9c694836363a0eef7cc4c0faa6f Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 25 Jan 2024 12:22:01 +1300 Subject: [PATCH 10/23] Remove ToC back to top padding if no content --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 567c3eea1..b7b175d37 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -48,7 +48,6 @@ & .is-link-to-top { display: block; - padding-top: var(--wp--preset--spacing--20); & a { color: var(--wp--preset--color--charcoal-4); @@ -57,6 +56,7 @@ } & * + .is-link-to-top { + padding-top: var(--wp--preset--spacing--20); border-top: 1px solid var(--wp--preset--color--light-grey-1); } } From ebb5561506d6597781fd4cd4fc81bb338605fbf3 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 09:49:18 +1300 Subject: [PATCH 11/23] Make sidebar container control padding when fixed --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 10 +++++----- mu-plugins/blocks/sidebar-container/src/view.js | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index b7b175d37..ba5353fa2 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -14,11 +14,10 @@ @media (min-width: 1200px) { .wp-block-wporg-sidebar-container { --local--block-end-sidebar--width: 340px; - --local--top-offset: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); + --local--offset-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); + --local--padding-top: var(--wp--preset--spacing--20); width: var(--local--block-end-sidebar--width); - margin-bottom: 0 !important; - padding: var(--wp--preset--spacing--20) 0; &:not(.is-fixed-sidebar) { @@ -29,8 +28,9 @@ &.is-fixed-sidebar { position: fixed; top: 0; - height: calc(100vh - var(--local--top-offset)); - margin-top: var(--local--top-offset); + height: calc(100vh - var(--local--offset-top)); + margin-top: var(--local--offset-top) !important; + padding: var(--local--padding-top) 0; overflow-y: scroll; /* Custom scrollbar so that it can be made visible on hover */ diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 1274c42bc..3d5b724a3 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -45,7 +45,10 @@ function onScroll() { // Toggle the fixed position based on whether the scrollPosition is greater than the initial gap from the top. containers.forEach( ( container ) => { - container.classList.toggle( 'is-fixed-sidebar', scrollPosition > SCROLL_POSITION_TO_FIX ); + container.classList.toggle( + 'is-fixed-sidebar', + scrollPosition > SCROLL_POSITION_TO_FIX - getCustomPropValue( '--local--padding-top', container ) + ); } ); const footerStart = mainEl.offsetTop + mainEl.offsetHeight; From 7c2c1a7d04620c98c1839e4bb396768bde513f2f Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:22:15 +1300 Subject: [PATCH 12/23] Move skip link target styles to local nav bar --- mu-plugins/blocks/local-navigation-bar/postcss/style.pcss | 7 +++++++ mu-plugins/blocks/sidebar-container/postcss/style.pcss | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mu-plugins/blocks/local-navigation-bar/postcss/style.pcss b/mu-plugins/blocks/local-navigation-bar/postcss/style.pcss index 0a4b69567..cc94af9ad 100644 --- a/mu-plugins/blocks/local-navigation-bar/postcss/style.pcss +++ b/mu-plugins/blocks/local-navigation-bar/postcss/style.pcss @@ -123,6 +123,13 @@ } } +@media (min-width: 890px) { + /* stylelint-disable selector-id-pattern */ + #wp--skip-link--target { + scroll-margin-top: var(--wp--custom--local-navigation-bar--spacing--height, 0); + } +} + /* Set up the custom properties. These can be overridden by settings in theme.json. */ :where(body) { --wp--custom--local-navigation-bar--spacing--height: 60px; diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index ba5353fa2..fe8bcdd4e 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -71,13 +71,6 @@ } } -@media (min-width: 890px) { - /* stylelint-disable selector-id-pattern */ - #wp--skip-link--target { - scroll-margin-top: var(--wp--custom--local-navigation-bar--spacing--height, 0); - } -} - /* Set up the custom properties. These can be overridden by settings in theme.json. */ :where(body) { --wp--custom--wporg-sidebar-container--spacing--margin--top: var(--wp--preset--spacing--edge-space); From b24b6f24d90ea198968299fdf0711879cb8482d8 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:28:59 +1300 Subject: [PATCH 13/23] Make the inline breakpoint configurable for each container This allows individual containers to become inline at different breakpoints, eg. the Chapter List remaining fixed and scrolling when the ToC is already displayed inline. --- mu-plugins/blocks/sidebar-container/index.php | 4 +- .../sidebar-container/postcss/style.pcss | 45 +++++++--- .../blocks/sidebar-container/src/block.json | 4 + .../blocks/sidebar-container/src/view.js | 89 ++++++++++++------- 4 files changed, 96 insertions(+), 46 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/index.php b/mu-plugins/blocks/sidebar-container/index.php index 08edf085d..4056b6982 100644 --- a/mu-plugins/blocks/sidebar-container/index.php +++ b/mu-plugins/blocks/sidebar-container/index.php @@ -45,11 +45,13 @@ function render( $attributes, $content, $block ) { esc_html__( '↑ Back to top', 'wporg' ) ) : ''; + $inlineBreakpoint = $attributes['inlineBreakpoint']; $wrapper_attributes = get_block_wrapper_attributes(); return sprintf( - '
%2$s%3$s
', + '
%3$s%4$s
', $wrapper_attributes, + esc_attr( $inlineBreakpoint ), $content, $back_to_top ); diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index fe8bcdd4e..deaa07fe6 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -1,21 +1,32 @@ -.wp-block-wporg-sidebar-container .is-link-to-top { - display: none; +.wp-block-wporg-sidebar-container { + --local--offset-top: var(--wp-admin--admin-bar--height, 0); + + /* These vars are used in JS calcs */ + --local--nav--offset: var(--wp--custom--local-navigation-bar--spacing--height, 60px); + --local--padding: var(--wp--preset--spacing--20); - & a { - text-decoration-line: none; + /* Account for local nav height on larger screens where it becomes fixed. */ + @media (min-width: 890px) { + /* stylelint-disable-next-line length-zero-no-unit */ + --local--nav--offset: 0px; + --local--offset-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); + } - &:hover { - text-decoration-line: underline; + & .is-link-to-top { + display: none; + + & a { + text-decoration-line: none; + + &:hover { + text-decoration-line: underline; + } } } -} -/* Slot the search & table of contents into a floating sidebar on large screens. */ -@media (min-width: 1200px) { - .wp-block-wporg-sidebar-container { + /* Slot the search & table of contents into a floating sidebar on large screens. */ + &.is-floating-sidebar { --local--block-end-sidebar--width: 340px; - --local--offset-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); - --local--padding-top: var(--wp--preset--spacing--20); width: var(--local--block-end-sidebar--width); @@ -30,7 +41,7 @@ top: 0; height: calc(100vh - var(--local--offset-top)); margin-top: var(--local--offset-top) !important; - padding: var(--local--padding-top) 0; + padding: var(--local--padding) 0; overflow-y: scroll; /* Custom scrollbar so that it can be made visible on hover */ @@ -60,8 +71,14 @@ border-top: 1px solid var(--wp--preset--color--light-grey-1); } } +} + +main .wp-block-wporg-sidebar-container { + + /* Hide the main sidebar until layout classes have been applied, to avoid FOUC */ + display: none; - main .wp-block-wporg-sidebar-container { + &.is-floating-sidebar { position: absolute; top: calc(var(--wp-global-header-offset, 90px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); margin-top: var(--wp--custom--wporg-sidebar-container--spacing--margin--top); diff --git a/mu-plugins/blocks/sidebar-container/src/block.json b/mu-plugins/blocks/sidebar-container/src/block.json index c07a7574d..557d1652f 100644 --- a/mu-plugins/blocks/sidebar-container/src/block.json +++ b/mu-plugins/blocks/sidebar-container/src/block.json @@ -11,6 +11,10 @@ "hasBackToTop": { "type": "boolean", "default": true + }, + "inlineBreakpoint": { + "type": "string", + "default": "1200px" } }, "supports": { diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 3d5b724a3..8b634d98b 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -1,17 +1,13 @@ /** * Fallback values for custom properties match CSS defaults. */ - -const GLOBAL_NAV_HEIGHT = getCustomPropValue( '--wp-global-header-height' ) || 90; -const ADMIN_BAR_HEIGHT = parseInt( - window.getComputedStyle( document.documentElement ).getPropertyValue( 'margin-top' ), - 10 -); const SPACE_TO_TOP = getCustomPropValue( '--wp--custom--wporg-sidebar-container--spacing--margin--top' ) || 80; -const SCROLL_POSITION_TO_FIX = GLOBAL_NAV_HEIGHT + SPACE_TO_TOP - ADMIN_BAR_HEIGHT; let containers; let mainEl; +let adminBarHeight; +let globalNavHeight; +const scrollHandlers = []; /** * Get the value of a CSS custom property. @@ -30,39 +26,62 @@ function getCustomPropValue( name, element = document.body ) { } /** - * Check the position of each sidebar relative to the scroll position, + * Check the position of the sidebar relative to the scroll position, * and toggle the "fixed" class at a certain point. - * Reduce the height of each sidebar to stop them overlapping the footer. + * Reduce the height of the sidebar to stop it overlapping the footer. + * + * @param {HTMLElement} container */ -function onScroll() { - // Only run the scroll code if the sidebar is floating on a wide screen. - if ( ! window.matchMedia( '(min-width: 1200px)' ).matches ) { - return; - } +function createScrollHandler( container ) { + return function onScroll() { + // Only run the scroll code if the sidebar is floating. + if ( ! container.classList.contains( 'is-floating-sidebar' ) ) { + return false; + } - const { scrollY, innerHeight: windowHeight } = window; - const scrollPosition = scrollY - ADMIN_BAR_HEIGHT; + const { scrollY, innerHeight: windowHeight } = window; + const scrollPosition = scrollY - adminBarHeight; + const localNavOffset = getCustomPropValue( '--local--nav--offset', container ); + const paddingTop = getCustomPropValue( '--local--padding', container ); - // Toggle the fixed position based on whether the scrollPosition is greater than the initial gap from the top. - containers.forEach( ( container ) => { + // Toggle the fixed position based on whether the scrollPosition is greater than the + // initial gap from the top minus the padding applied when fixed. container.classList.toggle( 'is-fixed-sidebar', - scrollPosition > SCROLL_POSITION_TO_FIX - getCustomPropValue( '--local--padding-top', container ) + scrollPosition > SPACE_TO_TOP + globalNavHeight + localNavOffset - adminBarHeight - paddingTop ); - } ); - const footerStart = mainEl.offsetTop + mainEl.offsetHeight; + const footerStart = mainEl.offsetTop + mainEl.offsetHeight; - // Is the footer visible in the viewport? - if ( footerStart < scrollPosition + windowHeight ) { - containers.forEach( ( container ) => { + // Is the footer visible in the viewport? + if ( footerStart < scrollPosition + windowHeight ) { container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); - } ); - } else { - containers.forEach( ( container ) => { + } else { container.style.removeProperty( 'height' ); - } ); - } + } + }; +} + +/** + * Set the height for the admin bar and global nav vars. + * Set the floating sidebar class on each container based on their breakpoint. + * Show hidden containers after layout. + */ +function onResize() { + adminBarHeight = getCustomPropValue( '--wp-admin--admin-bar--height' ) || 32; + globalNavHeight = getCustomPropValue( '--wp-global-header-height' ) || 90; + + containers.forEach( ( container ) => { + // Toggle the floating class based on the configured breakpoint. + const shouldFloat = window.matchMedia( `(min-width: ${ container.dataset.breakpoint })` ).matches; + container.classList.toggle( 'is-floating-sidebar', shouldFloat ); + // Show the sidebar after layout, if it has been hidden to avoid FOUC. + if ( 'none' === window.getComputedStyle( container ).display ) { + container.style.setProperty( 'display', 'revert' ); + } + } ); + + scrollHandlers.forEach( ( handler ) => handler() ); } function init() { @@ -70,10 +89,18 @@ function init() { mainEl = document.getElementById( 'wp--skip-link--target' ); if ( mainEl && containers.length ) { - onScroll(); // Run once to avoid footer collisions on load (ex, when linked to #reply-title). - window.addEventListener( 'scroll', onScroll ); + containers.forEach( ( container ) => { + const scrollHandler = createScrollHandler( container ); + scrollHandlers.push( scrollHandler ); + window.addEventListener( 'scroll', scrollHandler ); + } ); } + // Run once to set height vars and position elements on load. + // Avoids footer collisions (ex, when linked to #reply-title). + onResize(); + window.addEventListener( 'resize', onResize ); + // If there is no table of contents, hide the heading. if ( ! document.querySelector( '.wp-block-wporg-table-of-contents' ) ) { const heading = document.querySelector( '.wp-block-wporg-sidebar-container h2' ); From 740a0aa38bffaa553c2e4ef77aacb7f5a89ebf70 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:20:53 +1300 Subject: [PATCH 14/23] Move logic to hide ToC heading if content is empty from JS to render --- mu-plugins/blocks/sidebar-container/src/view.js | 6 ------ mu-plugins/blocks/table-of-contents/index.php | 13 ++++++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 8b634d98b..ed39482b4 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -100,12 +100,6 @@ function init() { // Avoids footer collisions (ex, when linked to #reply-title). onResize(); window.addEventListener( 'resize', onResize ); - - // If there is no table of contents, hide the heading. - if ( ! document.querySelector( '.wp-block-wporg-table-of-contents' ) ) { - const heading = document.querySelector( '.wp-block-wporg-sidebar-container h2' ); - heading?.style.setProperty( 'display', 'none' ); - } } window.addEventListener( 'load', init ); diff --git a/mu-plugins/blocks/table-of-contents/index.php b/mu-plugins/blocks/table-of-contents/index.php index 61d679acc..d15b61ab1 100644 --- a/mu-plugins/blocks/table-of-contents/index.php +++ b/mu-plugins/blocks/table-of-contents/index.php @@ -56,11 +56,14 @@ function render( $attributes, $content, $block ) { $title = apply_filters( 'wporg_table_of_contents_heading', __( 'In this article', 'wporg' ), $post->ID ); $content = '
'; - $content .= do_blocks( - ' -

' . esc_html( $title ) . '

- ' - ); + // If there is no content, don't render the heading. + $content .= empty( trim( wp_strip_all_tags( $post_content ) ) ) + ? '' + : do_blocks( + ' +

' . esc_html( $title ) . '

+ ' + ); $content .= ''; From 0b9b87388bc55114007b110c0fb6371656e0a1bf Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:42:21 +1300 Subject: [PATCH 15/23] Fix handling of zero css values in getCustomPropValue --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 3 +-- mu-plugins/blocks/sidebar-container/src/view.js | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index deaa07fe6..895870ce1 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -7,8 +7,7 @@ /* Account for local nav height on larger screens where it becomes fixed. */ @media (min-width: 890px) { - /* stylelint-disable-next-line length-zero-no-unit */ - --local--nav--offset: 0px; + --local--nav--offset: 0; --local--offset-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--wp--custom--local-navigation-bar--spacing--height, 60px)); } diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index ed39482b4..ee273df44 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -19,6 +19,9 @@ const scrollHandlers = []; */ function getCustomPropValue( name, element = document.body ) { const value = window.getComputedStyle( element ).getPropertyValue( name ); + if ( '0' === value ) { + return 0; + } if ( 'px' === value.slice( -2 ) ) { return Number( value.replace( 'px', '' ) ); } From 17d0addfe7d6859bfea7e8dbc0922a49c4fd8aa0 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:16:07 +1300 Subject: [PATCH 16/23] Complete jsdoc --- mu-plugins/blocks/sidebar-container/src/view.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index ee273df44..278f9728f 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -33,7 +33,8 @@ function getCustomPropValue( name, element = document.body ) { * and toggle the "fixed" class at a certain point. * Reduce the height of the sidebar to stop it overlapping the footer. * - * @param {HTMLElement} container + * @param {HTMLElement} container The sidebar container. + * @return {Function} onScroll The sidebar scroll handler. */ function createScrollHandler( container ) { return function onScroll() { @@ -67,7 +68,7 @@ function createScrollHandler( container ) { /** * Set the height for the admin bar and global nav vars. - * Set the floating sidebar class on each container based on their breakpoint. + * Set the floating sidebar class on each container based on its breakpoint. * Show hidden containers after layout. */ function onResize() { From abf6ac5d13256788953a4fe1c702a6862fe446f9 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:28:14 +1300 Subject: [PATCH 17/23] Fix scrolling height calc when logged out --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 895870ce1..2d7ab274f 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -1,5 +1,6 @@ .wp-block-wporg-sidebar-container { - --local--offset-top: var(--wp-admin--admin-bar--height, 0); + /* stylelint-disable-next-line length-zero-no-unit */ + --local--offset-top: var(--wp-admin--admin-bar--height, 0px); /* These vars are used in JS calcs */ --local--nav--offset: var(--wp--custom--local-navigation-bar--spacing--height, 60px); From 91fe052bd6509fe7ece7b439624a474cc9265285 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 31 Jan 2024 10:19:17 +1300 Subject: [PATCH 18/23] Revert changing admin bar height detection --- mu-plugins/blocks/sidebar-container/src/view.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index 278f9728f..f570b82c0 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -72,7 +72,10 @@ function createScrollHandler( container ) { * Show hidden containers after layout. */ function onResize() { - adminBarHeight = getCustomPropValue( '--wp-admin--admin-bar--height' ) || 32; + adminBarHeight = parseInt( + window.getComputedStyle( document.documentElement ).getPropertyValue( 'margin-top' ), + 10 + ); globalNavHeight = getCustomPropValue( '--wp-global-header-height' ) || 90; containers.forEach( ( container ) => { From 061aab3a3565a6556fdb08587ef0050e9353803e Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:22:30 +1300 Subject: [PATCH 19/23] Improve scrollbar styles Completes the states and fixes issues in Firefox --- .../sidebar-container/postcss/style.pcss | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 2d7ab274f..2d1c917c3 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -26,13 +26,39 @@ /* Slot the search & table of contents into a floating sidebar on large screens. */ &.is-floating-sidebar { - --local--block-end-sidebar--width: 340px; + --local--block-end-sidebar--width: 356px; width: var(--local--block-end-sidebar--width); + overflow-y: scroll; + overscroll-behavior: contain; + scrollbar-color: var(--wp--preset--color--charcoal-5) transparent; + + /* Custom scrollbar so that it can be made visible on hover */ + &::-webkit-scrollbar, + &::-webkit-scrollbar-track { + background-color: transparent; + } - &:not(.is-fixed-sidebar) { + &::-webkit-scrollbar-thumb { + &:active, + &:hover { + background-color: var(--wp--preset--color--charcoal-4) !important; + } + } - /* Match width of custom scrollbar when fixed, stops content width changing */ + &:active, + &:focus-within, + &:focus, + &:hover { + &::-webkit-scrollbar-thumb { + background-color: var(--wp--preset--color--charcoal-5); + border: 4px solid transparent; + background-clip: content-box; + border-radius: 10px; + } + } + + & > * { padding-right: 16px; } @@ -42,20 +68,6 @@ height: calc(100vh - var(--local--offset-top)); margin-top: var(--local--offset-top) !important; padding: var(--local--padding) 0; - overflow-y: scroll; - - /* Custom scrollbar so that it can be made visible on hover */ - &::-webkit-scrollbar, - &::-webkit-scrollbar-thumb { - background-color: transparent; - } - - &:hover::-webkit-scrollbar-thumb { - background-color: var(--wp--preset--color--charcoal-4); - border: 4.5px solid transparent; - background-clip: content-box; - border-radius: 10px; - } & .is-link-to-top { display: block; From bcb5688ac77e38b8af478ebed7d517cee9495f41 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Wed, 31 Jan 2024 17:15:04 +1300 Subject: [PATCH 20/23] Only reduce the height when the footer is visible if the sidebar is fixed --- mu-plugins/blocks/sidebar-container/src/view.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/src/view.js b/mu-plugins/blocks/sidebar-container/src/view.js index f570b82c0..f2540f312 100644 --- a/mu-plugins/blocks/sidebar-container/src/view.js +++ b/mu-plugins/blocks/sidebar-container/src/view.js @@ -50,15 +50,13 @@ function createScrollHandler( container ) { // Toggle the fixed position based on whether the scrollPosition is greater than the // initial gap from the top minus the padding applied when fixed. - container.classList.toggle( - 'is-fixed-sidebar', - scrollPosition > SPACE_TO_TOP + globalNavHeight + localNavOffset - adminBarHeight - paddingTop - ); + const shouldFix = + scrollPosition > SPACE_TO_TOP + globalNavHeight + localNavOffset - adminBarHeight - paddingTop; + container.classList.toggle( 'is-fixed-sidebar', shouldFix ); + // If the sidebar is fixed and the footer is visible in the viewport, reduce the height to stop overlap. const footerStart = mainEl.offsetTop + mainEl.offsetHeight; - - // Is the footer visible in the viewport? - if ( footerStart < scrollPosition + windowHeight ) { + if ( shouldFix && footerStart < scrollPosition + windowHeight ) { container.style.setProperty( 'height', `${ footerStart - scrollPosition - container.offsetTop }px` ); } else { container.style.removeProperty( 'height' ); From 07b512cd587f1ec909ebe15f87d9919ae45091d2 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:29:55 +1300 Subject: [PATCH 21/23] Revert "Move logic to hide ToC heading if content is empty from JS to render" This reverts the render changes in commit 740a0aa38bffaa553c2e4ef77aacb7f5a89ebf70, but keeps the JS changes --- mu-plugins/blocks/table-of-contents/index.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/mu-plugins/blocks/table-of-contents/index.php b/mu-plugins/blocks/table-of-contents/index.php index d15b61ab1..61d679acc 100644 --- a/mu-plugins/blocks/table-of-contents/index.php +++ b/mu-plugins/blocks/table-of-contents/index.php @@ -56,14 +56,11 @@ function render( $attributes, $content, $block ) { $title = apply_filters( 'wporg_table_of_contents_heading', __( 'In this article', 'wporg' ), $post->ID ); $content = '
'; - // If there is no content, don't render the heading. - $content .= empty( trim( wp_strip_all_tags( $post_content ) ) ) - ? '' - : do_blocks( - ' -

' . esc_html( $title ) . '

- ' - ); + $content .= do_blocks( + ' +

' . esc_html( $title ) . '

+ ' + ); $content .= ''; From 2aed92730dd4ddb3e3e0864f0a09bc5d31da6453 Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:40:07 +1300 Subject: [PATCH 22/23] Use snakecase for php vars --- mu-plugins/blocks/sidebar-container/index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mu-plugins/blocks/sidebar-container/index.php b/mu-plugins/blocks/sidebar-container/index.php index 4056b6982..9e126cfd8 100644 --- a/mu-plugins/blocks/sidebar-container/index.php +++ b/mu-plugins/blocks/sidebar-container/index.php @@ -39,19 +39,19 @@ function init() { * @return string Returns the block markup. */ function render( $attributes, $content, $block ) { + $wrapper_attributes = get_block_wrapper_attributes(); + $inline_breakpoint = $attributes['inlineBreakpoint']; $back_to_top = $attributes['hasBackToTop'] ? sprintf( '', esc_html__( '↑ Back to top', 'wporg' ) ) : ''; - $inlineBreakpoint = $attributes['inlineBreakpoint']; - $wrapper_attributes = get_block_wrapper_attributes(); return sprintf( '
%3$s%4$s
', $wrapper_attributes, - esc_attr( $inlineBreakpoint ), + esc_attr( $inline_breakpoint ), $content, $back_to_top ); From 40f897780e388f616b72383ec0f28b6e5aff487a Mon Sep 17 00:00:00 2001 From: Adam Wood <1017872+adamwoodnz@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:51:37 +1300 Subject: [PATCH 23/23] Add bottom padding all the time when floating This adds space between sidebar and footer when main content is short --- mu-plugins/blocks/sidebar-container/postcss/style.pcss | 1 + 1 file changed, 1 insertion(+) diff --git a/mu-plugins/blocks/sidebar-container/postcss/style.pcss b/mu-plugins/blocks/sidebar-container/postcss/style.pcss index 2d1c917c3..bf19be0f1 100644 --- a/mu-plugins/blocks/sidebar-container/postcss/style.pcss +++ b/mu-plugins/blocks/sidebar-container/postcss/style.pcss @@ -29,6 +29,7 @@ --local--block-end-sidebar--width: 356px; width: var(--local--block-end-sidebar--width); + padding-bottom: var(--local--padding); overflow-y: scroll; overscroll-behavior: contain; scrollbar-color: var(--wp--preset--color--charcoal-5) transparent;