Pagination with page navigation, next and previous links.
Installation
npx shadcn@latest add @caprice/paginationpnpm dlx shadcn@latest add @caprice/paginationyarn dlx shadcn@latest add @caprice/paginationbunx shadcn@latest add @caprice/paginationnpm install @caprice-ui/reactpnpm add @caprice-ui/reactyarn add @caprice-ui/reactbun add @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactpnpm add @base-ui/react lucide-reactyarn add @base-ui/react lucide-reactbun add @base-ui/react lucide-reactAdd a cn helper
import { cn as merge } from 'cn';
import type { VariantProps } from 'cva';
import { defineConfig } from 'cva/config';
import { getSchema } from 'cva/tools';
export const { cva, cx: cn } = defineConfig({
cx: merge,
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
'use client';
import { mergeProps, useRender } from '@base-ui/react';
import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from 'lucide-react';
import type * as React from 'react';
import { type Button, buttonVariants } from '@/components/caprice-ui/button';
import { cn } from '@/lib/utils';
/**
* Groups the pagination content.
* Renders a `<nav>` element.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Root {
export type Props = React.ComponentProps<'nav'>;
}
export function Root({ className, ...props }: Root.Props) {
return (
<nav
aria-label="pagination"
className={cn('mx-auto flex w-full justify-center', className)}
data-slot="pagination"
{...props}
/>
);
}
/**
* A container for the pagination items.
* Renders a `<ul>` element.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Content {
export type Props = React.ComponentProps<'ul'>;
}
export function Content({ className, ...props }: Content.Props) {
return (
<ul
className={cn('flex flex-row items-center gap-1', className)}
data-slot="pagination-content"
{...props}
/>
);
}
/**
* An individual pagination item.
* Renders a `<li>` element.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Item {
export type Props = React.ComponentProps<'li'>;
}
export function Item({ ...props }: Item.Props) {
return <li data-slot="pagination-item" {...props} />;
}
/**
* A link component.
* Renders an `<a>` element.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Link {
export type Props = useRender.ComponentProps<'a'> &
Pick<Button.Props, 'size'> & {
/**
* Whether the link is active.
* @default false
*/
isActive?: boolean;
};
}
export function Link({ className, render, isActive, size = 'icon', ...props }: Link.Props) {
const defaultProps: useRender.ElementProps<'a'> & { 'data-slot'?: string } = {
'data-slot': 'pagination-link',
className: cn(
buttonVariants({
variant: isActive ? 'outline' : 'ghost',
size,
}),
className
),
};
return useRender({
defaultTagName: 'a',
render,
state: {
active: isActive,
},
stateAttributesMapping: {
active: (value) => (value ? { 'aria-current': 'page' } : null),
},
props: mergeProps<'a'>(defaultProps, props),
});
}
/**
* The previous page link.
* Renders a {@link Link} component.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Previous {
export type Props = React.ComponentProps<typeof Link>;
}
export function Previous({ className, ...props }: Previous.Props) {
return (
<Link
aria-label="Go to previous page"
className={cn('gap-1 px-2.5 sm:pl-2.5', className)}
size="md"
{...props}
>
<ChevronLeftIcon />
<span className="hidden sm:block">Previous</span>
</Link>
);
}
/**
* The next page link.
* Renders a {@link Link} component.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Next {
export type Props = React.ComponentProps<typeof Link>;
}
export function Next({ className, ...props }: Next.Props) {
return (
<Link
aria-label="Go to next page"
className={cn('gap-1 px-2.5 sm:pr-2.5', className)}
size="md"
{...props}
>
<span className="hidden sm:block">Next</span>
<ChevronRightIcon />
</Link>
);
}
/**
* An ellipsis component.
* Renders a `<span>` element.
*
* Documentation: [Caprice UI Pagination](https://caprice-ui.com/docs/components/pagination)
*/
export namespace Ellipsis {
export type Props = React.ComponentProps<'span'>;
}
export function Ellipsis({ className, ...props }: Ellipsis.Props) {
return (
<span
aria-hidden
className={cn('flex size-9 items-center justify-center', className)}
data-slot="pagination-ellipsis"
{...props}
>
<MoreHorizontalIcon className="size-4" />
<span className="sr-only">More pages</span>
</span>
);
}
Update the import paths to match your project setup.
Usage
import * as Pagination from "@/components/caprice-ui/pagination"import * as Pagination from "@caprice-ui/react/pagination"<Pagination.Root>
<Pagination.Content>
<Pagination.Item>
<PaginationPrevious href="#" />
</Pagination.Item>
<Pagination.Item>
<PaginationLink href="#">1</PaginationLink>
</Pagination.Item>
<Pagination.Item>
<Pagination.Ellipsis />
</Pagination.Item>
<Pagination.Item>
<Pagination.Next href="#" />
</Pagination.Item>
</Pagination.Content>
</Pagination.Root>Custom Link
By default the <Pagination.Link /> component will render an tag, you can customize the link by passing a render prop.
import Link from 'next/link';
<Pagination.Root>
<Pagination.Content>
<Pagination.Item>
<Pagination.Link render={<Link href="#" />} />
</Pagination.Item>
</Pagination.Content>
</Pagination.Root>Last updated on