manifold/web/components/pagination.tsx

91 lines
2.6 KiB
TypeScript
Raw Normal View History

import { ReactNode } from 'react'
import clsx from 'clsx'
2022-08-02 22:12:03 +00:00
import { Spacer } from './layout/spacer'
import { Row } from './layout/row'
export function PaginationNextPrev(props: {
className?: string
prev?: ReactNode
next?: ReactNode
onClickPrev: () => void
onClickNext: () => void
scrollToTop?: boolean
}) {
const { className, prev, next, onClickPrev, onClickNext, scrollToTop } = props
return (
<Row className={clsx(className, 'flex-1 justify-between sm:justify-end')}>
{prev != null && (
<a
href={scrollToTop ? '#' : undefined}
className="relative inline-flex cursor-pointer select-none items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
onClick={onClickPrev}
>
{prev ?? 'Previous'}
</a>
)}
{next != null && (
<a
href={scrollToTop ? '#' : undefined}
className="relative ml-3 inline-flex cursor-pointer select-none items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50"
onClick={onClickNext}
>
{next ?? 'Next'}
</a>
)}
</Row>
)
}
2022-07-10 23:41:33 +00:00
export function Pagination(props: {
page: number
itemsPerPage: number
totalItems: number
setPage: (page: number) => void
scrollToTop?: boolean
className?: string
2022-07-19 20:16:20 +00:00
nextTitle?: string
prevTitle?: string
2022-07-10 23:41:33 +00:00
}) {
2022-07-19 20:16:20 +00:00
const {
page,
itemsPerPage,
totalItems,
setPage,
scrollToTop,
nextTitle,
prevTitle,
className,
2022-07-19 20:16:20 +00:00
} = props
2022-07-10 23:41:33 +00:00
const maxPage = Math.ceil(totalItems / itemsPerPage) - 1
2022-08-02 22:12:03 +00:00
if (maxPage === 0) return <Spacer h={4} />
2022-07-10 23:41:33 +00:00
return (
<nav
className={clsx(
'flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6',
className
)}
2022-07-10 23:41:33 +00:00
aria-label="Pagination"
>
<div className="hidden sm:block">
<p className="text-sm text-gray-700">
Showing <span className="font-medium">{page * itemsPerPage + 1}</span>{' '}
to{' '}
2022-07-10 23:41:33 +00:00
<span className="font-medium">
{Math.min(totalItems, (page + 1) * itemsPerPage)}
2022-07-10 23:41:33 +00:00
</span>{' '}
of <span className="font-medium">{totalItems}</span> results
2022-07-10 23:41:33 +00:00
</p>
</div>
<PaginationNextPrev
prev={page > 0 ? prevTitle ?? 'Previous' : null}
next={page < maxPage ? nextTitle ?? 'Next' : null}
onClickPrev={() => setPage(page - 1)}
onClickNext={() => setPage(page + 1)}
scrollToTop={scrollToTop}
/>
2022-07-10 23:41:33 +00:00
</nav>
)
}