diff --git a/app/javascript/mastodon/components/account.tsx b/app/javascript/mastodon/components/account.tsx index 375f759f42..8397695a44 100644 --- a/app/javascript/mastodon/components/account.tsx +++ b/app/javascript/mastodon/components/account.tsx @@ -71,6 +71,7 @@ interface AccountProps { minimal?: boolean; defaultAction?: 'block' | 'mute'; withBio?: boolean; + withMenu?: boolean; } export const Account: React.FC = ({ @@ -80,6 +81,7 @@ export const Account: React.FC = ({ minimal, defaultAction, withBio, + withMenu = true, }) => { const intl = useIntl(); const { signedIn } = useIdentity(); @@ -225,9 +227,10 @@ export const Account: React.FC = ({ ); } - let button: React.ReactNode, dropdown: React.ReactNode; + let button: React.ReactNode; + let dropdown: React.ReactNode; - if (menu.length > 0) { + if (menu.length > 0 && withMenu) { dropdown = ( = ({ } return ( -
-
- -
- {account ? ( - +
+
+
+ +
+ {account ? ( + + ) : ( + + )} +
+ +
+ + + {!minimal && ( +
+ {account ? ( + <> + {' '} + {verification} {muteTimeRemaining} + + ) : ( + + )} +
+ )} +
+ + + {account && + withBio && + (account.note.length > 0 ? ( +
) : ( - - )} -
- -
- - - {!minimal && ( -
- {account ? ( - <> - {' '} - {verification} {muteTimeRemaining} - - ) : ( - - )} +
+
- )} -
- + ))} +
{!minimal && (
@@ -323,22 +352,6 @@ export const Account: React.FC = ({
)}
- - {account && - withBio && - (account.note.length > 0 ? ( -
- ) : ( -
- -
- ))}
); }; diff --git a/app/javascript/mastodon/components/avatar.tsx b/app/javascript/mastodon/components/avatar.tsx index fb331813a9..2ae66ffa11 100644 --- a/app/javascript/mastodon/components/avatar.tsx +++ b/app/javascript/mastodon/components/avatar.tsx @@ -18,6 +18,7 @@ interface Props { withLink?: boolean; counter?: number | string; counterBorderColor?: string; + className?: string; } export const Avatar: React.FC = ({ @@ -27,6 +28,7 @@ export const Avatar: React.FC = ({ inline = false, withLink = false, style: styleFromParent, + className, counter, counterBorderColor, }) => { @@ -52,7 +54,7 @@ export const Avatar: React.FC = ({ const avatar = (
{ - const intl = useIntl(); - const account = useSelector(state => state.getIn(['accounts', id])); - const dispatch = useDispatch(); - - const handleDismiss = useCallback(() => { - dispatch(dismissSuggestion({ accountId: id })); - }, [id, dispatch]); - - let label; - - switch (source) { - case 'friends_of_friends': - label = ; - break; - case 'similar_to_recently_followed': - label = ; - break; - case 'featured': - label = ; - break; - case 'most_followed': - label = ; - break; - case 'most_interactions': - label = ; - break; - } - - return ( -
-
- {label} -
- -
- - -
-
- - - -
-
-
-
- ); -}; - -Card.propTypes = { - id: PropTypes.string.isRequired, - source: PropTypes.oneOf(['friends_of_friends', 'similar_to_recently_followed', 'featured', 'most_followed', 'most_interactions']), -}; diff --git a/app/javascript/mastodon/features/explore/components/card.tsx b/app/javascript/mastodon/features/explore/components/card.tsx new file mode 100644 index 0000000000..9cf128100e --- /dev/null +++ b/app/javascript/mastodon/features/explore/components/card.tsx @@ -0,0 +1,124 @@ +import { useCallback } from 'react'; + +import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; + +import { Link } from 'react-router-dom'; + +import CloseIcon from '@/material-icons/400-24px/close.svg?react'; +import { dismissSuggestion } from 'mastodon/actions/suggestions'; +import { Avatar } from 'mastodon/components/avatar'; +import { DisplayName } from 'mastodon/components/display_name'; +import { FollowButton } from 'mastodon/components/follow_button'; +import { IconButton } from 'mastodon/components/icon_button'; +import { domain } from 'mastodon/initial_state'; +import { useAppDispatch, useAppSelector } from 'mastodon/store'; + +const messages = defineMessages({ + dismiss: { + id: 'follow_suggestions.dismiss', + defaultMessage: "Don't show again", + }, +}); + +type SuggestionSource = + | 'friends_of_friends' + | 'similar_to_recently_followed' + | 'featured' + | 'most_followed' + | 'most_interactions'; + +export const Card: React.FC<{ id: string; source: SuggestionSource }> = ({ + id, + source, +}) => { + const intl = useIntl(); + const account = useAppSelector((state) => state.accounts.get(id)); + const dispatch = useAppDispatch(); + + const handleDismiss = useCallback(() => { + void dispatch(dismissSuggestion({ accountId: id })); + }, [id, dispatch]); + + let label; + + switch (source) { + case 'friends_of_friends': + label = ( + + ); + break; + case 'similar_to_recently_followed': + label = ( + + ); + break; + case 'featured': + label = ( + + ); + break; + case 'most_followed': + label = ( + + ); + break; + case 'most_interactions': + label = ( + + ); + break; + } + + if (!account) { + return null; + } + + return ( +
+
{label}
+ +
+ + + + +
+ + +
+
+
+ ); +}; diff --git a/app/javascript/mastodon/features/onboarding/follows.tsx b/app/javascript/mastodon/features/onboarding/follows.tsx index 703a4449be..d30834d0b6 100644 --- a/app/javascript/mastodon/features/onboarding/follows.tsx +++ b/app/javascript/mastodon/features/onboarding/follows.tsx @@ -170,7 +170,7 @@ export const Follows: React.FC<{ } > {displayedAccountIds.map((accountId) => ( - + ))} diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 8e4c721ed7..c56fbd6365 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2133,6 +2133,16 @@ body > [data-popper-placement] { display: flex; gap: 10px; align-items: center; + justify-content: end; +} + +.account__wrapper--with-bio { + align-items: start; +} + +.account__info-wrapper { + flex: 1 1 auto; + min-width: 0; } .account__avatar { @@ -2141,6 +2151,11 @@ body > [data-popper-placement] { border-radius: var(--avatar-border-radius); background: var(--surface-background-color); + @container (width < 360px) { + width: 35px !important; + height: 35px !important; + } + img { width: 100%; height: 100%; @@ -2266,7 +2281,7 @@ a .account__avatar { } .account__relationship, -.explore__suggestions__card { +.explore-suggestions-card { .icon-button { border: 1px solid var(--background-border-color); border-radius: 4px; @@ -3217,7 +3232,7 @@ a.account__display-name { } } -.explore__suggestions__card { +.explore-suggestions-card { padding: 12px 16px; gap: 8px; display: flex; @@ -3229,60 +3244,77 @@ a.account__display-name { } &__source { - padding-inline-start: 60px; font-size: 13px; line-height: 16px; color: $dark-text-color; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; + + @container (width >= 400px) { + padding-inline-start: 60px; + } } &__body { display: flex; gap: 12px; align-items: center; + justify-content: end; + } - &__main { - flex: 1 1 auto; - display: flex; - flex-direction: column; - gap: 8px; - min-width: 0; + &__avatar { + flex-shrink: 0; - &__name-button { - display: flex; - align-items: center; - gap: 8px; + @container (width < 360px) { + width: 35px !important; + height: 35px !important; + } + } - &__name { - display: block; - color: inherit; - text-decoration: none; - flex: 1 1 auto; - min-width: 0; - } + &__link { + flex: 1 1 auto; + display: flex; + gap: 12px; + align-items: center; + text-decoration: none; + min-width: 0; - .button { - min-width: 80px; - } - - .display-name { - font-size: 15px; - line-height: 20px; - color: $secondary-text-color; - - strong { - font-weight: 700; - } - - &__account { - color: $darker-text-color; - display: block; - } - } + &:hover, + &:focus-visible { + .display-name__html { + text-decoration: underline; } } + + .display-name { + font-size: 15px; + line-height: 20px; + color: $secondary-text-color; + + strong { + font-weight: 700; + } + + &__account { + color: $darker-text-color; + display: block; + } + } + } + + &__actions { + display: flex; + align-items: center; + gap: 8px; + justify-content: end; + + .button { + min-width: 80px; + } + } + + &__dismiss-button { + @container (width < 400px) { + display: none; + } } }