[Glitch] Increase clickable area around collection items, refactor ListItem component
Port 2b93a2211f to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
+6
-5
@@ -1,8 +1,7 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
padding: 12px 16px;
|
||||
gap: 16px;
|
||||
--list-item-padding: 16px;
|
||||
--list-item-padding-block: 12px;
|
||||
--list-item-gap: 16px;
|
||||
|
||||
&:not(.wrapperWithoutBorder) {
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
@@ -10,8 +9,10 @@
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
align-self: start;
|
||||
padding: 4px;
|
||||
margin-top: -2px;
|
||||
margin-top: -4px;
|
||||
margin-inline-end: -4px;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
|
||||
+19
-10
@@ -9,7 +9,10 @@ import { CollectionMenu } from 'flavours/glitch/features/collections/components/
|
||||
|
||||
import classes from './collection_list_item.module.scss';
|
||||
|
||||
interface CollectionListItemProps extends CollectionLockupProps {
|
||||
interface CollectionListItemProps extends Omit<
|
||||
CollectionLockupProps,
|
||||
'sideContent'
|
||||
> {
|
||||
withoutBorder?: boolean;
|
||||
positionInList: number;
|
||||
listSize: number;
|
||||
@@ -20,6 +23,7 @@ export const CollectionListItem: React.FC<CollectionListItemProps> = ({
|
||||
withoutBorder,
|
||||
positionInList,
|
||||
listSize,
|
||||
className,
|
||||
...otherProps
|
||||
}) => {
|
||||
const uniqueId = useId();
|
||||
@@ -29,21 +33,26 @@ export const CollectionListItem: React.FC<CollectionListItemProps> = ({
|
||||
return (
|
||||
<Article
|
||||
focusable
|
||||
className={classNames(
|
||||
classes.wrapper,
|
||||
withoutBorder && classes.wrapperWithoutBorder,
|
||||
)}
|
||||
aria-labelledby={linkId}
|
||||
aria-describedby={infoId}
|
||||
aria-posinset={positionInList}
|
||||
aria-setsize={listSize}
|
||||
>
|
||||
<CollectionLockup collection={collection} {...otherProps} />
|
||||
|
||||
<CollectionMenu
|
||||
context='list'
|
||||
<CollectionLockup
|
||||
collection={collection}
|
||||
className={classes.menuButton}
|
||||
className={classNames(
|
||||
classes.wrapper,
|
||||
withoutBorder && classes.wrapperWithoutBorder,
|
||||
className,
|
||||
)}
|
||||
sideContent={
|
||||
<CollectionMenu
|
||||
context='list'
|
||||
collection={collection}
|
||||
className={classes.menuButton}
|
||||
/>
|
||||
}
|
||||
{...otherProps}
|
||||
/>
|
||||
</Article>
|
||||
);
|
||||
|
||||
+2
-32
@@ -1,11 +1,5 @@
|
||||
.content {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 12px;
|
||||
color: var(--color-text-primary);
|
||||
line-height: 1.3;
|
||||
.wrapper {
|
||||
--list-item-padding: 0px;
|
||||
}
|
||||
|
||||
.avatarGrid {
|
||||
@@ -36,27 +30,3 @@
|
||||
fill: var(--color-text-primary);
|
||||
background: var(--color-bg-warning-softest);
|
||||
}
|
||||
|
||||
.link {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
color: var(--color-text-primary);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-text-brand);
|
||||
}
|
||||
|
||||
&::after {
|
||||
// Increase clickable area by extending link across parent
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
+64
-56
@@ -1,10 +1,11 @@
|
||||
import { useId } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
ListItemLink,
|
||||
ListItemWrapper,
|
||||
} from '@/flavours/glitch/components/list_item';
|
||||
import WarningIcon from '@/material-icons/400-24px/warning.svg?react';
|
||||
import type { ApiCollectionJSON } from 'flavours/glitch/api_types/collections';
|
||||
import { AvatarById } from 'flavours/glitch/components/avatar';
|
||||
@@ -47,71 +48,78 @@ export interface CollectionLockupProps {
|
||||
collection: ApiCollectionJSON;
|
||||
withAuthorHandle?: boolean;
|
||||
withTimestamp?: boolean;
|
||||
sideContent?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const CollectionLockup: React.FC<CollectionLockupProps> = ({
|
||||
collection,
|
||||
withAuthorHandle = true,
|
||||
withTimestamp,
|
||||
sideContent,
|
||||
className,
|
||||
}) => {
|
||||
const { id, name } = collection;
|
||||
const uniqueId = useId();
|
||||
const linkId = `${uniqueId}-link`;
|
||||
const infoId = `${uniqueId}-info`;
|
||||
const authorAccount = useAccount(collection.account_id);
|
||||
const authorHandle = useAccountHandle(authorAccount, domain);
|
||||
|
||||
return (
|
||||
<div className={classes.content}>
|
||||
<AvatarGrid
|
||||
accountIds={collection.items.map((item) => item.account_id)}
|
||||
sensitive={collection.sensitive}
|
||||
/>
|
||||
<div>
|
||||
<h2 id={linkId}>
|
||||
<Link to={getCollectionPath(id)} className={classes.link}>
|
||||
{name}
|
||||
</Link>
|
||||
</h2>
|
||||
<ul className={classes.info} id={infoId}>
|
||||
{collection.sensitive && (
|
||||
<li className='sr-only'>
|
||||
<FormattedMessage
|
||||
id='collections.sensitive'
|
||||
defaultMessage='Sensitive'
|
||||
/>
|
||||
</li>
|
||||
)}
|
||||
{withAuthorHandle && authorAccount && (
|
||||
<FormattedMessage
|
||||
id='collections.by_account'
|
||||
defaultMessage='by {account_handle}'
|
||||
values={{
|
||||
account_handle: authorHandle,
|
||||
}}
|
||||
tagName='li'
|
||||
/>
|
||||
)}
|
||||
const collectionInfo = (
|
||||
<ul>
|
||||
{collection.sensitive && (
|
||||
<li className='sr-only'>
|
||||
<FormattedMessage
|
||||
id='collections.account_count'
|
||||
defaultMessage='{count, plural, one {# account} other {# accounts}}'
|
||||
values={{ count: collection.item_count }}
|
||||
tagName='li'
|
||||
id='collections.sensitive'
|
||||
defaultMessage='Sensitive'
|
||||
/>
|
||||
{withTimestamp && (
|
||||
<FormattedMessage
|
||||
id='collections.last_updated_at'
|
||||
defaultMessage='Last updated: {date}'
|
||||
values={{
|
||||
date: (
|
||||
<RelativeTimestamp timestamp={collection.updated_at} long />
|
||||
),
|
||||
}}
|
||||
tagName='li'
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
)}
|
||||
{withAuthorHandle && authorAccount && (
|
||||
<FormattedMessage
|
||||
id='collections.by_account'
|
||||
defaultMessage='by {account_handle}'
|
||||
values={{
|
||||
account_handle: authorHandle,
|
||||
}}
|
||||
tagName='li'
|
||||
/>
|
||||
)}
|
||||
<FormattedMessage
|
||||
id='collections.account_count'
|
||||
defaultMessage='{count, plural, one {# account} other {# accounts}}'
|
||||
values={{ count: collection.item_count }}
|
||||
tagName='li'
|
||||
/>
|
||||
{withTimestamp && (
|
||||
<FormattedMessage
|
||||
id='collections.last_updated_at'
|
||||
defaultMessage='Last updated: {date}'
|
||||
values={{
|
||||
date: <RelativeTimestamp timestamp={collection.updated_at} long />,
|
||||
}}
|
||||
tagName='li'
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
|
||||
return (
|
||||
<ListItemWrapper
|
||||
className={classNames(classes.wrapper, className)}
|
||||
icon={
|
||||
<AvatarGrid
|
||||
accountIds={collection.items.map((item) => item.account_id)}
|
||||
sensitive={collection.sensitive}
|
||||
/>
|
||||
}
|
||||
sideContent={sideContent}
|
||||
>
|
||||
<ListItemLink
|
||||
as='h2'
|
||||
to={getCollectionPath(id)}
|
||||
subtitle={collectionInfo}
|
||||
>
|
||||
{name}
|
||||
</ListItemLink>
|
||||
</ListItemWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
+6
-4
@@ -1,8 +1,10 @@
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
padding: 12px;
|
||||
gap: 12px;
|
||||
--list-item-padding: 12px;
|
||||
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--color-border-primary);
|
||||
}
|
||||
|
||||
.removeButton {
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
+24
-3
@@ -1,5 +1,9 @@
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import type { CollectionLockupProps } from 'flavours/glitch/features/collections/components/collection_lockup';
|
||||
import { CollectionLockup } from 'flavours/glitch/features/collections/components/collection_lockup';
|
||||
|
||||
@@ -14,9 +18,26 @@ export const CollectionPreviewCard: React.FC<CollectionPreviewCardProps> = ({
|
||||
onRemove,
|
||||
...otherProps
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const removeButton = onRemove && (
|
||||
<IconButton
|
||||
icon='remove'
|
||||
iconComponent={CloseIcon}
|
||||
onClick={onRemove}
|
||||
title={intl.formatMessage({
|
||||
id: 'tag.remove',
|
||||
defaultMessage: 'Remove',
|
||||
})}
|
||||
className={classes.removeButton}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classNames(classes.wrapper, 'collection-preview')}>
|
||||
<CollectionLockup collection={collection} {...otherProps} />
|
||||
</div>
|
||||
<CollectionLockup
|
||||
collection={collection}
|
||||
className={classNames(classes.wrapper, 'collection-preview')}
|
||||
sideContent={removeButton}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user