Zaidan

Command Palette

Search for a command to run...

GitHub

Pagination

Pagination with page navigation, next and previous links.

Installation

CLI

Manual

Copy and paste the following code into your project.

import { ChevronLeft, ChevronRight, Ellipsis } from "lucide-solid";
import type { ComponentProps } from "solid-js";
import { mergeProps, splitProps } from "solid-js";
import { cn } from "~/lib/utils";
import { Button, type ButtonProps } from "~/components/ui/button";
type PaginationProps = ComponentProps<"nav">;
const Pagination = (props: PaginationProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<nav
aria-label="pagination"
data-slot="pagination"
class={cn("z-pagination mx-auto flex w-full justify-center", local.class)}
{...others}
/>
);
};
type PaginationContentProps = ComponentProps<"ul">;
const PaginationContent = (props: PaginationContentProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<ul
data-slot="pagination-content"
class={cn("z-pagination-content flex items-center", local.class)}
{...others}
/>
);
};
type PaginationItemProps = ComponentProps<"li">;
const PaginationItem = (props: PaginationItemProps) => {
return <li data-slot="pagination-item" {...props} />;
};
type PaginationLinkProps = {
isActive?: boolean;
} & Pick<ButtonProps, "size"> &
ComponentProps<"a">;
const PaginationLink = (props: PaginationLinkProps) => {
const mergedProps = mergeProps({ size: "icon" } as PaginationLinkProps, props);
const [local, others] = splitProps(mergedProps, ["class", "isActive", "size"]);
return (
<Button
as="a"
variant={local.isActive ? "outline" : "ghost"}
size={local.size}
class={cn("z-pagination-link", local.class)}
aria-current={local.isActive ? "page" : undefined}
data-slot="pagination-link"
data-active={local.isActive}
{...others}
/>
);
};
type PaginationPreviousProps = ComponentProps<typeof PaginationLink>;
const PaginationPrevious = (props: PaginationPreviousProps) => {
const [local, others] = splitProps(props, ["class", "children"]);
return (
<PaginationLink
aria-label="Go to previous page"
size="default"
class={cn("z-pagination-previous", local.class)}
{...others}
>
<ChevronLeft data-icon="inline-start" />
<span class="z-pagination-previous-text hidden sm:block">Previous</span>
</PaginationLink>
);
};
type PaginationNextProps = ComponentProps<typeof PaginationLink>;
const PaginationNext = (props: PaginationNextProps) => {
const [local, others] = splitProps(props, ["class", "children"]);
return (
<PaginationLink
aria-label="Go to next page"
size="default"
class={cn("z-pagination-next", local.class)}
{...others}
>
<span class="z-pagination-next-text hidden sm:block">Next</span>
<ChevronRight data-icon="inline-end" />
</PaginationLink>
);
};
type PaginationEllipsisProps = ComponentProps<"span">;
const PaginationEllipsis = (props: PaginationEllipsisProps) => {
const [local, others] = splitProps(props, ["class"]);
return (
<span
aria-hidden
data-slot="pagination-ellipsis"
class={cn("z-pagination-ellipsis flex items-center justify-center", local.class)}
{...others}
>
<Ellipsis />
<span class="sr-only">More pages</span>
</span>
);
};
export {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
};

SolidJS Router

By default, the <PaginationLink /> component will render an <a> element. You can use the as prop to render a different component, such as a SolidJS Router <A> component.

import { A } from "@solidjs/router";
import { PaginationLink } from "~/components/ui/pagination";
<PaginationLink as={A} href="/page/2">
2
</PaginationLink>

Examples

Here are the source code of all the examples from the preview page:

Basic

import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "~/components/ui/pagination";
function PaginationBasic() {
return (
<Example title="Basic">
<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>
</Example>
);
}

Simple

import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
} from "~/components/ui/pagination";
function PaginationSimple() {
return (
<Example title="Simple">
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">4</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">5</PaginationLink>
</PaginationItem>
</PaginationContent>
</Pagination>
</Example>
);
}

With Select

import {
Pagination,
PaginationContent,
PaginationItem,
PaginationNext,
PaginationPrevious,
} from "~/components/ui/pagination";
import { Field, FieldLabel } from "~/components/ui/field";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
function PaginationIconsOnly() {
const items = [
{ value: "10", label: "10" },
{ value: "25", label: "25" },
{ value: "50", label: "50" },
{ value: "100", label: "100" },
];
return (
<Example title="With Select">
<div class="flex items-center justify-between gap-4">
<Field orientation="horizontal" class="w-fit">
<FieldLabel for="select-rows-per-page">Rows per page</FieldLabel>
<Select<(typeof items)[number]>
options={items}
optionValue="value"
optionTextValue="label"
defaultValue={items[1]}
itemComponent={(props) => (
<SelectItem item={props.item}>{props.item.rawValue.label}</SelectItem>
)}
>
<SelectTrigger class="w-20" id="select-rows-per-page">
<SelectValue<(typeof items)[number]>>
{(state) => state.selectedOption().label}
</SelectValue>
</SelectTrigger>
<SelectContent />
</Select>
</Field>
<Pagination class="mx-0 w-auto">
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</Example>
);
}