From 4eeb99473308fe84ec521752c5e20ed303fd6039 Mon Sep 17 00:00:00 2001 From: "karthick.murugan" Date: Tue, 30 Sep 2025 20:04:28 +0530 Subject: [PATCH 1/5] Focus comments on deletion --- .../src/components/collab-sidebar/comments.js | 56 +++++++++++++++++-- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index a51767620f9d49..aa464ebc9ae6b1 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { useState, RawHTML, useRef } from '@wordpress/element'; +import { useState, RawHTML, useRef, useEffect } from '@wordpress/element'; import { __experimentalText as Text, __experimentalHStack as HStack, @@ -56,15 +56,50 @@ export function Comments( { onCommentDelete, setShowCommentBoard, } ) { - const blockCommentId = useSelect( ( select ) => { + const { blockCommentId, selectedBlockClientId } = useSelect( ( select ) => { const { getBlockAttributes, getSelectedBlockClientId } = select( blockEditorStore ); const clientId = getSelectedBlockClientId(); - return clientId - ? getBlockAttributes( clientId )?.metadata?.commentId - : null; + return { + blockCommentId: clientId + ? getBlockAttributes( clientId )?.metadata?.commentId + : null, + selectedBlockClientId: clientId, + }; }, [] ); const [ selectedThread = blockCommentId, setSelectedThread ] = useState(); + const [ focusTarget, setFocusTarget ] = useState( null ); + const relatedBlockElement = useBlockElement( selectedBlockClientId ); + + const handleDelete = ( comment ) => { + const currentIndex = threads.findIndex( ( t ) => t.id === comment.id ); + onCommentDelete( comment ); + const nextThread = threads[ currentIndex + 1 ]; + const prevThread = threads[ currentIndex - 1 ]; + if ( nextThread ) { + setSelectedThread( nextThread.id ); + setFocusTarget( nextThread.id ); + } else if ( prevThread ) { + setSelectedThread( prevThread.id ); + setFocusTarget( prevThread.id ); + } else { + setSelectedThread( null ); + setShowCommentBoard( false ); + if ( relatedBlockElement ) { + relatedBlockElement.scrollIntoView( { + behavior: 'instant', + block: 'center', + } ); + } + } + }; + + // Focus the target thread when focusTarget changes + useEffect( () => { + if ( focusTarget ) { + setFocusTarget( null ); + } + }, [ focusTarget ] ); const hasThreads = Array.isArray( threads ) && threads.length > 0; if ( ! hasThreads ) { @@ -88,11 +123,12 @@ export function Comments( { key={ thread.id } thread={ thread } onAddReply={ onAddReply } - onCommentDelete={ onCommentDelete } + onCommentDelete={ handleDelete } onEditComment={ onEditComment } isSelected={ selectedThread === thread.id } setSelectedThread={ setSelectedThread } setShowCommentBoard={ setShowCommentBoard } + focusTarget={ focusTarget } /> ) ); } @@ -105,6 +141,7 @@ function Thread( { isSelected, setSelectedThread, setShowCommentBoard, + focusTarget, } ) { const threadRef = useRef( null ); const { toggleBlockHighlight } = useDispatch( blockEditorStore ); @@ -114,6 +151,13 @@ function Thread( { 50 ); + // Focus this thread if it's the target + useEffect( () => { + if ( focusTarget === thread.id && threadRef.current ) { + threadRef.current.focus(); + } + }, [ focusTarget, thread.id ] ); + const onMouseEnter = () => { debouncedToggleBlockHighlight( thread.blockClientId, true ); }; From 95a106ff6aaae7db973c6ed2b828eaea42ed4b96 Mon Sep 17 00:00:00 2001 From: "karthick.murugan" Date: Tue, 7 Oct 2025 17:53:37 +0530 Subject: [PATCH 2/5] Implement utility functions --- .../src/components/collab-sidebar/comments.js | 57 ++++++++----------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index 64302c0f8f14ba..a0698b685c720b 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -70,38 +70,38 @@ export function Comments( { }; }, [] ); const [ selectedThread = blockCommentId, setSelectedThread ] = useState(); - const [ focusTarget, setFocusTarget ] = useState( null ); const relatedBlockElement = useBlockElement( selectedBlockClientId ); const handleDelete = ( comment ) => { const currentIndex = threads.findIndex( ( t ) => t.id === comment.id ); - onCommentDelete( comment ); const nextThread = threads[ currentIndex + 1 ]; const prevThread = threads[ currentIndex - 1 ]; - if ( nextThread ) { - setSelectedThread( nextThread.id ); - setFocusTarget( nextThread.id ); - } else if ( prevThread ) { - setSelectedThread( prevThread.id ); - setFocusTarget( prevThread.id ); - } else { - setSelectedThread( null ); - setShowCommentBoard( false ); - if ( relatedBlockElement ) { - relatedBlockElement.scrollIntoView( { - behavior: 'instant', - block: 'center', - } ); + + // Store the focus logic to execute after deletion completes + const focusAfterDeletion = () => { + if ( nextThread ) { + setSelectedThread( nextThread.id ); + // Use the utility function to focus the thread without triggering dropdown + focusCommentThread( nextThread.id, commentSidebarRef.current ); + } else if ( prevThread ) { + setSelectedThread( prevThread.id ); + // Use the utility function to focus the thread without triggering dropdown + focusCommentThread( prevThread.id, commentSidebarRef.current ); + } else { + setSelectedThread( null ); + setShowCommentBoard( false ); + if ( relatedBlockElement ) { + relatedBlockElement.scrollIntoView( { + behavior: 'instant', + block: 'center', + } ); + } } - } - }; + }; - // Focus the target thread when focusTarget changes - useEffect( () => { - if ( focusTarget ) { - setFocusTarget( null ); - } - }, [ focusTarget ] ); + // Execute deletion and focus after completion + onCommentDelete( comment ).then( focusAfterDeletion ); + }; // Auto-select the related comment thread when a block is selected. useEffect( () => { @@ -135,7 +135,6 @@ export function Comments( { isSelected={ selectedThread === thread.id } setSelectedThread={ setSelectedThread } setShowCommentBoard={ setShowCommentBoard } - focusTarget={ focusTarget } commentSidebarRef={ commentSidebarRef } /> ) ); @@ -149,7 +148,6 @@ function Thread( { isSelected, setSelectedThread, setShowCommentBoard, - focusTarget, commentSidebarRef, } ) { const { toggleBlockHighlight, selectBlock } = @@ -161,13 +159,6 @@ function Thread( { 50 ); - // Focus this thread if it's the target - useEffect( () => { - if ( focusTarget === thread.id && threadRef.current ) { - threadRef.current.focus(); - } - }, [ focusTarget, thread.id ] ); - const onMouseEnter = () => { debouncedToggleBlockHighlight( thread.blockClientId, true ); }; From 5874266a9db2398de295dde3aa8246a31c650338 Mon Sep 17 00:00:00 2001 From: "karthick.murugan" Date: Tue, 7 Oct 2025 17:56:47 +0530 Subject: [PATCH 3/5] Remove few comments --- packages/editor/src/components/collab-sidebar/comments.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index a0698b685c720b..5cb63e2e931a09 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -77,15 +77,13 @@ export function Comments( { const nextThread = threads[ currentIndex + 1 ]; const prevThread = threads[ currentIndex - 1 ]; - // Store the focus logic to execute after deletion completes + // Store the focus logic to execute after deletion completes. const focusAfterDeletion = () => { if ( nextThread ) { setSelectedThread( nextThread.id ); - // Use the utility function to focus the thread without triggering dropdown focusCommentThread( nextThread.id, commentSidebarRef.current ); } else if ( prevThread ) { setSelectedThread( prevThread.id ); - // Use the utility function to focus the thread without triggering dropdown focusCommentThread( prevThread.id, commentSidebarRef.current ); } else { setSelectedThread( null ); @@ -99,7 +97,7 @@ export function Comments( { } }; - // Execute deletion and focus after completion + // Execute deletion and focus after completion. onCommentDelete( comment ).then( focusAfterDeletion ); }; From 0ab6b8fbac05afdd5c2d55bcac2e2d501e6e79bb Mon Sep 17 00:00:00 2001 From: "karthick.murugan" Date: Tue, 7 Oct 2025 18:02:48 +0530 Subject: [PATCH 4/5] Remove ref --- packages/editor/src/components/collab-sidebar/comments.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index 5cb63e2e931a09..82a8c204583b50 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -6,7 +6,7 @@ import clsx from 'clsx'; /** * WordPress dependencies */ -import { useState, RawHTML, useRef, useEffect } from '@wordpress/element'; +import { useState, RawHTML, useEffect } from '@wordpress/element'; import { __experimentalText as Text, __experimentalHStack as HStack, @@ -151,7 +151,6 @@ function Thread( { const { toggleBlockHighlight, selectBlock } = useDispatch( blockEditorStore ); const relatedBlockElement = useBlockElement( thread.blockClientId ); - const threadRef = useRef(); const debouncedToggleBlockHighlight = useDebounce( toggleBlockHighlight, 50 @@ -203,7 +202,6 @@ function Thread( { // Disable reason: role="listitem" does in fact support aria-expanded. // eslint-disable-next-line jsx-a11y/role-supports-aria-props Date: Fri, 10 Oct 2025 18:08:15 +0530 Subject: [PATCH 5/5] Feedback changes --- .../src/components/collab-sidebar/comments.js | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/editor/src/components/collab-sidebar/comments.js b/packages/editor/src/components/collab-sidebar/comments.js index 82a8c204583b50..46ed68d5925892 100644 --- a/packages/editor/src/components/collab-sidebar/comments.js +++ b/packages/editor/src/components/collab-sidebar/comments.js @@ -69,36 +69,29 @@ export function Comments( { selectedBlockClientId: clientId, }; }, [] ); + const { selectBlock } = useDispatch( blockEditorStore ); const [ selectedThread = blockCommentId, setSelectedThread ] = useState(); - const relatedBlockElement = useBlockElement( selectedBlockClientId ); - const handleDelete = ( comment ) => { + const handleDelete = async ( comment ) => { const currentIndex = threads.findIndex( ( t ) => t.id === comment.id ); const nextThread = threads[ currentIndex + 1 ]; const prevThread = threads[ currentIndex - 1 ]; - // Store the focus logic to execute after deletion completes. - const focusAfterDeletion = () => { - if ( nextThread ) { - setSelectedThread( nextThread.id ); - focusCommentThread( nextThread.id, commentSidebarRef.current ); - } else if ( prevThread ) { - setSelectedThread( prevThread.id ); - focusCommentThread( prevThread.id, commentSidebarRef.current ); - } else { - setSelectedThread( null ); - setShowCommentBoard( false ); - if ( relatedBlockElement ) { - relatedBlockElement.scrollIntoView( { - behavior: 'instant', - block: 'center', - } ); - } - } - }; + await onCommentDelete( comment ); - // Execute deletion and focus after completion. - onCommentDelete( comment ).then( focusAfterDeletion ); + // Focus logic after deletion completes. + if ( nextThread ) { + setSelectedThread( nextThread.id ); + focusCommentThread( nextThread.id, commentSidebarRef.current ); + } else if ( prevThread ) { + setSelectedThread( prevThread.id ); + focusCommentThread( prevThread.id, commentSidebarRef.current ); + } else { + setSelectedThread( null ); + setShowCommentBoard( false ); + // Focus the parent block instead of just scrolling into view. + selectBlock( selectedBlockClientId ); + } }; // Auto-select the related comment thread when a block is selected.