Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3251dfb
💫 UPDATE: Use updated fields from users endpoint and updated tests
mehmoodak Apr 7, 2026
e26cc0e
💫 UPDATE: types
mehmoodak Apr 7, 2026
34ec99c
UPDATE: Makes site icons square and avoid mixing it with user avatars
mehmoodak Mar 27, 2026
1fa66d6
👌 IMPROVE: add personal feedback
mehmoodak Mar 27, 2026
9269280
🐛 FIX: classname
mehmoodak Apr 1, 2026
597aacf
UPDATE: Makes site icons square and avoid mixing it with user avatars
mehmoodak Mar 27, 2026
21c6255
👌 IMPROVE: user avatar navigations
mehmoodak Mar 30, 2026
4daea00
💫 UPDATE: renmae UserAvatar iconSize prop to size
mehmoodak Mar 31, 2026
aacb92f
👌 IMPROVE: personal feedback
mehmoodak Apr 1, 2026
5423007
🐛 FIX: Use wpcom_login for user profile navigation
mehmoodak Apr 2, 2026
2d53769
🐛 FIX: Use wpcom_id field to get user info and not ID field
mehmoodak Apr 2, 2026
2be7b34
Refactor: PrimaryBlogCard to TypeScript
mehmoodak Apr 1, 2026
c12729c
Refactor: GravatarHeader to TypeScript
mehmoodak Apr 1, 2026
324a4bf
Refactor: Gravatar RecommendedBlogs to TypeScript
mehmoodak Apr 1, 2026
bdb8bf6
Refactor: Gravatar HovercardContent to TypeScript
mehmoodak Apr 1, 2026
1f2a0b5
Refactor: GravatarWithHovercards to TypeScript
mehmoodak Apr 1, 2026
07009a4
Implement custom UserHovercard
mehmoodak Apr 4, 2026
2d68279
🐛 FIX: user avatar fixes
mehmoodak Apr 4, 2026
32e4e65
🐛 FIX: gravatar fixes
mehmoodak Apr 4, 2026
2051091
Add PreloadedImage component
mehmoodak Apr 4, 2026
739b5de
Add useUserHovercardQuery
mehmoodak Apr 4, 2026
14b9855
💫 UPDATE: Use user hovercard query for the component
mehmoodak Apr 4, 2026
55c4a53
🐛 FIX: minor UI tweaks
mehmoodak Apr 4, 2026
cfa1d0f
➕ ADDS: search users via gravatar email hash as well
mehmoodak Apr 4, 2026
36fe7ef
➕ ADDS: gravatar fallback
mehmoodak Apr 4, 2026
9a4f97f
💫 UPDATE: Use updated fields from users endpoint and updated tests
mehmoodak Apr 7, 2026
ee14a23
💫 UPDATE: types
mehmoodak Apr 7, 2026
672bcb9
Add and use useReaderUserQuery in User Profile page
mehmoodak Apr 7, 2026
9609a14
🐛 FIX: useGetReaderUserQuery returning empty string
mehmoodak Apr 7, 2026
9f34e52
👌 IMPROVE: loader
mehmoodak Apr 7, 2026
58e7a0a
Merge branch 'READ-468/use-tanstack-query-on-user-profile-page' into …
mehmoodak Apr 7, 2026
dadd50c
💫 UPDATE: use useGetReaderUserQuery for user hovercard
mehmoodak Apr 7, 2026
c102ba2
🐛 FIX: overflows
mehmoodak Apr 7, 2026
803f3c5
🐛 FIX: styling and navigations
mehmoodak Apr 7, 2026
9d5041a
🐛 FIX: stale state of subscribe button
mehmoodak Apr 7, 2026
79b476e
Merge branch 'READ-468/use-tanstack-query-on-user-profile-page' into …
mehmoodak Apr 7, 2026
b1924c3
🐛 FIX: personal feedback
mehmoodak Apr 7, 2026
d59674d
🐛 FIX: styles
mehmoodak Apr 7, 2026
3674dd2
🐛 FIX: use PreloadedImage in UserAvatar
mehmoodak Apr 7, 2026
71f5ab8
➕ ADDS: tests for all new components
mehmoodak Apr 8, 2026
627ff40
🐛 FIX: tests
mehmoodak Apr 8, 2026
94020d5
👌 IMPROVE: translations
mehmoodak Apr 8, 2026
001268d
🐛 FIX: popover click propagation
mehmoodak Apr 8, 2026
a91b5b6
🐛 FIX: tests
mehmoodak Apr 8, 2026
71fb852
🐛 FIX: tests
mehmoodak Apr 8, 2026
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
15 changes: 10 additions & 5 deletions client/blocks/comments/form.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import './form.scss';
import { Button, FormInputValidation } from '@automattic/components';
import clsx from 'clsx';
import { localize, useTranslate } from 'i18n-calypso';
import PropTypes from 'prop-types';
import { Component } from 'react';
import { connect } from 'react-redux';
import UserAvatar from 'calypso/blocks/user-avatar';
import FormFieldset from 'calypso/components/forms/form-fieldset';
import GravatarWithHovercards from 'calypso/components/gravatar-with-hovercards';
import { ProtectFormGuard } from 'calypso/lib/protect-form';
import { recordAction, recordGaEvent, recordTrackForPost, getLocation } from 'calypso/reader/stats';
import { writeComment, deleteComment, replyComment } from 'calypso/state/comments/actions';
Expand All @@ -15,8 +16,6 @@ import { getCurrentRoute } from 'calypso/state/selectors/get-current-route';
import { getPreviousPath } from 'calypso/state/selectors/get-previous-path';
import AutoresizingFormTextarea from './autoresizing-form-textarea';

import './form.scss';

const noop = () => {};

function PostCommentFormError( { type } ) {
Expand Down Expand Up @@ -149,7 +148,7 @@ class PostCommentForm extends Component {
}

render() {
const { post, error, errorType, translate } = this.props;
const { post, error, errorType, translate, currentUser } = this.props;

// Don't display the form if comments are closed
if ( post && post.discussion && post.discussion.comments_open === false ) {
Expand All @@ -174,7 +173,13 @@ class PostCommentForm extends Component {
<form className="comments__form">
<ProtectFormGuard isChanged={ this.hasCommentText() } />
<FormFieldset>
<GravatarWithHovercards user={ this.props.currentUser } />
<UserAvatar
user={ {
avatar_URL: currentUser?.avatar_URL,
wpcom_login: currentUser?.username,
} }
hideHovercard
/>
<AutoresizingFormTextarea
value={ this.getCommentText() }
placeholder={ translate( 'Add a comment…' ) }
Expand Down
4 changes: 2 additions & 2 deletions client/blocks/comments/form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
padding: 0 0 0 42px;
margin-top: 24px;

.gravatar {
.user-avatar {
position: absolute;
top: 0;
left: 0;
Expand All @@ -16,7 +16,7 @@
padding: 5px 10px;
}

button:not(.components-button) {
button:not(.components-button):not(.follow-button) {
opacity: 0;
position: absolute;
margin: 16px 0 0;
Expand Down
37 changes: 21 additions & 16 deletions client/blocks/comments/post-comment.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import './post-comment.scss';
import config from '@automattic/calypso-config';
import { getUrlParts } from '@automattic/calypso-url';
import { Gridicon, TimeSince } from '@automattic/components';
import { isURL, getProtocol, getAuthority } from '@wordpress/url';
import { Icon, external } from '@wordpress/icons';
import { isURL, getAuthority, prependHTTPS } from '@wordpress/url';
import clsx from 'clsx';
import { translate } from 'i18n-calypso';
import { get, some, flatMap } from 'lodash';
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { connect } from 'react-redux';
import ConversationCaterpillar from 'calypso/blocks/conversation-caterpillar';
import GravatarWithHovercards from 'calypso/components/gravatar-with-hovercards';
import UserAvatar from 'calypso/blocks/user-avatar';
import { decodeEntities } from 'calypso/lib/formatting';
import { navigate } from 'calypso/lib/navigate';
import { createAccountUrl } from 'calypso/lib/paths';
Expand All @@ -29,8 +31,6 @@ import PostCommentContent from './post-comment-content';
import PostCommentWithError from './post-comment-with-error';
import PostTrackback from './post-trackback';

import './post-comment.scss';

const noop = () => {};

/**
Expand Down Expand Up @@ -319,12 +319,10 @@ class PostComment extends PureComponent {
} else if ( commentAuthor.site_ID ) {
commentAuthorUrl = getStreamUrl( null, commentAuthor.site_ID );
} else {
const urlToCheck = commentAuthor?.URL;
const urlToCheck = prependHTTPS( commentAuthor?.URL );
if ( urlToCheck && isURL( urlToCheck ) ) {
const protocol = getProtocol( urlToCheck );
const domain = getAuthority( urlToCheck );
// isURL uses URL() which allows '%20' in Chromium but not Firefox, so we check ourselves.
if ( protocol === 'https:' && ! domain.includes( '%' ) ) {
if ( ! domain.includes( '%' ) ) {
commentAuthorUrl = urlToCheck;
}
}
Expand All @@ -334,7 +332,9 @@ class PostComment extends PureComponent {
};

renderAuthorTag = ( { authorName, authorUrl, commentId, className } ) => {
return authorUrl ? (
const isExternalUrl = authorUrl?.startsWith( '/reader/users/' ) === false;

return authorUrl && ! isExternalUrl ? (
<a
href={ authorUrl }
className={ className }
Expand All @@ -346,6 +346,17 @@ class PostComment extends PureComponent {
) : (
<strong className={ className } id={ `comment-${ commentId }` }>
{ authorName }

{ isExternalUrl && (
<a
className="comments__external-link"
href={ authorUrl }
target="_blank"
rel="noopener noreferrer"
>
<Icon icon={ external } size={ 18 } />
</a>
) }
</strong>
);
};
Expand Down Expand Up @@ -446,13 +457,7 @@ class PostComment extends PureComponent {
return (
<li className={ postCommentClassnames }>
<div className="comments__comment-author">
{ commentAuthorUrl ? (
<a href={ commentAuthorUrl } onClick={ this.handleAuthorClick } tabIndex={ -1 }>
<GravatarWithHovercards user={ comment.author } />
</a>
) : (
<GravatarWithHovercards user={ comment.author } />
) }
<UserAvatar user={ comment.author } />

{ this.renderAuthorTag( {
authorUrl: commentAuthorUrl,
Expand Down
17 changes: 13 additions & 4 deletions client/blocks/comments/post-comment.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
&.depth-2 {
padding-left: 42px;

> .comments__comment-author .gravatar {
> .comments__comment-author .user-avatar {
left: 0;
}
}
Expand Down Expand Up @@ -68,10 +68,9 @@
font-size: $font-body-small;
font-weight: 600;

.gravatar {
border-radius: 48px; /* stylelint-disable-line scales/radii */
.user-avatar {
position: absolute;
top: 8px;
top: 4px;
left: -41px;
}
}
Expand All @@ -95,6 +94,16 @@ a.comments__comment-username {
}
}

.comments__external-link {
margin-left: 2px;
position: relative;
top: 3px;

svg {
fill: var(--color-link);
}
}

.comments__comment-trackbackicon {
background-color: var(--color-neutral-0);
border-radius: 50%;
Expand Down
1 change: 0 additions & 1 deletion client/blocks/comments/post-trackback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export default function PostTrackback( props: PostTrackbackProps ): JSX.Element
return null;
}
const unescapedAuthorName = unescape( get( comment, 'author.name', '' ) );

const authorUrlLink = comment.author?.wpcom_login
? getUserProfileUrl( comment.author.wpcom_login )
: comment.author?.URL;
Expand Down
6 changes: 1 addition & 5 deletions client/blocks/reader-full-post/header-meta.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ const ReaderFullPostHeaderMeta = ( { post, author, siteName, feedId, siteId } )

return (
<div className="reader-full-post__header-meta-wrapper">
<UserAvatar
className="reader-full-post__header-meta-avatars"
user={ author }
iconSize={ 40 }
/>
<UserAvatar user={ author } size={ 40 } />
<div className="reader-full-post__header-meta-info">
<div className="reader-full-post__header-meta-line-1">
{ showAuthorLink && (
Expand Down
14 changes: 0 additions & 14 deletions client/blocks/reader-full-post/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,6 @@ $reader-full-post-desktop-min: $reader-full-post-sidebar-width + $reader-full-po
}
}

.reader-full-post__header-meta-avatars {
flex-shrink: 0;

.gravatar {
border-radius: 50%;
width: 40px;
height: 40px;
}

.gridicons-globe {
fill: var( --color-neutral-70 );
}
}

.reader-full-post__header-meta-info {
flex: 1;
min-width: 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import UserAvatar from 'calypso/blocks/user-avatar';
import { useTranslate } from 'i18n-calypso';

const ReaderSubscriptionListItemPlaceholder = (): JSX.Element => {
const translate = useTranslate();

const ReaderSubscriptionListItemPlaceholder = () => {
return (
<div className="reader-subscription-list-item reader-subscription-list-item__placeholder">
<div>
<UserAvatar isCompact iconSize={ 32 } />
<span className="reader-subscription-list-item__site-avatar is-placeholder"></span>
</div>
<div className="reader-subscription-list-item__byline">
<span className="reader-subscription-list-item__site-title is-placeholder">Site title</span>
<span className="reader-subscription-list-item__site-title is-placeholder">
{ translate( 'Site title' ) }
</span>
<div className="reader-subscription-list-item__site-excerpt is-placeholder">
Description of the site
{ translate( 'The description of the site.' ) }
</div>
<span className="reader-subscription-list-item__by-text is-placeholder">
by author name
{ translate( 'Author name' ) }
</span>
<span className="reader-subscription-list-item__site-url is-placeholder">
www.example.com
</span>
</div>
<div className="reader-subscription-list-item__options">
<div className="reader-subscription-list-item__follow">Follow here</div>
<div className="reader-subscription-list-item__follow">{ translate( 'Follow here' ) }</div>
</div>
</div>
);
Expand Down
15 changes: 8 additions & 7 deletions client/blocks/reader-subscription-list-item/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@
-webkit-box-orient: vertical;
}

.reader-subscription-list-item .gravatar {
float: left;
height: 32px;
min-height: 32px;
min-width: 32px;
}

.reader-subscription-list-item .site-icon {
margin-top: 4px;
}
Expand Down Expand Up @@ -182,6 +175,7 @@

// Placeholders
.reader-subscription-list-item.reader-subscription-list-item__placeholder {
.reader-subscription-list-item__site-avatar,
.reader-subscription-list-item__site-title,
.reader-subscription-list-item__site-excerpt,
.reader-subscription-list-item__by-text,
Expand All @@ -195,6 +189,13 @@
max-width: 80%;
}

.reader-subscription-list-item__site-avatar {
border-radius: 4px;
display: inline-block;
width: 32px;
height: 32px;
}

.reader-subscription-list-item__site-title {
max-width: 60%;
}
Expand Down
2 changes: 1 addition & 1 deletion client/blocks/reader-suggested-follows/dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ const ReaderSuggestedFollowsDialog = ( {
<ReaderSitesList
sites={ data }
followSource="reader-recommended-follows-dialog__recommended-feeds-list"
iconSize={ 48 }
siteIconSize={ 48 }
/>
</li>
) }
Expand Down
4 changes: 2 additions & 2 deletions client/blocks/reader-suggested-follows/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
padding: 0 32px 10px 32px;
}

;
.reader-recommended-follows-dialog__body {
scrollbar-width: thin;
scrollbar-gutter: stable;
Expand Down Expand Up @@ -171,8 +170,9 @@

.is-placeholder.placeholder-title {
width: 50%;
height: 48
height: 48px;
}

.is-placeholder.placeholder-description {
height: 24px;
}
Expand Down
2 changes: 0 additions & 2 deletions client/blocks/user-avatar/docs/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ const UserAvatarExample = (): JSX.Element => {
return (
<div className="design-assets__group">
<UserAvatar user={ user } />
<h4>Compact</h4>
<UserAvatar user={ user } isCompact />
</div>
);
};
Expand Down
Loading
Loading