Examples
Basic
Prop | Default | Type | Description |
---|---|---|---|
total | 0 | number | The total number of items in your list. |
defaultPage | 1 | number | The value of the page that should be active when initially rendered. Use when you do not need to control the value state. |
disabled | false | boolean | When true, prevents the user from interacting with item. |
itemsPerPage | 10 | number | Number of items per page. |
page | - | number | The controlled value of the current page. Can be binded as v-model:page . |
showEdges | false | boolean | When true, always show first page, last page, and ellipsis. |
Read more in Reka Pagination Root API.
Preview
Code
<script setup lang="ts">
const currentPage = ref(1)
</script>
<template>
<div class="flex overflow-auto">
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
show-edges
/>
</div>
</template>
Sibling Count
Prop | Default | Type | Description |
---|---|---|---|
siblingCount | 2 | number | The number of surrounding pages displayed around the current page. |
Preview
Code
<script lang="ts" setup>
const currentPage = ref(1)
</script>
<template>
<div class="flex flex-col space-y-4">
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="300"
:sibling-count="3"
/>
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="300"
:sibling-count="1"
/>
</div>
</template>
Visibility
Prop | Default | Type | Description |
---|---|---|---|
showFirst | true | boolean | Displays the first page button. |
showLast | true | boolean | Displays the last page button. |
showPrev | true | boolean | Displays the previous page button. |
showNext | true | boolean | Displays the next page button. |
showListItem | true | boolean | Displays the list items. |
Preview
Code
Current Page: 1
<script setup lang="ts">
const currentPage = ref(1)
</script>
<template>
<div class="flex flex-col space-y-4">
<span>Current Page: {{ currentPage }}</span>
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
:show-list-item="false"
/>
</div>
</template>
Size
Prop | Default | Type | Description |
---|---|---|---|
size | sm | string | Adjusts the size of the entire pagination. |
firstPageSize | sm | string | Customizes the size of the first page button. |
lastPageSize | sm | string | Customizes the size of the last page button. |
prevPageSize | sm | string | Customizes the size of the previous page button. |
nextPageSize | sm | string | Customizes the size of the next page button. |
listItemSize | sm | string | Customizes the size of the page list items. |
ellipsisSize | sm | string | Customizes the size of the ellipsis indicator. |
By default, the size prop applies to height, width, padding, and font size. If you only want to change the size of the button, use the square
prop. Refer to the Button square section for more information.
Read more in Button size section
Preview
Code
<script lang="ts" setup>
const currentPage = ref(1)
</script>
<template>
<div class="flex flex-col space-y-4">
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
size="xs"
/>
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
size="sm"
/>
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
size="md"
/>
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
size="lg"
/>
</div>
</template>
Variant and Color
Prop | Default | Type | Description |
---|---|---|---|
pagination-selected | solid-primary | {variant}-{color} | The color of the selected page. |
pagination-unselected | solid-white | {variant}-{color} | The color of the unselected page. |
pagination-ellipsis | text-black | {variant}-{color} | The color of the ellipsis. |
Read more in Button variant and color section
Preview
Code
<script lang="ts" setup>
const currentPage = ref(1)
</script>
<template>
<div class="flex flex-col">
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-black"
pagination-unselected="ghost-gray"
show-edges
/>
<NSeparator />
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="soft-primary"
pagination-unselected="link-primary"
pagination-ellipsis="text-primary"
show-edges
/>
<NSeparator />
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-pink"
pagination-unselected="outline-pink"
pagination-ellipsis="text-pink"
show-edges
/>
<NSeparator />
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-indigo"
pagination-unselected="soft-indigo"
pagination-ellipsis="text-indigo"
show-edges
/>
</div>
</template>
Rounded
Preview
Code
<script lang="ts" setup>
const currentPage = ref(1)
</script>
<template>
<div class="flex flex-col">
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-white"
pagination-unselected="ghost-gray"
rounded="b-2xl"
/>
<NSeparator />
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-orange"
pagination-unselected="outline-white"
/>
<NSeparator />
<NPagination
v-model:page="currentPage"
:items-per-page="10"
:total="100"
pagination-selected="solid-yellow"
pagination-unselected="outline-white"
rounded="t-full"
/>
</div>
</template>
Read more in Button rounded section
Sub Components
Prop | API reference | Description |
---|---|---|
_pagination-list-item | Reka Pagination ListItem API | Customizes the pagination list item component. |
_pagination-prev | Reka Pagination Prev API | Customizes the previous page navigation button. |
_pagination-next | Reka Pagination Next API | Customizes the next page navigation button. |
_pagination-first | Reka Pagination First API | Customizes the first page navigation button. |
_pagination-last | Reka Pagination Last API | Customizes the last page navigation button. |
_pagination-ellipsis | Reka Pagination Ellipsis API | Customizes the ellipsis indicator in the pagination. |
_pagination-list | Reka Pagination List API | Customizes the pagination list component. |
Preview
Code
<template>
<div class="flex items-start overflow-auto">
<NPagination
:total="100"
:items-per-page="10"
:show-first="false"
:show-last="false"
show-edges
rounded="none"
:_pagination-list="{
class: 'gap-0 divide-x divide-base border-1 border-base',
rounded: 'r-full l-full',
}"
:_pagination-prev="{
icon: false,
square: false,
paginationUnselected: 'ghost-white',
label: 'Previous',
leading: 'i-lucide-arrow-left',
}"
:_pagination-list-item="{
paginationUnselected: 'ghost-white',
paginationSelected: 'solid-black',
}"
:_pagination-next="{
icon: false,
square: false,
paginationUnselected: 'ghost-white',
label: 'Next',
trailing: 'i-lucide-arrow-right',
}"
/>
</div>
</template>
Slots
Name | Props | Description |
---|---|---|
first | - | Customizes the first page navigation button. |
last | - | Customizes the last page navigation button. |
prev | - | Customizes the previous page navigation button. |
next | - | Customizes the next page navigation button. |
list-item | item , page | Customizes the pagination list item component. |
ellipsis | - | Customizes the ellipsis indicator in the pagination. |
Preview
Code
<template>
<div class="flex items-start overflow-auto">
<NPagination
:items-per-page="10"
:total="100"
:show-first="false"
:show-last="false"
show-edges
>
<template #prev>
<NButton
btn="ghost-gray"
label="Previous"
leading="i-lucide-chevron-left"
/>
</template>
<template #list-item="{ item, page }">
<NPaginationListItem
square
pagination-unselected="ghost-gray"
pagination-selected="solid-white"
:value="item.value"
class="gap-0"
leading="i-lucide-hash"
:label="`${item.value}`"
:page
:una="{
btnLeading: 'text-10px',
}"
/>
</template>
<template #ellipsis>
<NIcon
name="i-lucide-chevrons-left-right-ellipsis"
size="xs"
/>
</template>
<template #next>
<NButton
btn="ghost-gray"
label="Next"
trailing="i-lucide-chevron-right"
/>
</template>
</NPagination>
</div>
</template>
Presets
shortcuts/pagination.ts
type PaginationPrefix = 'pagination'
export const staticPagination: Record<`${PaginationPrefix}-${string}` | PaginationPrefix, string> = {
// configurations
'pagination': 'overflow-hidden',
'pagination-list': 'flex items-center gap-1 overflow-hidden',
// components
'pagination-root': '',
'pagination-list-item': 'pagination',
'pagination-ellipsis-base': 'btn-(~ square) flex items-center justify-center',
'pagination-ellipsis-icon-base': 'square-1.25em',
'pagination-ellipsis-icon': 'i-lucide-ellipsis',
'pagination-first': 'pagination',
'pagination-first-icon': 'i-lucide-chevrons-left',
'pagination-prev': 'pagination',
'pagination-prev-icon': 'i-lucide-chevron-left',
'pagination-next': 'pagination',
'pagination-next-icon': 'i-lucide-chevron-right',
'pagination-last': 'pagination',
'pagination-last-icon': 'i-lucide-chevrons-right',
}
export const dynamicPagination = [
[
/^pagination-ellipsis(?:-([^-]+))?(?:-([^-]+))?$/,
([, variant = 'text', color = 'black']) =>
`btn-${variant}-${color}`,
],
[
/^pagination-selected(?:-([^-]+))?(?:-([^-]+))?$/,
([, variant = 'solid', color = 'primary']) =>
`data-[selected=true]:btn-${variant}-${color}`,
],
[
/^pagination-unselected(?:-([^-]+))?(?:-([^-]+))?$/,
([, variant = 'solid', color = 'white']) =>
`data-[selected=false]:btn-${variant}-${color}`,
],
]
export const pagination = [
...dynamicPagination,
staticPagination,
]
Props
types/pagination.ts
import type { PaginationEllipsisProps, PaginationFirstProps, PaginationLastProps, PaginationListItemProps, PaginationListProps, PaginationNextProps, PaginationPrevProps, PaginationRootProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import type { NButtonProps } from './button'
interface BaseExtensionProps {
square?: HTMLAttributes['class']
class?: HTMLAttributes['class']
rounded?: HTMLAttributes['class']
size?: HTMLAttributes['class']
}
type isVisible = boolean
export interface NPaginationProps extends
PaginationRootProps,
BaseExtensionProps,
Pick<NButtonProps, 'paginationSelected' | 'paginationUnselected'>,
Pick<NPaginationEllipsisProps, 'paginationEllipsis'> {
showFirst?: isVisible
showPrev?: isVisible
showNext?: isVisible
showLast?: isVisible
showListItem?: isVisible
// sub-components
_paginationList?: Partial<NPaginationListProps>
_paginationListItem?: Partial<NPaginationListItemProps>
_paginationEllipsis?: Partial<NPaginationEllipsisProps>
_paginationFirst?: Partial<NPaginationFirstProps>
_paginationPrev?: Partial<NPaginationPrevProps>
_paginationNext?: Partial<NPaginationNextProps>
_paginationLast?: Partial<NPaginationLastProps>
una?: NPaginationUnaProps
}
export interface NPaginationListProps extends PaginationListProps, BaseExtensionProps {
una?: Pick<NPaginationUnaProps, 'paginationList'>
}
export interface NPaginationListItemProps extends PaginationListItemProps, Omit<NButtonProps, 'una'> {
isSelected?: boolean
page?: PaginationRootProps['page']
una?: Pick<NPaginationUnaProps, 'paginationListItem' | 'pagination'> & NButtonProps['una']
}
export interface NPaginationEllipsisProps extends PaginationEllipsisProps, BaseExtensionProps {
paginationEllipsis?: HTMLAttributes['class']
una?: Pick<NPaginationUnaProps, 'paginationEllipsis' | 'paginationEllipsisIconBase' | 'paginationEllipsisIcon' | 'pagination'>
}
export interface NPaginationFirstProps extends PaginationFirstProps, Omit<NButtonProps, 'una'> {
una?: Pick<NPaginationUnaProps, 'paginationFirst' | 'pagination'> & NButtonProps['una']
}
export interface NPaginationPrevProps extends PaginationPrevProps, Omit<NButtonProps, 'una'> {
una?: Pick<NPaginationUnaProps, 'paginationPrev' | 'pagination'> & NButtonProps['una']
}
export interface NPaginationNextProps extends PaginationNextProps, Omit<NButtonProps, 'una'> {
una?: Pick<NPaginationUnaProps, 'paginationNext' | 'pagination'> & NButtonProps['una']
}
export interface NPaginationLastProps extends PaginationLastProps, Omit<NButtonProps, 'una'> {
una?: Pick<NPaginationUnaProps, 'paginationLast' | 'pagination'> & NButtonProps['una']
}
interface NPaginationUnaProps {
pagination?: HTMLAttributes['class']
paginationRoot?: HTMLAttributes['class']
paginationList?: HTMLAttributes['class']
paginationNext?: HTMLAttributes['class']
paginationPrev?: HTMLAttributes['class']
paginationFirst?: HTMLAttributes['class']
paginationLast?: HTMLAttributes['class']
paginationListItem?: HTMLAttributes['class']
paginationEllipsis?: HTMLAttributes['class']
paginationEllipsisIconBase?: HTMLAttributes['class']
paginationEllipsisIcon?: HTMLAttributes['class']
}
Components
Pagination.vue
PaginationEllipsis.vue
PaginationListItem.vue
PaginationFirst.vue
PaginationLast.vue
PaginationNext.vue
PaginationPrev.vue
<script setup lang="ts">
import type { PaginationRootEmits } from 'reka-ui'
import type { NPaginationProps } from '../../../types'
import { reactivePick } from '@vueuse/core'
import { PaginationList, PaginationRoot, useForwardPropsEmits } from 'reka-ui'
import { cn } from '../../../utils'
import PaginationEllipsis from './PaginationEllipsis.vue'
import PaginationFirst from './PaginationFirst.vue'
import PaginationLast from './PaginationLast.vue'
import PaginationListItem from './PaginationListItem.vue'
import PaginationNext from './PaginationNext.vue'
import PaginationPrev from './PaginationPrev.vue'
const props = withDefaults(defineProps<NPaginationProps>(), {
showFirst: true,
showLast: true,
showListItem: true,
showNext: true,
showPrev: true,
})
const emits = defineEmits<PaginationRootEmits>()
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultPage', 'disabled', 'itemsPerPage', 'page', 'showEdges', 'siblingCount', 'total'), emits)
</script>
<template>
<PaginationRoot
v-slot="{ page }"
v-bind="rootProps"
:class="cn(
'pagination-root',
props.class,
props.una?.paginationRoot,
)"
>
<PaginationList
v-slot="{ items }"
:class="cn(
'pagination-list',
props?._paginationList?.class,
props.una?.paginationList,
)"
v-bind="_paginationList"
>
<slot>
<PaginationFirst
v-if="showFirst"
:rounded
:size
:pagination-selected
:pagination-unselected
v-bind="_paginationFirst"
:square
:una
>
<slot
name="first"
/>
</PaginationFirst>
<PaginationPrev
v-if="showPrev"
:rounded
:pagination-selected
:pagination-unselected
:size
v-bind="_paginationPrev"
:square
:una
>
<slot
name="prev"
/>
</PaginationPrev>
<template v-if="showListItem">
<template v-for="(item, index) in items">
<slot
v-if="item.type === 'page'"
name="list-item"
:item="item"
:page="page"
>
<PaginationListItem
:key="index"
:value="item.value"
:page
:rounded
:size
:pagination-selected
:pagination-unselected
:square
:una
v-bind="_paginationListItem"
/>
</slot>
<PaginationEllipsis
v-else
:key="item.type"
:index="index"
:rounded
:size
:pagination-ellipsis
:square
:una
v-bind="_paginationEllipsis"
>
<slot
name="ellipsis"
/>
</PaginationEllipsis>
</template>
</template>
<PaginationNext
v-if="showNext"
:rounded
:size
:pagination-selected
:pagination-unselected
v-bind="_paginationNext"
:square
:una
>
<slot
name="next"
/>
</PaginationNext>
<PaginationLast
v-if="showLast"
:rounded
:size
:pagination-selected
:pagination-unselected
:square
:una
v-bind="_paginationLast"
>
<slot
name="last"
/>
</PaginationLast>
</slot>
</PaginationList>
</PaginationRoot>
</template>
<script setup lang="ts">
import type { NPaginationEllipsisProps } from '../../../types'
import { PaginationEllipsis, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Icon from '../../elements/Icon.vue'
const props = withDefaults(defineProps<NPaginationEllipsisProps>(), {
paginationEllipsis: '~',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationEllipsis
v-bind="forwardedProps"
:pagination-ellipsis
:class="cn(
'pagination-ellipsis-base',
props.una?.pagination,
props.una?.paginationEllipsis,
props.class,
)"
>
<slot>
<Icon
:class="cn(
'pagination-ellipsis-icon-base',
props.una?.paginationEllipsisIconBase,
)"
:name="forwardedProps?.una?.paginationEllipsisIcon || 'pagination-ellipsis-icon'"
/>
</slot>
</PaginationEllipsis>
</template>
<script setup lang="ts">
import type { NPaginationListItemProps } from '../../../types'
import { PaginationListItem, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = withDefaults(defineProps<NPaginationListItemProps>(), {
paginationSelected: '~',
paginationUnselected: '~',
square: true,
})
const delegatedProps = computed(() => {
const { value: __, class: _, ...delegated } = props
return delegated
})
const label = computed(() => {
return props.label || props.value.toString()
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationListItem
:value
as-child
:data-selected="value === page"
>
<Button
v-bind="forwardedProps"
:label
:class="cn(
'pagination-list-item',
props?.una?.pagination,
props?.una?.paginationListItem,
props.class,
)"
>
<template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData" />
</template>
</Button>
</PaginationListItem>
</template>
<script setup lang="ts">
import type { NPaginationFirstProps } from '../../../types'
import { PaginationFirst, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = withDefaults(defineProps<NPaginationFirstProps>(), {
square: true,
paginationUnselected: '~',
icon: true,
label: 'pagination-first-icon',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationFirst
as-child
>
<slot>
<Button
:data-selected="false"
v-bind="forwardedProps"
:class="cn(
'pagination-first',
props.una?.pagination,
props.una?.paginationFirst,
props.class,
)"
/>
</slot>
</PaginationFirst>
</template>
<script setup lang="ts">
import type { NPaginationLastProps } from '../../../types'
import { PaginationLast, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = withDefaults(defineProps<NPaginationLastProps>(), {
paginationUnselected: '~',
icon: true,
square: true,
label: 'pagination-last-icon',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationLast as-child>
<slot>
<Button
:data-selected="false"
v-bind="forwardedProps"
:class="cn(
'pagination-last',
props.una?.pagination,
props.una?.paginationLast,
props.class,
)"
/>
</slot>
</paginationlast>
</template>
<script setup lang="ts">
import type { NPaginationNextProps } from '../../../types'
import { PaginationNext, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = withDefaults(defineProps<NPaginationNextProps>(), {
paginationUnselected: '~',
square: true,
icon: true,
label: 'pagination-next-icon',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationNext as-child>
<slot>
<Button
:data-selected="false"
v-bind="forwardedProps"
:class="cn(
'pagination-next',
props.una?.pagination,
props.una?.paginationNext,
props.class,
)"
/>
</slot>
</PaginationNext>
</template>
<script setup lang="ts">
import type { NPaginationPrevProps } from '../../../types'
import { PaginationPrev, useForwardProps } from 'reka-ui'
import { computed } from 'vue'
import { cn } from '../../../utils'
import Button from '../../elements/Button.vue'
const props = withDefaults(defineProps<NPaginationPrevProps>(), {
paginationUnselected: '~',
square: true,
icon: true,
label: 'pagination-prev-icon',
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const forwardedProps = useForwardProps(delegatedProps)
</script>
<template>
<PaginationPrev as-child>
<slot>
<Button
:data-selected="false"
v-bind="forwardedProps"
:class="cn(
'pagination-prev',
props.una?.pagination,
props.una?.paginationPrev,
props.class,
)"
/>
</slot>
</PaginationPrev>
</template>