From 6a0188b697685c9f47e656e497f8d5daba84048e Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 8 May 2024 11:49:23 +0900 Subject: [PATCH] Block editor: scroll block into view on insert (#61418) Co-authored-by: ellatrix Co-authored-by: draganescu Co-authored-by: scruffian --- .../block-list/use-block-props/index.js | 2 + .../use-block-props/use-scroll-into-view.js | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 packages/block-editor/src/components/block-list/use-block-props/use-scroll-into-view.js diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 46ebe502be07e6..64e40559bb4735 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -28,6 +28,7 @@ import { useEventHandlers } from './use-selected-block-event-handlers'; import { useNavModeExit } from './use-nav-mode-exit'; import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; +import { useScrollIntoView } from './use-scroll-into-view'; import { useFlashEditableBlocks } from '../../use-flash-editable-blocks'; import { canBindBlock } from '../../../hooks/use-bindings-attributes'; @@ -122,6 +123,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { clientId, isEnabled: name === 'core/block' || templateLock === 'contentOnly', } ), + useScrollIntoView( { isSelected } ), ] ); const blockEditContext = useBlockEditContext(); diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-scroll-into-view.js b/packages/block-editor/src/components/block-list/use-block-props/use-scroll-into-view.js new file mode 100644 index 00000000000000..6301dac2c2108e --- /dev/null +++ b/packages/block-editor/src/components/block-list/use-block-props/use-scroll-into-view.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { useReducedMotion, useRefEffect } from '@wordpress/compose'; + +export function useScrollIntoView( { isSelected } ) { + const prefersReducedMotion = useReducedMotion(); + return useRefEffect( + ( node ) => { + if ( isSelected ) { + const { ownerDocument } = node; + const { defaultView } = ownerDocument; + if ( ! defaultView.IntersectionObserver ) { + return; + } + const observer = new defaultView.IntersectionObserver( + ( entries ) => { + // Once observing starts, we always get an initial + // entry with the intersecting state. + if ( ! entries[ 0 ].isIntersecting ) { + node.scrollIntoView( { + behavior: prefersReducedMotion + ? 'instant' + : 'smooth', + } ); + } + observer.disconnect(); + } + ); + observer.observe( node ); + return () => { + observer.disconnect(); + }; + } + }, + [ isSelected ] + ); +}