Pagination primitives aligned with button variants
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '@/components/ui/pagination'
...import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '@/components/ui/pagination'
export default function PaginationDemoExample() {
return <Pagination><PaginationContent><PaginationItem><PaginationPrevious href="#" /></PaginationItem><PaginationItem><PaginationLink href="#">1</PaginationLink></PaginationItem><PaginationItem><PaginationLink href="#" isActive>2</PaginationLink></PaginationItem><PaginationItem><PaginationLink href="#">3</PaginationLink></PaginationItem><PaginationItem><PaginationEllipsis /></PaginationItem><PaginationItem><PaginationNext href="#" /></PaginationItem></PaginationContent></Pagination>
}
Installation
npx @fictjs/shadcn@latest add paginationCopy the Fict shadcn component into your project.
Source
components/ui/pagination.tsx
src/components/ui/pagination.tsx
import { cn } from '@/lib/cn'
import { buttonVariants } from '@/components/ui/button'
type NavProps = JSX.IntrinsicElements['nav']
type UlProps = JSX.IntrinsicElements['ul']
type LiProps = JSX.IntrinsicElements['li']
type AnchorProps = JSX.IntrinsicElements['a']
type SpanProps = JSX.IntrinsicElements['span']
export function Pagination(props: NavProps) {
const { class: className, ...rest } = props
return <nav role='navigation' aria-label='pagination' class={cn('mx-auto flex w-full justify-center', className)} {...rest} />
}
export function PaginationContent(props: UlProps) {
const { class: className, ...rest } = props
return <ul class={cn('flex flex-row items-center gap-1', className)} {...rest} />
}
export function PaginationItem(props: LiProps) {
return <li {...props} />
}
export function PaginationLink(props: AnchorProps & { isActive?: boolean }) {
const { class: className, isActive, ...rest } = props
return (
<a
aria-current={isActive ? 'page' : undefined}
class={cn(
buttonVariants({ variant: isActive ? 'outline' : 'ghost', size: 'icon' }),
'h-9 w-9',
className,
)}
{...rest}
/>
)
}
export function PaginationPrevious(props: AnchorProps) {
const { class: className, ...rest } = props
return <PaginationLink aria-label='Go to previous page' class={cn('w-auto px-3', className)} {...rest}>Previous</PaginationLink>
}
export function PaginationNext(props: AnchorProps) {
const { class: className, ...rest } = props
return <PaginationLink aria-label='Go to next page' class={cn('w-auto px-3', className)} {...rest}>Next</PaginationLink>
}
export function PaginationEllipsis(props: SpanProps) {
const { class: className, ...rest } = props
return <span aria-hidden='true' class={cn('flex h-9 w-9 items-center justify-center text-muted-foreground', className)} {...rest}>…</span>
}
Usage
Examples
Simple
import { Pagination, PaginationContent, PaginationItem, PaginationLink } from '@/components/ui/pagination'
...import { Pagination, PaginationContent, PaginationItem, PaginationLink } from '@/components/ui/pagination'
export default function PaginationSimpleExample() {
return <Pagination><PaginationContent>{[1, 2, 3, 4, 5].map(page => <PaginationItem><PaginationLink href="#" isActive={page === 2}>{page}</PaginationLink></PaginationItem>)}</PaginationContent></Pagination>
}
Icons Only
import { Pagination, PaginationContent, PaginationItem, PaginationLink } from '@/components/ui/pagination'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
...import { Pagination, PaginationContent, PaginationItem, PaginationLink } from '@/components/ui/pagination'
import { NativeSelect, NativeSelectOption } from '@/components/ui/native-select'
function ArrowIcon(props: { direction: 'previous' | 'next' }) {
return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d={props.direction === 'previous' ? 'm15 18-6-6 6-6' : 'm9 18 6-6-6-6'} /></svg>
}
export default function PaginationIconsOnlyExample() {
let rows = $state('25')
return <div class="flex w-full items-center justify-between"><label class="flex items-center gap-2">Rows per page<NativeSelect value={rows} onChange={event => { rows = event.currentTarget.value }}>{['10', '25', '50', '100'].map(value => <NativeSelectOption value={value}>{value}</NativeSelectOption>)}</NativeSelect></label><Pagination class="mx-0 w-auto"><PaginationContent><PaginationItem><PaginationLink href="#" aria-label="Go to previous page"><ArrowIcon direction="previous" /></PaginationLink></PaginationItem><PaginationItem><PaginationLink href="#" aria-label="Go to next page"><ArrowIcon direction="next" /></PaginationLink></PaginationItem></PaginationContent></Pagination></div>
}
Rtl
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink } from '@/components/ui/pagination'
...import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink } from '@/components/ui/pagination'
const translations = {
ar: { dir: 'rtl', previous: 'السابق', next: 'التالي', pages: ['١', '٢', '٣'] },
he: { dir: 'rtl', previous: 'הקודם', next: 'הבא', pages: ['1', '2', '3'] },
en: { dir: 'ltr', previous: 'Previous', next: 'Next', pages: ['1', '2', '3'] },
} as const
export default function PaginationRtlExample() {
let language = $state<keyof typeof translations>('ar')
const text = () => translations[language]
return <div class="grid gap-4"><select value={language} onChange={event => { language = event.currentTarget.value as keyof typeof translations }}><option value="ar">Arabic (العربية)</option><option value="he">Hebrew (עברית)</option><option value="en">English</option></select><Pagination dir={text().dir}><PaginationContent><PaginationItem><PaginationLink href="#" class="w-auto px-3">{text().previous}</PaginationLink></PaginationItem>{text().pages.map((page, index) => <PaginationItem><PaginationLink href="#" isActive={index === 1}>{page}</PaginationLink></PaginationItem>)}<PaginationItem><PaginationEllipsis /></PaginationItem><PaginationItem><PaginationLink href="#" class="w-auto px-3">{text().next}</PaginationLink></PaginationItem></PaginationContent></Pagination></div>
}