diff --git a/packages/core-data/src/hooks/use-post-editor-awareness-state.ts b/packages/core-data/src/hooks/use-post-editor-awareness-state.ts index 5acd74939313a9..3b64ade4cd0211 100644 --- a/packages/core-data/src/hooks/use-post-editor-awareness-state.ts +++ b/packages/core-data/src/hooks/use-post-editor-awareness-state.ts @@ -96,7 +96,7 @@ function usePostEditorAwarenessState( * @param postType - The type of the post. * @return {ActiveUser[]} The active users. */ -export function useActiveUsers( +export function useActiveCollaborators( postId: number | null, postType: string | null ): ActiveUser[] { diff --git a/packages/core-data/src/private-apis.js b/packages/core-data/src/private-apis.js index e9fcf36f7e6090..917af885a9b8cd 100644 --- a/packages/core-data/src/private-apis.js +++ b/packages/core-data/src/private-apis.js @@ -3,10 +3,12 @@ */ import { useEntityRecordsWithPermissions } from './hooks/use-entity-records'; import { RECEIVE_INTERMEDIATE_RESULTS } from './utils'; +import { useActiveCollaborators } from './hooks/use-post-editor-awareness-state'; import { lock } from './lock-unlock'; export const privateApis = {}; lock( privateApis, { useEntityRecordsWithPermissions, RECEIVE_INTERMEDIATE_RESULTS, + useActiveCollaborators, } ); diff --git a/packages/editor/src/components/collaborators-presence/avatar.tsx b/packages/editor/src/components/collaborators-presence/avatar.tsx new file mode 100644 index 00000000000000..73cfe7ade43d0f --- /dev/null +++ b/packages/editor/src/components/collaborators-presence/avatar.tsx @@ -0,0 +1,50 @@ +import { clsx } from 'clsx'; +import { type PostEditorAwarenessState } from '../../../../core-data/src/awareness/types'; +import './styles/avatar.scss'; + +type AvatarSize = 'small' | 'medium'; + +interface AvatarProps { + userInfo: PostEditorAwarenessState[ 'userInfo' ]; + showUserColorBorder?: boolean; + size?: AvatarSize; +} + +/** + * Renders a circular avatar bubble for a user with an optional border. + * + * @param {Object} props Component props. + * @param {Object} props.userInfo User information. + * @param {boolean} props.showUserColorBorder Whether to show the user color border. + * @param {string} props.size Size of the avatar. + */ +export function Avatar( { + userInfo, + showUserColorBorder, + size = 'small', +}: AvatarProps ) { + const className = clsx( + 'editor-collaborators-presence__avatar', + `editor-collaborators-presence__avatar--${ size }`, + showUserColorBorder && + 'editor-collaborators-presence__avatar--with-color-border' + ); + + const avatarUrl = + userInfo.avatar_urls?.[ 48 ] || + userInfo.avatar_urls?.[ 96 ] || + userInfo.avatar_urls?.[ 24 ]; + + const avatarStyles = { + '--avatar-url': `url(${ avatarUrl })`, + '--user-color': userInfo.color, + } as React.CSSProperties; + + return ( +