ScrollableList: replace margins with padding
This commit is contained in:
parent
a8c306e62b
commit
ae48cb2c06
|
@ -6,10 +6,26 @@ import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||||
|
|
||||||
import { Spinner, Text } from './ui';
|
import { Spinner, Text } from './ui';
|
||||||
|
|
||||||
|
type Context = {
|
||||||
|
itemClassName?: string,
|
||||||
|
listClassName?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
type VComponent = {
|
||||||
|
context?: Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: It's crucial to space lists with **padding** instead of margin!
|
||||||
|
// Pass an `itemClassName` like `pb-3`, NOT a `space-y-3` className
|
||||||
|
// https://virtuoso.dev/troubleshooting#list-does-not-scroll-to-the-bottom--items-jump-around
|
||||||
|
const Item: React.FC<VComponent> = ({ context, ...rest }) => (
|
||||||
|
<div className={context?.itemClassName} {...rest} />
|
||||||
|
);
|
||||||
|
|
||||||
// Ensure the className winds up here
|
// Ensure the className winds up here
|
||||||
const List = React.forwardRef((props: any, ref: React.ForwardedRef<HTMLDivElement>) => {
|
const List = React.forwardRef<HTMLDivElement, VComponent>((props, ref) => {
|
||||||
const { context, ...rest } = props;
|
const { context, ...rest } = props;
|
||||||
return <div ref={ref} className={context.listClassName} {...rest} />;
|
return <div ref={ref} className={context?.listClassName} {...rest} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
interface IScrollableList {
|
interface IScrollableList {
|
||||||
|
@ -28,6 +44,7 @@ interface IScrollableList {
|
||||||
placeholderCount?: number,
|
placeholderCount?: number,
|
||||||
onRefresh?: () => Promise<any>,
|
onRefresh?: () => Promise<any>,
|
||||||
className?: string,
|
className?: string,
|
||||||
|
itemClassName?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Legacy ScrollableList with Virtuoso for backwards-compatibility */
|
/** Legacy ScrollableList with Virtuoso for backwards-compatibility */
|
||||||
|
@ -43,6 +60,7 @@ const ScrollableList: React.FC<IScrollableList> = ({
|
||||||
onScrollToTop,
|
onScrollToTop,
|
||||||
onLoadMore,
|
onLoadMore,
|
||||||
className,
|
className,
|
||||||
|
itemClassName,
|
||||||
hasMore,
|
hasMore,
|
||||||
placeholderComponent: Placeholder,
|
placeholderComponent: Placeholder,
|
||||||
placeholderCount = 0,
|
placeholderCount = 0,
|
||||||
|
@ -101,12 +119,14 @@ const ScrollableList: React.FC<IScrollableList> = ({
|
||||||
itemContent={renderItem}
|
itemContent={renderItem}
|
||||||
context={{
|
context={{
|
||||||
listClassName: className,
|
listClassName: className,
|
||||||
|
itemClassName,
|
||||||
}}
|
}}
|
||||||
components={{
|
components={{
|
||||||
Header: () => prepend,
|
Header: () => prepend,
|
||||||
ScrollSeekPlaceholder: Placeholder as any,
|
ScrollSeekPlaceholder: Placeholder as any,
|
||||||
EmptyPlaceholder: () => renderEmpty(),
|
EmptyPlaceholder: () => renderEmpty(),
|
||||||
List,
|
List,
|
||||||
|
Item,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</PullToRefresh>
|
</PullToRefresh>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import classNames from 'classnames';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
@ -222,7 +223,12 @@ export default class StatusList extends ImmutablePureComponent {
|
||||||
placeholderComponent={PlaceholderStatus}
|
placeholderComponent={PlaceholderStatus}
|
||||||
placeholderCount={20}
|
placeholderCount={20}
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
className={divideType === 'border' ? 'divide-y divide-solid divide-gray-200 dark:divide-gray-800' : 'sm:space-y-3 divide-y divide-solid divide-gray-200 dark:divide-gray-800 sm:divide-none'}
|
className={classNames('divide-y divide-solid divide-gray-200 dark:divide-slate-700', {
|
||||||
|
'sm:divide-none': divideType !== 'border',
|
||||||
|
})}
|
||||||
|
itemClassName={classNames({
|
||||||
|
'sm:pb-3': divideType !== 'border',
|
||||||
|
})}
|
||||||
{...other}
|
{...other}
|
||||||
>
|
>
|
||||||
{this.renderScrollableContent()}
|
{this.renderScrollableContent()}
|
||||||
|
|
|
@ -116,7 +116,8 @@ class UserIndex extends ImmutablePureComponent {
|
||||||
showLoading={showLoading}
|
showLoading={showLoading}
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
emptyMessage={intl.formatMessage(messages.empty)}
|
emptyMessage={intl.formatMessage(messages.empty)}
|
||||||
className='mt-4 space-y-4'
|
className='mt-4'
|
||||||
|
itemClassName='pb-4'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withDate />,
|
<AccountContainer key={id} id={id} withDate />,
|
||||||
|
|
|
@ -45,7 +45,7 @@ const Blocks: React.FC = () => {
|
||||||
onLoadMore={() => handleLoadMore(dispatch)}
|
onLoadMore={() => handleLoadMore(dispatch)}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-4'
|
itemClassName='pb-4'
|
||||||
>
|
>
|
||||||
{accountIds.map((id: string) =>
|
{accountIds.map((id: string) =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
|
|
|
@ -125,7 +125,7 @@ class Followers extends ImmutablePureComponent {
|
||||||
diffCount={diffCount}
|
diffCount={diffCount}
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
emptyMessage={<FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />}
|
emptyMessage={<FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />}
|
||||||
className='space-y-4'
|
itemClassName='pb-4'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />,
|
<AccountContainer key={id} id={id} withNote={false} />,
|
||||||
|
|
|
@ -125,7 +125,7 @@ class Following extends ImmutablePureComponent {
|
||||||
diffCount={diffCount}
|
diffCount={diffCount}
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
emptyMessage={<FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />}
|
emptyMessage={<FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />}
|
||||||
className='space-y-4'
|
itemClassName='pb-4'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />,
|
<AccountContainer key={id} id={id} withNote={false} />,
|
||||||
|
|
|
@ -45,7 +45,7 @@ const Mutes: React.FC = () => {
|
||||||
onLoadMore={() => handleLoadMore(dispatch)}
|
onLoadMore={() => handleLoadMore(dispatch)}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-4'
|
itemClassName='pb-4'
|
||||||
>
|
>
|
||||||
{accountIds.map((id: string) =>
|
{accountIds.map((id: string) =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
|
|
|
@ -28,7 +28,7 @@ const BirthdaysModal = ({ onClose }: IBirthdaysModal) => {
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reblogs'
|
scrollKey='reblogs'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<Account key={id} accountId={id} />,
|
<Account key={id} accountId={id} />,
|
||||||
|
|
|
@ -54,7 +54,7 @@ class FavouritesModal extends React.PureComponent {
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='favourites'
|
scrollKey='favourites'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
|
|
|
@ -61,7 +61,7 @@ class MentionsModal extends React.PureComponent {
|
||||||
body = (
|
body = (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='mentions'
|
scrollKey='mentions'
|
||||||
className='space-y-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />,
|
<AccountContainer key={id} id={id} withNote={false} />,
|
||||||
|
|
|
@ -87,7 +87,7 @@ const ReactionsModal: React.FC<IReactionsModal> = ({ onClose, statusId, ...props
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reactions'
|
scrollKey='reactions'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accounts.map((account) =>
|
{accounts.map((account) =>
|
||||||
<AccountContainer key={`${account.id}-${account.reaction}`} id={account.id} /* reaction={account.reaction} */ />,
|
<AccountContainer key={`${account.id}-${account.reaction}`} id={account.id} /* reaction={account.reaction} */ />,
|
||||||
|
|
|
@ -72,7 +72,7 @@ class ReblogsModal extends React.PureComponent {
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reblogs'
|
scrollKey='reblogs'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='space-y-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
|
|
Loading…
Reference in New Issue