Add AvatarStack component
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
0ba4a63106
commit
13cd0b726e
2 changed files with 66 additions and 14 deletions
40
app/soapbox/components/avatar-stack.tsx
Normal file
40
app/soapbox/components/avatar-stack.tsx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Avatar, HStack } from 'soapbox/components/ui';
|
||||||
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
import { makeGetAccount } from 'soapbox/selectors';
|
||||||
|
|
||||||
|
import type { Account } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
const getAccount = makeGetAccount();
|
||||||
|
|
||||||
|
interface IAvatarStack {
|
||||||
|
accountIds: ImmutableOrderedSet<string>
|
||||||
|
limit?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const AvatarStack: React.FC<IAvatarStack> = ({ accountIds, limit = 3 }) => {
|
||||||
|
const accounts = useAppSelector(state => ImmutableList(accountIds.slice(0, limit).map(accountId => getAccount(state, accountId)).filter(account => account))) as ImmutableList<Account>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HStack className='relative' aria-hidden>
|
||||||
|
{accounts.map((account, i) => (
|
||||||
|
<div
|
||||||
|
className={clsx('relative', { '-ml-3': i !== 0 })}
|
||||||
|
key={account.id}
|
||||||
|
style={{ zIndex: limit - i }}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
className='ring-1 ring-white dark:ring-primary-900'
|
||||||
|
src={account.avatar}
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</HStack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AvatarStack;
|
|
@ -5,8 +5,9 @@ import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { fetchAccountFamiliarFollowers } from 'soapbox/actions/familiar-followers';
|
import { fetchAccountFamiliarFollowers } from 'soapbox/actions/familiar-followers';
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
|
import AvatarStack from 'soapbox/components/avatar-stack';
|
||||||
import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper';
|
import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper';
|
||||||
import { Text } from 'soapbox/components/ui';
|
import { HStack, Text } from 'soapbox/components/ui';
|
||||||
import VerificationBadge from 'soapbox/components/verification-badge';
|
import VerificationBadge from 'soapbox/components/verification-badge';
|
||||||
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||||
import { makeGetAccount } from 'soapbox/selectors';
|
import { makeGetAccount } from 'soapbox/selectors';
|
||||||
|
@ -30,7 +31,7 @@ const ProfileFamiliarFollowers: React.FC<IProfileFamiliarFollowers> = ({ account
|
||||||
if (me && features.familiarFollowers) {
|
if (me && features.familiarFollowers) {
|
||||||
dispatch(fetchAccountFamiliarFollowers(account.id));
|
dispatch(fetchAccountFamiliarFollowers(account.id));
|
||||||
}
|
}
|
||||||
}, []);
|
}, [account.id]);
|
||||||
|
|
||||||
const openFamiliarFollowersModal = () => {
|
const openFamiliarFollowersModal = () => {
|
||||||
dispatch(openModal('FAMILIAR_FOLLOWERS', {
|
dispatch(openModal('FAMILIAR_FOLLOWERS', {
|
||||||
|
@ -44,10 +45,18 @@ const ProfileFamiliarFollowers: React.FC<IProfileFamiliarFollowers> = ({ account
|
||||||
|
|
||||||
const accounts: Array<React.ReactNode> = familiarFollowers.map(account => !!account && (
|
const accounts: Array<React.ReactNode> = familiarFollowers.map(account => !!account && (
|
||||||
<HoverRefWrapper accountId={account.id} inline>
|
<HoverRefWrapper accountId={account.id} inline>
|
||||||
<Link className='mention' to={`/@${account.acct}`}>
|
<Link className='mention inline-block' to={`/@${account.acct}`}>
|
||||||
<span dangerouslySetInnerHTML={{ __html: account.display_name_html }} />
|
<HStack space={1} alignItems='center' grow>
|
||||||
|
<Text
|
||||||
|
size='sm'
|
||||||
|
theme='primary'
|
||||||
|
truncate
|
||||||
|
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
||||||
|
/>
|
||||||
|
{/* <span dangerouslySetInnerHTML={{ __html: account.display_name_html }} /> */}
|
||||||
|
|
||||||
{account.verified && <VerificationBadge />}
|
{account.verified && <VerificationBadge />}
|
||||||
|
</HStack>
|
||||||
</Link>
|
</Link>
|
||||||
</HoverRefWrapper>
|
</HoverRefWrapper>
|
||||||
)).toArray();
|
)).toArray();
|
||||||
|
@ -65,15 +74,18 @@ const ProfileFamiliarFollowers: React.FC<IProfileFamiliarFollowers> = ({ account
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text theme='muted' size='sm'>
|
<HStack space={2} alignItems='center'>
|
||||||
<FormattedMessage
|
<AvatarStack accountIds={familiarFollowerIds} />
|
||||||
id='account.familiar_followers'
|
<Text theme='muted' size='sm'>
|
||||||
defaultMessage='Followed by {accounts}'
|
<FormattedMessage
|
||||||
values={{
|
id='account.familiar_followers'
|
||||||
accounts: <FormattedList type='conjunction' value={accounts} />,
|
defaultMessage='Followed by {accounts}'
|
||||||
}}
|
values={{
|
||||||
/>
|
accounts: <FormattedList type='conjunction' value={accounts} />,
|
||||||
</Text>
|
}}
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue