<Pagination count={100} defaultPageSize={10} siblingCount={1} />
npx @left4code/cosmic-ui-cli@latest add pagination
This writes the component and everything it imports, then installs the packages it needs. Run npx @left4code/cosmic-ui-cli@latest initfirst if you haven't already.
Install the following dependencies:
Built directly on the Zag.js state machine. This is a single self-contained component rather than a Root + parts split - the page buttons come from api.pages, an array the machine computes from count / pageSize / siblingCount, so there's nothing left for a consumer to compose by hand. The plain border shown here is a placeholder; swap it for the Frame primitive later. Copy and paste the following code into your project.
import { useId } from "react";
import { twMerge } from "tailwind-merge";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { useMachine, normalizeProps } from "@zag-js/react";
import * as paginationMachine from "@zag-js/pagination";
function Pagination({
className,
...rest
}: Partial<paginationMachine.Props> & { className?: string }) {
const service = useMachine(paginationMachine.machine, { id: useId(), ...rest });
const api = paginationMachine.connect(service, normalizeProps);
return (
<div {...api.getRootProps()} className={twMerge(["flex items-center gap-1.5", className])}>
<button
{...api.getPrevTriggerProps()}
className="size-8 flex items-center justify-center border border-primary/30 hover:bg-primary/10 disabled:opacity-30 disabled:pointer-events-none"
>
<ChevronLeft className="size-4" />
</button>
{api.pages.map((page, i) =>
page.type === "page" ? (
<button
key={i}
{...api.getItemProps(page)}
className="size-8 border border-primary/30 hover:bg-primary/10 data-[selected]:bg-primary/20 data-[selected]:border-primary"
>
{page.value}
</button>
) : (
<span
key={i}
{...api.getEllipsisProps({ index: i })}
className="size-8 flex items-center justify-center"
>
…
</span>
)
)}
<button
{...api.getNextTriggerProps()}
className="size-8 flex items-center justify-center border border-primary/30 hover:bg-primary/10 disabled:opacity-30 disabled:pointer-events-none"
>
<ChevronRight className="size-4" />
</button>
</div>
);
}
export { Pagination };
Update the import paths to match your project setup.
import { Pagination } from "@/components/ui/pagination";
<Pagination count={100} defaultPageSize={10} siblingCount={1} />