Pagination
A navigation component that allows users to browse through pages.
import { Pagination, type PaginationProps } from '~/components/ui/pagination'
export const Demo = (props: PaginationProps) => {
return <Pagination {...props} count={90} pageSize={10} siblingCount={1} defaultPage={2} />
}
import { Pagination, type PaginationProps } from '~/components/ui/pagination'
export const Demo = (props: PaginationProps) => {
return <Pagination {...props} count={90} pageSize={10} siblingCount={1} defaultPage={2} />
}
Usage
import { Pagination } from '~/components/ui/pagination'
Installation
npx @park-ui/cli components add pagination
1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/pagination.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { Pagination } from '@ark-ui/react/pagination'
import { type PaginationVariantProps, pagination } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(pagination)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
HTMLElement,
Assign<Assign<HTMLStyledProps<'nav'>, Pagination.RootProviderBaseProps>, PaginationVariantProps>
>(Pagination.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
HTMLElement,
Assign<Assign<HTMLStyledProps<'nav'>, Pagination.RootBaseProps>, PaginationVariantProps>
>(Pagination.Root, 'root', { forwardProps: ['page'] })
export const Ellipsis = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Pagination.EllipsisBaseProps>
>(Pagination.Ellipsis, 'ellipsis')
export const Item = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, Pagination.ItemBaseProps>
>(Pagination.Item, 'item')
export const NextTrigger = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, Pagination.NextTriggerBaseProps>
>(Pagination.NextTrigger, 'nextTrigger')
export const PrevTrigger = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, Pagination.PrevTriggerBaseProps>
>(Pagination.PrevTrigger, 'prevTrigger')
export { PaginationContext as Context } from '@ark-ui/react/pagination'
import { type Assign, Pagination } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type PaginationVariantProps, pagination } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(pagination)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
Assign<Assign<HTMLStyledProps<'nav'>, Pagination.RootProviderBaseProps>, PaginationVariantProps>
>(Pagination.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
Assign<Assign<HTMLStyledProps<'nav'>, Pagination.RootBaseProps>, PaginationVariantProps>
>(Pagination.Root, 'root', { forwardProps: ['page'] })
export const Ellipsis = withContext<Assign<HTMLStyledProps<'div'>, Pagination.EllipsisBaseProps>>(
Pagination.Ellipsis,
'ellipsis',
)
export const Item = withContext<Assign<HTMLStyledProps<'button'>, Pagination.ItemBaseProps>>(
Pagination.Item,
'item',
)
export const NextTrigger = withContext<
Assign<HTMLStyledProps<'button'>, Pagination.NextTriggerBaseProps>
>(Pagination.NextTrigger, 'nextTrigger')
export const PrevTrigger = withContext<
Assign<HTMLStyledProps<'button'>, Pagination.PrevTriggerBaseProps>
>(Pagination.PrevTrigger, 'prevTrigger')
export { PaginationContext as Context } from '@ark-ui/solid'
No snippet found
2
Add Composition
Copy the composition snippet below into ~/components/ui/pagination.tsx
'use client'
import { forwardRef } from 'react'
import { Button } from './button'
import { IconButton } from './icon-button'
import * as StyledPagination from './styled/pagination'
export interface PaginationProps extends StyledPagination.RootProps {}
export const Pagination = forwardRef<HTMLElement, PaginationProps>((props, ref) => {
return (
<StyledPagination.Root ref={ref} {...props}>
<StyledPagination.PrevTrigger asChild>
<IconButton variant="ghost" aria-label="Next Page">
<ChevronLeftIcon />
</IconButton>
</StyledPagination.PrevTrigger>
<StyledPagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<StyledPagination.Item key={index} {...page} asChild>
<Button variant="outline">{page.value}</Button>
</StyledPagination.Item>
) : (
<StyledPagination.Ellipsis key={index} index={index}>
…
</StyledPagination.Ellipsis>
),
)
}
</StyledPagination.Context>
<StyledPagination.NextTrigger asChild>
<IconButton variant="ghost" aria-label="Next Page">
<ChevronRightIcon />
</IconButton>
</StyledPagination.NextTrigger>
</StyledPagination.Root>
)
})
Pagination.displayName = 'Pagination'
const ChevronLeftIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>Chevron Left Icon</title>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m15 18l-6-6l6-6"
/>
</svg>
)
const ChevronRightIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>Chevron Right Icon</title>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m9 18l6-6l-6-6"
/>
</svg>
)
import { For } from 'solid-js'
import { Button } from './button'
import { IconButton } from './icon-button'
import * as StyledPagination from './styled/pagination'
export interface PaginationProps extends StyledPagination.RootProps {}
export const Pagination = (props: PaginationProps) => {
return (
<StyledPagination.Root {...props}>
<StyledPagination.PrevTrigger
asChild={(props) => (
<IconButton {...props} variant="ghost" aria-label="Next Page">
<ChevronLeftIcon />
</IconButton>
)}
/>
<StyledPagination.Context>
{(pagiation) => (
<For each={pagiation().pages}>
{(page, index) =>
page.type === 'page' ? (
<StyledPagination.Item
{...page}
asChild={(props) => <Button {...props} variant="outline" />}
>
{page.value}
</StyledPagination.Item>
) : (
<StyledPagination.Ellipsis index={index()}>…</StyledPagination.Ellipsis>
)
}
</For>
)}
</StyledPagination.Context>
<StyledPagination.NextTrigger
asChild={(props) => (
<IconButton {...props} variant="ghost" aria-label="Next Page">
<ChevronRightIcon />
</IconButton>
)}
/>
</StyledPagination.Root>
)
}
const ChevronLeftIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>Chevron Left Icon</title>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m15 18l-6-6l6-6"
/>
</svg>
)
const ChevronRightIcon = () => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<title>Chevron Right Icon</title>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m9 18l6-6l-6-6"
/>
</svg>
)
3
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { paginationAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const pagination = defineSlotRecipe({
className: 'pagination',
slots: paginationAnatomy.keys(),
base: {
root: {
display: 'flex',
gap: '2.5',
},
item: {
fontVariantNumeric: 'tabular-nums',
},
ellipsis: {
alignItems: 'center',
color: 'fg.default',
display: 'inline-flex',
fontWeight: 'semibold',
px: '2',
},
},
})