0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-08 02:52:39 -05:00

Improved ActivityPub design (#22051)

ref https://linear.app/ghost/issue/AP-677/standardize-border-radius-used-in-avatars, https://linear.app/ghost/issue/AP-680/standardize-font-sizes-colors-and-weights, https://linear.app/ghost/issue/AP-676/improve-the-sidebar-widget

- Ensured consistent use of border-radius in avatars
- Removed onClick for large avatars, since we only use them when you're already viewing someone's profile
- Updated font colors, weights and sizes for consistency
- Updated design of the sidebar widget in (simpler design, less lines, tighter spacing=
- "Explore" button looks more like what we use in settings and dashboard
This commit is contained in:
Djordje Vlaisavljevic 2025-01-23 17:35:05 +00:00 committed by GitHub
parent 19d9c3e3e2
commit 8c2e62dc23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 28 additions and 30 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@tryghost/admin-x-activitypub",
"version": "0.3.53",
"version": "0.3.54",
"license": "MIT",
"repository": {
"type": "git",

View file

@ -137,9 +137,9 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
</div>
</div>
<div className={`sticky top-[133px] ml-auto w-full max-w-[300px] max-lg:hidden xxxl:sticky xxxl:right-[40px]`}>
<h2 className='mb-2 text-lg font-semibold'>This is your {layout === 'inbox' ? 'inbox' : 'feed'}</h2>
<p className='mb-6 border-b border-grey-200 pb-6 text-grey-700'>You&apos;ll find {layout === 'inbox' ? 'long-form content' : 'short posts and updates'} from the accounts you follow here.</p>
<h2 className='mb-2 text-lg font-semibold'>You might also like</h2>
<h2 className='mb-1.5 text-lg font-semibold'>This is your {layout === 'inbox' ? 'inbox' : 'feed'}</h2>
<p className='mb-6 text-grey-700'>You&apos;ll find {layout === 'inbox' ? 'long-form content' : 'short posts and updates'} from the accounts you follow here.</p>
<h2 className='mb-1 text-lg font-semibold'>You might also like</h2>
{isLoadingSuggested ? (
<LoadingIndicator size="sm" />
) : (
@ -154,7 +154,7 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
>
<APAvatar author={actor} />
<div className='flex min-w-0 flex-col'>
<span className='block w-full truncate font-bold text-black'>{getName(actor)}</span>
<span className='block w-full truncate font-semibold text-black'>{getName(actor)}</span>
<span className='block w-full truncate text-sm text-grey-600'>{getUsername(actor)}</span>
</div>
</ActivityItem>
@ -165,7 +165,7 @@ const Inbox: React.FC<InboxProps> = ({layout}) => {
})}
</ul>
)}
<Button className='mt-4' color='grey' fullWidth={true} label='Explore' onClick={() => updateRoute('search')} />
<Button className='mt-2' color='green' fullWidth={true} label='Explore &rarr;' link={true} onClick={() => updateRoute('search')} />
</div>
</div>
</>

View file

@ -59,7 +59,7 @@ const AccountSearchResultItem: React.FC<AccountSearchResultItemProps> = ({accoun
}}/>
<div>
<div className='text-grey-600'>
<span className='font-bold text-black'>{account.name} </span>{account.handle}
<span className='font-semibold text-black'>{account.name} </span>{account.handle}
</div>
<div className='text-sm'>{new Intl.NumberFormat().format(account.followerCount)} followers</div>
</div>
@ -124,7 +124,7 @@ const SuggestedProfile: React.FC<SuggestedProfileProps> = ({profile, update}) =>
<APAvatar author={profile.actor}/>
<div>
<div className='text-grey-600'>
<span className='font-bold text-black'>{profile.actor.name} </span>{profile.handle}
<span className='font-semibold text-black'>{profile.actor.name} </span>{profile.handle}
</div>
<div className='text-sm'>{new Intl.NumberFormat().format(profile.followerCount)} followers</div>
</div>

View file

@ -718,7 +718,7 @@ const ArticleModal: React.FC<ArticleModalProps> = ({
</div>
<div className='relative z-10 flex w-full min-w-0 flex-col overflow-visible text-[1.5rem]'>
<div className='flex w-full'>
<span className='min-w-0 truncate whitespace-nowrap font-bold'>{actor.name}</span>
<span className='min-w-0 truncate whitespace-nowrap font-semibold'>{actor.name}</span>
</div>
<div className='flex w-full'>
<span className='text-grey-700 after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]'>{getUsername(actor)}</span>

View file

@ -7,7 +7,6 @@ import APAvatar from '../global/APAvatar';
import FeedItemStats from './FeedItemStats';
import clsx from 'clsx';
import getReadingTime from '../../utils/get-reading-time';
import getRelativeTimestamp from '../../utils/get-relative-timestamp';
import getUsername from '../../utils/get-username';
import stripHtml from '../../utils/strip-html';
import {handleProfileClick} from '../../utils/handle-profile-click';
@ -161,8 +160,6 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
const timestamp =
new Date(object?.published ?? new Date()).toLocaleDateString('default', {year: 'numeric', month: 'short', day: '2-digit'}) + ', ' + new Date(object?.published ?? new Date()).toLocaleTimeString('default', {hour: '2-digit', minute: '2-digit'});
const date = new Date(object?.published ?? new Date());
const [, setIsCopied] = useState(false);
const contentRef = useRef<HTMLDivElement>(null);
@ -324,7 +321,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
</div>
<div className='relative z-10 flex w-full min-w-0 flex-col overflow-visible text-[1.5rem]'>
<div className='flex w-full'>
<span className='min-w-0 truncate whitespace-nowrap font-bold after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]' data-test-activity-heading>{author.name}</span>
<span className='min-w-0 truncate whitespace-nowrap font-semibold after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]' data-test-activity-heading>{author.name}</span>
<div>{renderTimestamp(object)}</div>
</div>
<div className='flex w-full'>
@ -375,7 +372,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
<div className='flex w-full items-center justify-between'>
<div className='relative z-10 flex w-full min-w-0 flex-col overflow-visible'>
<div className='flex'>
<span className='min-w-0 truncate whitespace-nowrap font-bold after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]' data-test-activity-heading>{author.name}</span>
<span className='min-w-0 truncate whitespace-nowrap font-semibold after:mx-1 after:font-normal after:text-grey-700 after:content-["·"]' data-test-activity-heading>{author.name}</span>
<div>{renderTimestamp(object)}</div>
</div>
<div className='flex'>
@ -432,7 +429,7 @@ const FeedItem: React.FC<FeedItemProps> = ({actor, object, layout, type, comment
onClick={e => handleProfileClick(actor, e)}
>{author.name}
</span>
<span className='shrink-0 whitespace-nowrap text-grey-600 before:mr-1 before:content-["·"]' title={`${timestamp}`}>{getRelativeTimestamp(date)}</span>
<span className='shrink-0 whitespace-nowrap text-grey-600 before:mr-1 before:content-["·"]' title={`${timestamp}`}>{renderTimestamp(object)}</span>
</div>
<div className='flex'>
<div className='flex min-h-[73px] w-full min-w-0 flex-col items-start justify-start gap-1'>

View file

@ -21,8 +21,8 @@ interface APAvatarProps {
const APAvatar: React.FC<APAvatarProps> = ({author, size}) => {
let iconSize = 18;
let containerClass = `shrink-0 items-center justify-center relative cursor-pointer z-10 flex ${size === 'lg' ? '' : 'hover:opacity-80'}`;
let imageClass = 'z-10 rounded-md w-10 h-10 object-cover';
let containerClass = `shrink-0 items-center justify-center overflow-hidden relative z-10 flex ${size === 'lg' ? '' : 'hover:opacity-80 cursor-pointer'}`;
let imageClass = 'z-10 object-cover';
const [iconUrl, setIconUrl] = useState(author?.icon?.url);
useEffect(() => {
@ -36,28 +36,30 @@ const APAvatar: React.FC<APAvatarProps> = ({author, size}) => {
switch (size) {
case '2xs':
iconSize = 10;
containerClass = clsx('h-4 w-4 rounded-md ', containerClass);
imageClass = 'z-10 rounded-md w-4 h-4 object-cover';
containerClass = clsx('h-4 w-4 rounded-md', containerClass);
imageClass = clsx('h-4 w-4', imageClass);
break;
case 'xs':
iconSize = 12;
containerClass = clsx('h-6 w-6 rounded-md ', containerClass);
imageClass = 'z-10 rounded-md w-6 h-6 object-cover';
containerClass = clsx('h-6 w-6 rounded-lg', containerClass);
imageClass = clsx('h-6 w-6', imageClass);
break;
case 'notification':
iconSize = 12;
containerClass = clsx('h-9 w-9 rounded-md', containerClass);
imageClass = 'z-10 rounded-xl w-9 h-9 object-cover';
containerClass = clsx('h-9 w-9 rounded-lg', containerClass);
imageClass = clsx('h-9 w-9', imageClass);
break;
case 'sm':
containerClass = clsx('h-10 w-10 rounded-md', containerClass);
containerClass = clsx('h-10 w-10 rounded-xl', containerClass);
imageClass = clsx('h-10 w-10', imageClass);
break;
case 'lg':
containerClass = clsx('h-22 w-22 rounded-xl', containerClass);
imageClass = 'z-10 rounded-xl w-22 h-22 object-cover';
imageClass = clsx('h-22 w-22', imageClass);
break;
default:
containerClass = clsx('h-10 w-10 rounded-md', containerClass);
containerClass = clsx('h-10 w-10 rounded-lg', containerClass);
imageClass = clsx('h-10 w-10', imageClass);
break;
}
@ -79,7 +81,7 @@ const APAvatar: React.FC<APAvatarProps> = ({author, size}) => {
<div
className={containerClass}
title={title}
onClick={onClick}
onClick={size === 'lg' ? undefined : onClick}
>
<img
className={imageClass}

View file

@ -31,14 +31,13 @@ button.ap-like-button:active svg {
.ap-note-content a,
.ap-profile-content a,
.ap-note-content-large a {
color: #2563eb !important;
color: #00A4EB !important;
word-break: break-all;
}
.ap-note-content a:hover,
.ap-profile-content a:hover,
.ap-note-content-large a:hover {
color: #1d4ed8 !important;
text-decoration: underline !important;
}
@ -60,7 +59,7 @@ button.ap-like-button:active svg {
}
.ap-note-content-large > * + * {
margin-top: 1.6rem !important;
margin-top: 1.65rem !important;
}
.ap-note-content > h1 + *,