Skip to content

Commit c8d2128

Browse files
committed
feat(infinite scroll): add pagination mode
1 parent d0b1cfd commit c8d2128

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

packages/components/base/src/infinite-scroll/index.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface InfiniteScrollProps {
3434
ContentWrapper?: React.FC<React.PropsWithChildren>;
3535
/** Additional props passed to the intersection observer element */
3636
intersectionElementProps?: React.ComponentPropsWithoutRef<"div">;
37+
mode?: "infinite" | "enable-once" | "pagination";
3738
}
3839

3940
export const InfiniteScroll: React.FC<React.PropsWithChildren<InfiniteScrollProps>> = ({
@@ -50,10 +51,11 @@ export const InfiniteScroll: React.FC<React.PropsWithChildren<InfiniteScrollProp
5051
loadMoreButton = "Load more",
5152
ContentWrapper = defaultContentWrapper,
5253
intersectionElementProps,
54+
mode = loadMoreButton ? "enable-once" : "infinite",
5355
}) => {
5456
const intersectionRef = useRef<HTMLDivElement>(null);
5557

56-
const [infiniteScrollEnabled, setInfiniteScrollEnabled] = useState(!displayLoadMore);
58+
const [infiniteScrollEnabled, setInfiniteScrollEnabled] = useState(mode === "infinite");
5759
const [isIntersecting, setIsIntersecting] = useState(false);
5860

5961
const hasItemsLeft = useMemo(
@@ -63,25 +65,28 @@ export const InfiniteScroll: React.FC<React.PropsWithChildren<InfiniteScrollProp
6365

6466
const LoadMoreButton = useMemo(() => {
6567
if (!displayLoadMore) return null;
68+
69+
const action = () => {
70+
if (mode === "enable-once") {
71+
setInfiniteScrollEnabled(true);
72+
} else {
73+
if (loading) return;
74+
void onLoadMore();
75+
}
76+
};
77+
6678
if (typeof loadMoreButton === "function") {
6779
return loadMoreButton({
68-
loadMore: () => {
69-
setInfiniteScrollEnabled(true);
70-
},
80+
loadMore: action,
7181
});
7282
}
7383

7484
return (
75-
<Button
76-
skinVariation="bordered"
77-
fullWidth
78-
onClick={() => {
79-
setInfiniteScrollEnabled(true);
80-
}}>
85+
<Button skinVariation="bordered" fullWidth onClick={action}>
8186
{loadMoreButton}
8287
</Button>
8388
);
84-
}, [loadMoreButton, displayLoadMore]);
89+
}, [displayLoadMore, loadMoreButton, loading, mode, onLoadMore]);
8590

8691
const elements = useMemo<React.ReactNode[]>(() => {
8792
const elements = [
@@ -94,7 +99,9 @@ export const InfiniteScroll: React.FC<React.PropsWithChildren<InfiniteScrollProp
9499
</ContentWrapper>
95100
) : null,
96101
hasItemsLeft && loadingMore ? (loadingMoreElement ?? <Spinner />) : null,
97-
displayLoadMore && !infiniteScrollEnabled && hasItemsLeft ? LoadMoreButton : null,
102+
displayLoadMore && !infiniteScrollEnabled && hasItemsLeft && !loading && !loadingMore
103+
? LoadMoreButton
104+
: null,
98105
];
99106

100107
return direction === "bottom" ? elements : elements.reverse();

packages/docs/stories/src/generic-infinite-scroll.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const Default: Story = {
8585
},
8686
},
8787
args: {
88+
mode: "enable-once",
8889
loadMoreButton: "Load more items",
8990
displayLoadMore: true,
9091
loadingMoreElement: customLoadingMoreElement,

0 commit comments

Comments
 (0)