Files
gridpilot.gg/apps/website/ui/Pagination.tsx
2026-01-18 23:24:30 +01:00

78 lines
2.2 KiB
TypeScript

import { ChevronLeft, ChevronRight } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Button } from './Button';
import { Text } from './Text';
export interface PaginationProps {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
}
export const Pagination = ({
currentPage,
totalPages,
onPageChange
}: PaginationProps) => {
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
const visiblePages = pages.filter(page => {
if (totalPages <= 7) return true;
if (page === 1 || page === totalPages) return true;
if (page >= currentPage - 1 && page <= currentPage + 1) return true;
return false;
});
return (
<Box display="flex" alignItems="center" justifyContent="between" paddingTop={4}>
<Text size="sm" variant="low">
Page {currentPage} of {totalPages}
</Text>
<Box display="flex" alignItems="center" gap={2}>
<Button
variant="ghost"
size="sm"
disabled={currentPage === 1}
onClick={() => onPageChange(currentPage - 1)}
icon={<ChevronLeft size={16} />}
>
Previous
</Button>
<Box display="flex" alignItems="center" gap={1}>
{visiblePages.map((page, index) => {
const prevPage = visiblePages[index - 1];
const showEllipsis = prevPage && page - prevPage > 1;
return (
<React.Fragment key={page}>
{showEllipsis && <Text variant="low">...</Text>}
<Button
variant={page === currentPage ? 'primary' : 'ghost'}
size="sm"
onClick={() => onPageChange(page)}
style={{ minWidth: '2.5rem', padding: 0 }}
>
{page}
</Button>
</React.Fragment>
);
})}
</Box>
<Button
variant="ghost"
size="sm"
disabled={currentPage === totalPages}
onClick={() => onPageChange(currentPage + 1)}
icon={<ChevronRight size={16} />}
>
Next
</Button>
</Box>
</Box>
);
};