diff --git a/packages/ui/package.json b/packages/ui/package.json
index cac3a9e2fe..048ef5e389 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -53,7 +53,7 @@
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-radio-group": "^1.3.8",
"@radix-ui/react-select": "^2.2.6",
- "@radix-ui/react-slot": "^1.2.3",
+ "@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tooltip": "^1.2.8",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"class-variance-authority": "^0.7.1",
diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts
index 8e43bebba6..f404714c28 100644
--- a/packages/ui/src/components/index.ts
+++ b/packages/ui/src/components/index.ts
@@ -58,6 +58,7 @@ export * from './primitives/combobox'
export * from './primitives/command'
export * from './primitives/dialog'
export * from './primitives/kbd'
+export * from './primitives/pagination'
export * from './primitives/popover'
export * from './primitives/radioGroup'
export * from './primitives/select'
diff --git a/packages/ui/src/components/primitives/pagination.tsx b/packages/ui/src/components/primitives/pagination.tsx
new file mode 100644
index 0000000000..2de5a36592
--- /dev/null
+++ b/packages/ui/src/components/primitives/pagination.tsx
@@ -0,0 +1,98 @@
+import { Button, buttonVariants } from '@cherrystudio/ui/components/primitives/button'
+import { cn } from '@cherrystudio/ui/utils/index'
+import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from 'lucide-react'
+import * as React from 'react'
+
+function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
+ return (
+
+ )
+}
+
+function PaginationContent({ className, ...props }: React.ComponentProps<'ul'>) {
+ return
+}
+
+function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
+ return
+}
+
+type PaginationLinkProps = {
+ isActive?: boolean
+} & Pick, 'size'> &
+ React.ComponentProps<'a'>
+
+function PaginationLink({ className, isActive, size = 'icon', ...props }: PaginationLinkProps) {
+ return (
+
+ )
+}
+
+function PaginationPrevious({ className, ...props }: React.ComponentProps) {
+ return (
+
+
+ Previous
+
+ )
+}
+
+function PaginationNext({ className, ...props }: React.ComponentProps) {
+ return (
+
+ Next
+
+
+ )
+}
+
+function PaginationEllipsis({ className, ...props }: React.ComponentProps<'span'>) {
+ return (
+
+
+ More pages
+
+ )
+}
+
+export {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious
+}
diff --git a/packages/ui/stories/components/primitives/Pagination.stories.tsx b/packages/ui/stories/components/primitives/Pagination.stories.tsx
new file mode 100644
index 0000000000..9c827dbb25
--- /dev/null
+++ b/packages/ui/stories/components/primitives/Pagination.stories.tsx
@@ -0,0 +1,182 @@
+import type { Meta, StoryObj } from '@storybook/react'
+
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious
+} from '../../../src/components/primitives/pagination'
+
+const meta: Meta = {
+ title: 'Components/Primitives/Pagination',
+ component: Pagination,
+ parameters: {
+ layout: 'centered',
+ docs: {
+ description: {
+ component: 'Pagination with page navigation, next and previous links. Based on shadcn/ui.'
+ }
+ }
+ },
+ tags: ['autodocs'],
+ argTypes: {
+ className: {
+ control: { type: 'text' },
+ description: 'Additional CSS classes'
+ }
+ }
+}
+
+export default meta
+type Story = StoryObj
+
+// Default
+export const Default: Story = {
+ render: () => (
+
+
+
+
+
+
+ 1
+
+
+
+ 2
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+ )
+}
+
+// Simple
+export const Simple: Story = {
+ render: () => (
+
+
+
+
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+
+
+
+
+ )
+}
+
+// With Ellipsis
+export const WithEllipsis: Story = {
+ render: () => (
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ 4
+
+
+
+ 5
+
+
+
+ 6
+
+
+
+
+
+ 10
+
+
+
+
+
+
+ )
+}
+
+// First Page Active
+export const FirstPageActive: Story = {
+ render: () => (
+
+
+
+
+
+
+
+ 1
+
+
+
+ 2
+
+
+ 3
+
+
+
+
+
+
+ )
+}
+
+// Last Page Active
+export const LastPageActive: Story = {
+ render: () => (
+
+
+
+
+
+
+ 1
+
+
+ 2
+
+
+
+ 3
+
+
+
+
+
+
+
+ )
+}
diff --git a/yarn.lock b/yarn.lock
index 9bd40c81b5..89ab3ec608 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2256,7 +2256,7 @@ __metadata:
"@radix-ui/react-popover": "npm:^1.1.15"
"@radix-ui/react-radio-group": "npm:^1.3.8"
"@radix-ui/react-select": "npm:^2.2.6"
- "@radix-ui/react-slot": "npm:^1.2.3"
+ "@radix-ui/react-slot": "npm:^1.2.4"
"@radix-ui/react-tooltip": "npm:^1.2.8"
"@radix-ui/react-use-controllable-state": "npm:^1.2.2"
"@storybook/addon-docs": "npm:^10.0.5"
@@ -7617,7 +7617,7 @@ __metadata:
languageName: node
linkType: hard
-"@radix-ui/react-slot@npm:1.2.3, @radix-ui/react-slot@npm:^1.2.3":
+"@radix-ui/react-slot@npm:1.2.3":
version: 1.2.3
resolution: "@radix-ui/react-slot@npm:1.2.3"
dependencies:
@@ -7632,6 +7632,21 @@ __metadata:
languageName: node
linkType: hard
+"@radix-ui/react-slot@npm:^1.2.4":
+ version: 1.2.4
+ resolution: "@radix-ui/react-slot@npm:1.2.4"
+ dependencies:
+ "@radix-ui/react-compose-refs": "npm:1.1.2"
+ peerDependencies:
+ "@types/react": "*"
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/8b719bb934f1ae5ac0e37214783085c17c2f1080217caf514c1c6cc3d9ca56c7e19d25470b26da79aa6e605ab36589edaade149b76f5fc0666f1063e2fc0a0dc
+ languageName: node
+ linkType: hard
+
"@radix-ui/react-tooltip@npm:^1.2.8":
version: 1.2.8
resolution: "@radix-ui/react-tooltip@npm:1.2.8"