Skip to content

Commit

Permalink
feat(suite): rework pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
necky2 committed Jan 24, 2025
1 parent f1b822d commit 97345f9
Showing 1 changed file with 134 additions and 26 deletions.
160 changes: 134 additions & 26 deletions packages/suite/src/components/wallet/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ const Wrapper = styled.div`
gap: ${spacingsPx.xxxs};
`;

const PageItem = styled.div<{ $isActive?: boolean }>`
const Ellipsis = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: ${spacingsPx.xxl};
height: ${spacingsPx.xxl};
padding: ${spacingsPx.xxs} ${spacingsPx.xs};
text-align: center;
${typography.hint};
`;

const PageItem = styled.div<{ $isActive?: boolean; $isDisabled?: boolean }>`
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -31,14 +42,22 @@ const PageItem = styled.div<{ $isActive?: boolean }>`
${typography.hint};
cursor: pointer;
${({ $isActive, theme }) =>
${({ $isActive, $isDisabled, theme }) =>
!$isActive &&
!$isDisabled &&
css`
&:hover {
background: ${theme.backgroundTertiaryDefaultOnElevation0};
color: ${theme.textOnTertiary};
}
`};
${({ $isDisabled }) =>
$isDisabled &&
css`
color: ${({ theme }) => theme.textDisabled};
cursor: not-allowed;
`};
`;

const Actions = styled.div<{ $isActive: boolean }>`
Expand All @@ -56,27 +75,90 @@ interface PaginationProps {
onPageSelected: (page: number) => void;
}

const SLIDING_WINDOW_SIZE = 7; // should be an even number, so that the active page can be centered
const calculatePages = ({
currentPage,
totalPages,
}: {
currentPage: number;
totalPages: number;
}) => {
const calculatedPages: (number | null)[] = [];

// center the current page
let windowBeginning = currentPage - Math.floor((SLIDING_WINDOW_SIZE - 1) / 2);

// prevent window overflow on the right
if (windowBeginning + SLIDING_WINDOW_SIZE > totalPages)
windowBeginning = totalPages - (SLIDING_WINDOW_SIZE - 1);

// prevent window overflow on the left
if (windowBeginning < 1) windowBeginning = 1;

for (
let page = windowBeginning;
page < windowBeginning + SLIDING_WINDOW_SIZE && page <= totalPages;
page++
) {
const indexInWindow = calculatedPages.length;

// first button override
if (indexInWindow === 0) {
calculatedPages.push(1);
continue;
}

// second button override
if (indexInWindow === 1 && page !== 2) {
calculatedPages.push(null);
continue;
}

// second to last button override
if (
indexInWindow === SLIDING_WINDOW_SIZE - 2 &&
page !== totalPages - 1 &&
totalPages > SLIDING_WINDOW_SIZE
) {
calculatedPages.push(null);
continue;
}

// last button override
if (indexInWindow === SLIDING_WINDOW_SIZE - 1 && page !== totalPages) {
calculatedPages.push(totalPages);
continue;
}

calculatedPages.push(page);
}

return calculatedPages;
};

export const Pagination = ({
currentPage,
onPageSelected,
hasPages = true,
isLastPage,
isLastPage: _isLastPage,
perPage,
totalItems,
...rest
}: PaginationProps) => {
const totalPages = Math.ceil(totalItems / perPage);
const showPrevious = currentPage > 1;
// array of int used for creating all page buttons
const isFirstPage = currentPage === 1;
const isLastPage = hasPages ? currentPage === totalPages : _isLastPage;

// array of pages to be rendered as buttons
const calculatedPages = useMemo(
() => [...Array(totalPages)].map((_p, i) => i + 1),
[totalPages],
() => calculatePages({ currentPage, totalPages }),
[currentPage, totalPages],
);

if (!hasPages) {
return (
<Wrapper {...rest}>
<Actions $isActive={showPrevious}>
<Actions $isActive={!isFirstPage}>
<PageItem onClick={() => onPageSelected(currentPage - 1)}>
<Translation id="TR_PAGINATION_NEWER" />
</PageItem>
Expand All @@ -92,23 +174,39 @@ export const Pagination = ({

return (
<Wrapper {...rest}>
<Actions $isActive={showPrevious}>
{currentPage > 2 && <PageItem onClick={() => onPageSelected(1)}>«</PageItem>}
<PageItem onClick={() => onPageSelected(currentPage - 1)}></PageItem>
<Actions $isActive={true}>
<PageItem
$isDisabled={isFirstPage}
onClick={!isFirstPage ? () => onPageSelected(1) : undefined}
>
«
</PageItem>
<PageItem
$isDisabled={isFirstPage}
onClick={!isFirstPage ? () => onPageSelected(currentPage - 1) : undefined}
>
</PageItem>
</Actions>

{totalPages ? (
calculatedPages.map(i => (
<PageItem
key={i}
data-testid={`@wallet/accounts/pagination/${i}`}
data-test-activated={i === currentPage}
onClick={() => onPageSelected(i)}
$isActive={i === currentPage}
>
{i}
</PageItem>
))
<>
{calculatedPages.map((page, i) =>
page === null ? (
<Ellipsis key={i}></Ellipsis>
) : (
<PageItem
key={i}
data-testid={`@wallet/accounts/pagination/${page}`}
data-test-activated={page === currentPage}
onClick={() => onPageSelected(page)}
$isActive={page === currentPage}
>
{page}
</PageItem>
),
)}
</>
) : (
<>
{[...Array(currentPage - 1)].map((_p, i) => (
Expand All @@ -129,10 +227,20 @@ export const Pagination = ({
</>
)}

<Actions $isActive={currentPage < (totalPages || 1)}>
<PageItem onClick={() => onPageSelected(currentPage + 1)}></PageItem>
{totalPages && totalPages > 2 && (
<PageItem onClick={() => onPageSelected(totalPages)}>»</PageItem>
<Actions $isActive={true}>
<PageItem
$isDisabled={isLastPage}
onClick={!isLastPage ? () => onPageSelected(currentPage + 1) : undefined}
>
</PageItem>
{totalPages > 0 && (
<PageItem
$isDisabled={isLastPage}
onClick={!isLastPage ? () => onPageSelected(totalPages) : undefined}
>
»
</PageItem>
)}
</Actions>
</Wrapper>
Expand Down

0 comments on commit 97345f9

Please sign in to comment.