Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inline commenting: Comment board alignment to relative blocks #67622

Draft
wants to merge 20 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ff967cb
Export useBlockElement as private api
akasunil Dec 5, 2024
67f651d
Set comment board position relative to the blocks
akasunil Dec 5, 2024
c0165f0
Fix sidebar style background
akasunil Dec 5, 2024
0cc03de
Export useBlockElement instead of useBlockElement
akasunil Dec 6, 2024
23ff73b
Add floating-ui dependacy to editor package
akasunil Dec 6, 2024
dacc2e7
Bind board position to relative block using useFloating
akasunil Dec 6, 2024
9b5e5f9
Merge branch 'trunk' of github.com:WordPress/gutenberg into enhance/i…
akasunil Dec 6, 2024
9067050
Fix style of comment board
akasunil Dec 6, 2024
260d806
Synced with trunk and resolved conflicts
akasunil Dec 10, 2024
6c0256f
Add client id inside comment object to reduce complexity
akasunil Dec 10, 2024
b3252ac
Conditionally align comment board with blocks
akasunil Dec 11, 2024
c1b99ed
Merge branch 'trunk' of github.com:WordPress/gutenberg into enhance/i…
akasunil Dec 11, 2024
51d89e1
Fix board focus issue
akasunil Dec 13, 2024
96b0e1a
Synced with trunk and resolved conflicts
akasunil Dec 13, 2024
b3b74a6
Merge branch 'trunk' of github.com:WordPress/gutenberg into enhance/i…
akasunil Dec 17, 2024
13c7a1e
downgrade floating ui package to fix the error
akasunil Dec 17, 2024
23a2a5c
Use offset in middleware to avoid board overlapping
akasunil Dec 17, 2024
7a0ab59
Fix first comment board position issue
akasunil Dec 23, 2024
0a73ea7
Resolve issue of board overlap when one board is focused
akasunil Dec 27, 2024
239c7f8
Merge branch 'trunk' of github.com:WordPress/gutenberg into enhance/i…
akasunil Dec 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import useBlockDisplayTitle from './components/block-title/use-block-display-tit
import TabbedSidebar from './components/tabbed-sidebar';
import CommentIconSlotFill from './components/collab/block-comment-icon-slot';
import CommentIconToolbarSlotFill from './components/collab/block-comment-icon-toolbar-slot';
import { useBlockElementRef } from './components/block-list/use-block-props/use-block-refs';

/**
* Private @wordpress/block-editor APIs.
*/
Expand Down Expand Up @@ -97,4 +99,5 @@ lock( privateApis, {
sectionRootClientIdKey,
CommentIconSlotFill,
CommentIconToolbarSlotFill,
useBlockElementRef,
} );
1 change: 1 addition & 0 deletions packages/editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
],
"dependencies": {
"@babel/runtime": "7.25.7",
"@floating-ui/react-dom": "^2.0.8",
"@wordpress/a11y": "*",
"@wordpress/api-fetch": "*",
"@wordpress/blob": "*",
Expand Down
131 changes: 124 additions & 7 deletions packages/editor/src/components/collab-sidebar/comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
* External dependencies
*/
import clsx from 'clsx';
import {
useFloating,
autoUpdate,
offset as offsetMiddleware,
} from '@floating-ui/react-dom';

/**
* WordPress dependencies
*/
import { useState, RawHTML } from '@wordpress/element';
import { useState, RawHTML, useRef, useEffect } from '@wordpress/element';
import {
__experimentalHStack as HStack,
__experimentalVStack as VStack,
Expand All @@ -18,13 +23,19 @@ import {
import { Icon, check, published, moreVertical } from '@wordpress/icons';
import { __, _x, sprintf } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
import {
store as blockEditorStore,
privateApis as blockEditorPrivateApis,
} from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import CommentAuthorInfo from './comment-author-info';
import CommentForm from './comment-form';
import { unlock } from '../../lock-unlock';

const { useBlockElementRef } = unlock( blockEditorPrivateApis );

/**
* Renders the Comments component.
Expand All @@ -37,6 +48,7 @@ import CommentForm from './comment-form';
* @param {Function} props.onCommentResolve - The function to mark a comment as resolved.
* @param {boolean} props.showCommentBoard - Whether to show the comment board.
* @param {Function} props.setShowCommentBoard - The function to set the comment board visibility.
* @param {boolean} props.canvasSidebar - Whether is this canvas sidebar or not.
* @return {React.ReactNode} The rendered Comments component.
*/
export function Comments( {
Expand All @@ -47,7 +59,19 @@ export function Comments( {
onCommentResolve,
showCommentBoard,
setShowCommentBoard,
canvasSidebar,
} ) {
const [ heights, setHeights ] = useState( {} );

const updateHeight = ( id, newHeight ) => {
setHeights( ( prev ) => {
if ( prev[ id ] !== newHeight ) {
return { ...prev, [ id ]: newHeight };
}
return prev;
} );
};

const { blockCommentId } = useSelect( ( select ) => {
const { getBlockAttributes, getSelectedBlockClientId } =
select( blockEditorStore );
Expand All @@ -64,11 +88,20 @@ export function Comments( {
showCommentBoard && blockCommentId ? blockCommentId : null
);

// Object to store offsets for each board.
const offsetsRef = useRef( {} );

const updateOffsets = ( id, offset ) => {
offsetsRef.current[ id ] = offset;
};

const clearThreadFocus = () => {
setFocusThread( null );
setShowCommentBoard( false );
};

const ParentWrapper = canvasSidebar ? ThreadWrapper : VStack;

return (
<>
{
Expand All @@ -89,9 +122,12 @@ export function Comments( {
}
{ Array.isArray( threads ) &&
threads.length > 0 &&
threads.map( ( thread ) => (
<VStack
threads.map( ( thread, index ) => (
<ParentWrapper
key={ thread.id }
id={ thread.id }
thread={ thread }
spacing="3"
className={ clsx(
'editor-collab-sidebar-panel__thread',
{
Expand All @@ -102,9 +138,12 @@ export function Comments( {
focusThread && focusThread === thread.id,
}
) }
id={ thread.id }
spacing="3"
onClick={ () => setFocusThread( thread.id ) }
offsetsRef={ offsetsRef }
updateOffsets={ updateOffsets }
previousThreadId={ threads[ index - 1 ]?.id }
updateHeight={ updateHeight }
heights={ heights }
>
<Thread
thread={ thread }
Expand All @@ -115,7 +154,7 @@ export function Comments( {
isFocused={ focusThread === thread.id }
clearThreadFocus={ clearThreadFocus }
/>
</VStack>
</ParentWrapper>
) ) }
</>
);
Expand Down Expand Up @@ -357,3 +396,81 @@ const CommentBoard = ( { thread, onResolve, onEdit, onDelete, status } ) => {
</>
);
};

const ThreadWrapper = ( {
children,
thread,
className,
onClick,
offsetsRef,
updateOffsets,
previousThreadId,
updateHeight,
heights,
} ) => {
const blockRef = useRef();
useBlockElementRef( thread.clientId, blockRef );

const selectedBlockElementRect = blockRef.current?.getBoundingClientRect();

const initialOffsetTop = selectedBlockElementRect?.top;

const previousOffset = previousThreadId
? offsetsRef.current[ previousThreadId ]
: 0;

const previousBoardHeight = heights[ previousThreadId ];

const calculateOffset = () => {
if (
previousOffset &&
initialOffsetTop < previousOffset + previousBoardHeight
) {
return previousOffset - initialOffsetTop + previousBoardHeight + 20;
}
return 0;
};

const { y, refs } = useFloating( {
placement: 'right-start',
middleware: [
offsetMiddleware( {
crossAxis: calculateOffset(),
} ),
],
whileElementsMounted: autoUpdate,
} );

useEffect( () => {
if ( blockRef.current ) {
refs.setReference( blockRef.current ); // Bind reference element
}
}, [ blockRef, refs ] );

useEffect( () => {
if ( y !== null && y !== 0 ) {
updateOffsets( thread.id, y, refs.floating?.current?.clientHeight ); // Pass the offset to the parent
}
}, [ y, updateOffsets ] );

useEffect( () => {
if ( refs.floating?.current ) {
const newHeight = refs.floating?.current.scrollHeight;
updateHeight( thread.id, newHeight );
}
}, [ thread.id, updateHeight ] );

return (
<VStack
ref={ refs.setFloating }
className={ className }
spacing="3"
onClick={ onClick }
style={ {
top: y,
} }
>
{ children }
</VStack>
);
};
14 changes: 10 additions & 4 deletions packages/editor/src/components/collab-sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ function CollabSidebarContent( {
setShowCommentBoard,
styles,
comments,
canvasSidebar = false,
} ) {
const { createNotice } = useDispatch( noticesStore );
const { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore );
Expand Down Expand Up @@ -203,14 +204,14 @@ function CollabSidebarContent( {
setShowCommentBoard={ setShowCommentBoard }
/>
<Comments
key={ getSelectedBlockClientId() }
threads={ comments }
onEditComment={ onEditComment }
onAddReply={ addNewComment }
onCommentDelete={ onCommentDelete }
onCommentResolve={ onCommentResolve }
showCommentBoard={ showCommentBoard }
setShowCommentBoard={ setShowCommentBoard }
canvasSidebar={ canvasSidebar }
/>
</div>
);
Expand Down Expand Up @@ -296,19 +297,23 @@ export default function CollabSidebar() {
return { resultComments: [], sortedThreads: [] };
}

const blockCommentIds = getCommentIdsFromBlocks( blocks );
const blockCommentIdMap = new Map(
blockCommentIds.map( ( item ) => [ item.commentID, item ] )
);

const updatedResult = result.map( ( item ) => ( {
...item,
reply: [ ...item.reply ].reverse(),
clientId: blockCommentIdMap.get( item.id )?.clientID,
} ) );

const blockCommentIds = getCommentIdsFromBlocks( blocks );

const threadIdMap = new Map(
updatedResult.map( ( thread ) => [ thread.id, thread ] )
);

const sortedComments = blockCommentIds
.map( ( id ) => threadIdMap.get( id ) )
.map( ( item ) => threadIdMap.get( item.commentID ) )
.filter( ( thread ) => thread !== undefined );

return { resultComments: updatedResult, sortedThreads: sortedComments };
Expand Down Expand Up @@ -367,6 +372,7 @@ export default function CollabSidebar() {
styles={ {
backgroundColor,
} }
canvasSidebar
/>
</PluginSidebar>
</>
Expand Down
10 changes: 9 additions & 1 deletion packages/editor/src/components/collab-sidebar/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@

.editor-collab-sidebar {
height: 100%;
overflow: hidden;

.editor-collab-sidebar-panel {
&__thread {
position: absolute;
width: calc(100% - 32px);
}
}
}

.editor-collab-sidebar-panel {
padding: $grid-unit-20;
height: 100%;
height: 100vw;

&__thread {
position: relative;
Expand Down
5 changes: 4 additions & 1 deletion packages/editor/src/components/collab-sidebar/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ export function getCommentIdsFromBlocks( blocks ) {
block.attributes.blockCommentId &&
! commentIds.includes( block.attributes.blockCommentId )
) {
commentIds.push( block.attributes.blockCommentId );
commentIds.push( {
clientID: block.clientId,
commentID: block.attributes.blockCommentId,
} );
}

// Recursively check inner blocks
Expand Down
Loading