diff --git a/app/javascript/mastodon/components/empty_state/empty_state.module.scss b/app/javascript/mastodon/components/empty_state/empty_state.module.scss index bdab2f2732..9d1d5a115c 100644 --- a/app/javascript/mastodon/components/empty_state/empty_state.module.scss +++ b/app/javascript/mastodon/components/empty_state/empty_state.module.scss @@ -3,16 +3,20 @@ flex-direction: column; align-items: center; max-width: 600px; - padding: 20px; + padding: 24px; gap: 16px; text-align: center; color: var(--color-text-primary); } .content { + max-width: 300px; + svg, img { - width: 240px; + width: 200px; + aspect-ratio: 1; + object-fit: contain; max-width: 100%; margin-bottom: 16px; } @@ -20,11 +24,14 @@ h3 { font-size: 17px; font-weight: 500; + text-wrap: balance; + line-height: 1.2; } p { - font-size: 15px; margin-top: 8px; + font-size: 15px; color: var(--color-text-secondary); + text-wrap: pretty; } } diff --git a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx index a5bb5878c9..fa16f7dbe2 100644 --- a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx +++ b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx @@ -49,8 +49,14 @@ export const EmptyMessage: React.FC = ({ image={image} title={ + } + message={ + } > @@ -72,7 +78,7 @@ export const EmptyMessage: React.FC = ({ message = ( ); } @@ -93,47 +99,21 @@ export const EmptyMessage: React.FC = ({ /> ); } else { - // Standard other account empty state. - title = ( - - ); - if (hasCollections) { - if (acct) { - message = ( - - ); - } else { - message = ( - - ); - } + if (acct) { + title = ( + + ); } else { - if (acct) { - message = ( - - ); - } else { - message = ( - - ); - } + title = ( + + ); } } diff --git a/app/javascript/mastodon/features/account_featured/components/subheading.module.scss b/app/javascript/mastodon/features/account_featured/components/subheading.module.scss new file mode 100644 index 0000000000..aee5d65af2 --- /dev/null +++ b/app/javascript/mastodon/features/account_featured/components/subheading.module.scss @@ -0,0 +1,37 @@ +.subheading { + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: space-between; + min-height: 52px; + padding: 12px 16px; + font-size: 13px; + font-weight: 500; + text-transform: uppercase; + color: var(--color-text-primary); + background: var(--color-bg-secondary); +} + +.link { + display: flex; + padding-block: 4px; + font-size: 13px; + font-weight: 500; + text-transform: none; + text-decoration: none; + color: inherit; + + &:hover { + text-decoration: underline; + } + + &:focus-visible { + outline: var(--outline-focus-default); + outline-offset: 2px; + } + + :global(.icon) { + width: 18px; + height: 18px; + } +} diff --git a/app/javascript/mastodon/features/account_featured/components/subheading.tsx b/app/javascript/mastodon/features/account_featured/components/subheading.tsx new file mode 100644 index 0000000000..361253b260 --- /dev/null +++ b/app/javascript/mastodon/features/account_featured/components/subheading.tsx @@ -0,0 +1,42 @@ +import type { ComponentPropsWithoutRef } from 'react'; + +import classNames from 'classnames'; +import { Link } from 'react-router-dom'; + +import type { IconProp } from '@/mastodon/components/icon'; +import { Icon } from '@/mastodon/components/icon'; +import { polymorphicForwardRef } from '@/types/polymorphic'; + +import classes from './subheading.module.scss'; + +export const Subheading = polymorphicForwardRef<'h2'>( + ({ as: Component = 'h2', children, className, ...props }, ref) => { + return ( + + {children} + + ); + }, +); + +interface SubheadingLinkProps extends ComponentPropsWithoutRef { + icon: IconProp; +} + +export const SubheadingLink: React.FC = ({ + icon, + children, + className, + ...props +}) => { + return ( + + + {children} + + ); +}; diff --git a/app/javascript/mastodon/features/account_featured/index.tsx b/app/javascript/mastodon/features/account_featured/index.tsx index 244302f209..b8964ec1d3 100644 --- a/app/javascript/mastodon/features/account_featured/index.tsx +++ b/app/javascript/mastodon/features/account_featured/index.tsx @@ -6,9 +6,10 @@ import { useHistory } from 'react-router'; import { List as ImmutableList } from 'immutable'; +import { AccountListItem } from '@/mastodon/components/account_list_item'; import { useAccount } from '@/mastodon/hooks/useAccount'; +import AddIcon from '@/material-icons/400-24px/add.svg?react'; import { fetchEndorsedAccounts } from 'mastodon/actions/accounts'; -import { Account } from 'mastodon/components/account'; import { ColumnBackButton } from 'mastodon/components/column_back_button'; import { LoadingIndicator } from 'mastodon/components/loading_indicator'; import { RemoteHint } from 'mastodon/components/remote_hint'; @@ -28,10 +29,11 @@ import { } from 'mastodon/reducers/slices/collections'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; -import { CollectionListItem } from '../collections/detail/collection_list_item'; +import { CollectionListItem } from '../collections/components/collection_list_item'; import { areCollectionsEnabled } from '../collections/utils'; import { EmptyMessage } from './components/empty_message'; +import { Subheading, SubheadingLink } from './components/subheading'; const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({ multiColumn, @@ -114,14 +116,44 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({ {accountId && ( )} + {!featuredAccountIds.isEmpty() && ( + <> + + + + + {featuredAccountIds.map((featuredAccountId, index) => ( +
+ +
+ ))} +
+ + )} {listedCollections.length > 0 && status === 'idle' && ( <> -

- -

+ +

+ +

+ + + +
{listedCollections.map((item, index) => ( = ({ )} - {!featuredAccountIds.isEmpty() && ( - <> -

- -

- - {featuredAccountIds.map((featuredAccountId, index) => ( -
- -
- ))} -
- - )} diff --git a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx b/app/javascript/mastodon/features/account_timeline/components/tabs.tsx index fc66c39831..b2970412df 100644 --- a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx +++ b/app/javascript/mastodon/features/account_timeline/components/tabs.tsx @@ -8,8 +8,6 @@ import { NavLink } from 'react-router-dom'; import { useAccount } from '@/mastodon/hooks/useAccount'; import { useAccountId } from '@/mastodon/hooks/useAccountId'; -import { areCollectionsEnabled } from '../../collections/utils'; - import classes from './styles.module.scss'; const isActive: Required['isActive'] = (match, location) => @@ -41,14 +39,7 @@ export const AccountTabs: FC = () => { )} {show_featured && ( - {areCollectionsEnabled() ? ( - - ) : ( - - )} + )} diff --git a/app/javascript/mastodon/features/collections/detail/collection_list_item.module.scss b/app/javascript/mastodon/features/collections/components/collection_list_item.module.scss similarity index 96% rename from app/javascript/mastodon/features/collections/detail/collection_list_item.module.scss rename to app/javascript/mastodon/features/collections/components/collection_list_item.module.scss index 7fb3d21bbc..eaee216e6a 100644 --- a/app/javascript/mastodon/features/collections/detail/collection_list_item.module.scss +++ b/app/javascript/mastodon/features/collections/components/collection_list_item.module.scss @@ -1,8 +1,7 @@ .wrapper { display: flex; align-items: start; - margin-inline: 24px; - padding-block: 12px; + padding: 12px 16px; gap: 16px; &:not(.wrapperWithoutBorder) { diff --git a/app/javascript/mastodon/features/collections/detail/collection_list_item.tsx b/app/javascript/mastodon/features/collections/components/collection_list_item.tsx similarity index 97% rename from app/javascript/mastodon/features/collections/detail/collection_list_item.tsx rename to app/javascript/mastodon/features/collections/components/collection_list_item.tsx index 08c04f030a..c680b7924c 100644 --- a/app/javascript/mastodon/features/collections/detail/collection_list_item.tsx +++ b/app/javascript/mastodon/features/collections/components/collection_list_item.tsx @@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { Link } from 'react-router-dom'; +import { CollectionMenu } from '@/mastodon/features/collections/components/collection_menu'; import WarningIcon from '@/material-icons/400-24px/warning.svg?react'; import type { ApiCollectionJSON } from 'mastodon/api_types/collections'; import { AvatarById } from 'mastodon/components/avatar'; @@ -15,7 +16,6 @@ import { useAccount } from 'mastodon/hooks/useAccount'; import { domain } from 'mastodon/initial_state'; import classes from './collection_list_item.module.scss'; -import { CollectionMenu } from './collection_menu'; export const AvatarGrid: React.FC<{ accountIds: (string | undefined)[]; diff --git a/app/javascript/mastodon/features/collections/detail/collection_menu.tsx b/app/javascript/mastodon/features/collections/components/collection_menu.tsx similarity index 100% rename from app/javascript/mastodon/features/collections/detail/collection_menu.tsx rename to app/javascript/mastodon/features/collections/components/collection_menu.tsx diff --git a/app/javascript/mastodon/features/collections/detail/share_modal.module.scss b/app/javascript/mastodon/features/collections/components/share_modal.module.scss similarity index 100% rename from app/javascript/mastodon/features/collections/detail/share_modal.module.scss rename to app/javascript/mastodon/features/collections/components/share_modal.module.scss diff --git a/app/javascript/mastodon/features/collections/detail/share_modal.tsx b/app/javascript/mastodon/features/collections/components/share_modal.tsx similarity index 99% rename from app/javascript/mastodon/features/collections/detail/share_modal.tsx rename to app/javascript/mastodon/features/collections/components/share_modal.tsx index 1b7f4dcf1c..6ae198b0a6 100644 --- a/app/javascript/mastodon/features/collections/detail/share_modal.tsx +++ b/app/javascript/mastodon/features/collections/components/share_modal.tsx @@ -20,7 +20,8 @@ import { } from 'mastodon/components/modal_shell'; import { useAppDispatch } from 'mastodon/store'; -import { AuthorNote } from '.'; +import { AuthorNote } from '../detail'; + import classes from './share_modal.module.scss'; const messages = defineMessages({ diff --git a/app/javascript/mastodon/features/collections/detail/index.tsx b/app/javascript/mastodon/features/collections/detail/index.tsx index 70422f9114..404cd8a074 100644 --- a/app/javascript/mastodon/features/collections/detail/index.tsx +++ b/app/javascript/mastodon/features/collections/detail/index.tsx @@ -23,8 +23,9 @@ import { domain, me } from 'mastodon/initial_state'; import { fetchCollection } from 'mastodon/reducers/slices/collections'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; +import { CollectionMenu } from '../components/collection_menu'; + import { CollectionAccountsList } from './accounts_list'; -import { CollectionMenu } from './collection_menu'; import { useConfirmRevoke } from './revoke_collection_inclusion_modal'; import classes from './styles.module.scss'; @@ -66,7 +67,7 @@ export const AuthorNote: React.FC<{ id: string }> = ({ id }) => { ); }; -export const RevokeControls: React.FC<{ +const RevokeControls: React.FC<{ collection: ApiCollectionJSON; }> = ({ collection }) => { const authorAccount = useAccount(collection.account_id); diff --git a/app/javascript/mastodon/features/collections/index.tsx b/app/javascript/mastodon/features/collections/index.tsx index 82653a22c1..57258d6ff4 100644 --- a/app/javascript/mastodon/features/collections/index.tsx +++ b/app/javascript/mastodon/features/collections/index.tsx @@ -21,7 +21,7 @@ import { } from 'mastodon/reducers/slices/collections'; import { useAppSelector, useAppDispatch } from 'mastodon/store'; -import { CollectionListItem } from './detail/collection_list_item'; +import { CollectionListItem } from './components/collection_list_item'; import { messages as editorMessages } from './editor'; const messages = defineMessages({ diff --git a/app/javascript/mastodon/features/ui/components/column_subheading.jsx b/app/javascript/mastodon/features/ui/components/column_subheading.jsx deleted file mode 100644 index e970a0bfdd..0000000000 --- a/app/javascript/mastodon/features/ui/components/column_subheading.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import PropTypes from 'prop-types'; - -const ColumnSubheading = ({ text }) => { - return ( -
- {text} -
- ); -}; - -ColumnSubheading.propTypes = { - text: PropTypes.string.isRequired, -}; - -export default ColumnSubheading; diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx index 2f3f5ee7c8..0000acb009 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.jsx +++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx @@ -79,7 +79,7 @@ export const MODAL_COMPONENTS = { 'DOMAIN_BLOCK': DomainBlockModal, 'REPORT': ReportModal, 'REPORT_COLLECTION': ReportCollectionModal, - 'SHARE_COLLECTION': () => import('@/mastodon/features/collections/detail/share_modal').then(module => ({ default: module.CollectionShareModal })), + 'SHARE_COLLECTION': () => import('@/mastodon/features/collections/components/share_modal').then(module => ({ default: module.CollectionShareModal })), 'REVOKE_COLLECTION_INCLUSION': () => import('@/mastodon/features/collections/detail/revoke_collection_inclusion_modal').then(module => ({ default: module.RevokeCollectionInclusionModal })), 'ACTIONS': () => Promise.resolve({ default: ActionsModal }), 'EMBED': EmbedModal, diff --git a/app/javascript/mastodon/locales/en-GB.json b/app/javascript/mastodon/locales/en-GB.json index c87e517625..55141b0bf8 100644 --- a/app/javascript/mastodon/locales/en-GB.json +++ b/app/javascript/mastodon/locales/en-GB.json @@ -592,7 +592,7 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", - "empty_column.account_featured.other": "{acct} has not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?", + "empty_column.account_featured.other": "{acct} has not featured anything yet.", "empty_column.account_hides_collections": "This user has chosen not to make this information available", "empty_column.account_suspended": "Account suspended", "empty_column.account_timeline": "No posts here!", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index bb643d8e32..c8095b1f5c 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -45,6 +45,7 @@ "account.featured": "Featured", "account.featured.accounts": "Profiles", "account.featured.collections": "Collections", + "account.featured.new_collection": "New collection", "account.field_overflow": "Show full content", "account.filters.all": "All activity", "account.filters.boosts_toggle": "Show boosts", @@ -606,14 +607,12 @@ "emoji_button.search_results": "Search results", "emoji_button.symbols": "Symbols", "emoji_button.travel": "Travel & Places", - "empty_column.account_featured.other": "{acct} has not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?", - "empty_column.account_featured_other.no_collections_desc": "{acct} hasn’t created any collections yet.", - "empty_column.account_featured_other.title": "Nothing to see here", - "empty_column.account_featured_self.no_collections": "No collections yet", + "empty_column.account_featured.other": "{acct} has not featured anything yet.", "empty_column.account_featured_self.no_collections_button": "Create a collection", "empty_column.account_featured_self.pre_collections": "Stay tuned for Collections", - "empty_column.account_featured_self.pre_collections_desc": "Collections (coming in Mastodon 4.6) allows you to create your own curated lists of accounts to recommend to others.", - "empty_column.account_featured_unknown.no_collections_desc": "This account hasn’t created any collections yet.", + "empty_column.account_featured_self.pre_collections_desc": "Collections (coming in Mastodon 4.6) allow you to create your own curated lists of accounts to recommend to others.", + "empty_column.account_featured_self.showcase_accounts": "Showcase your favorite accounts", + "empty_column.account_featured_self.showcase_accounts_desc": "Collections are curated lists of accounts to help others discover more of the Fediverse.", "empty_column.account_featured_unknown.other": "This account hasn’t featured anything yet.", "empty_column.account_hides_collections": "This user has chosen to not make this information available", "empty_column.account_suspended": "Account suspended", diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index cad0dafef8..e172591ba6 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -4105,15 +4105,6 @@ a.account__display-name { margin: -6px 10px; } -.column-subheading { - background: var(--color-bg-secondary); - color: var(--color-text-secondary); - padding: 12px 24px; - font-size: 13px; - font-weight: 500; - text-transform: uppercase; -} - .getting-started__wrapper { flex: 0 0 auto; }