Skip to content

UIPagination

UIPagination

A versatile pagination component that provides intuitive navigation through paginated content with support for various layouts, sizes, and customization options.

<template>
<UIPagination
v-model="currentPage"
:total="totalItems"
:pageSize="itemsPerPage"
:showSizeChanger="true"
:showQuickJumper="true"
:showTotal="total => `Total ${total} items`"
@change="handlePageChange"
@sizeChange="handleSizeChange"
/>
</template>
<script setup lang="ts">
const currentPage = ref(1)
const totalItems = ref(100)
const itemsPerPage = ref(10)
const handlePageChange = (page: number) => {
// Handle page change
}
const handleSizeChange = (size: number) => {
// Handle page size change
}
</script>

Props

  • modelValue (number): Current page number
  • total (number): Total number of items
  • pageSize (number): Items per page
  • pageSizeOptions (array): Available page size options
  • showSizeChanger (boolean): Show page size selector
  • showQuickJumper (boolean): Show quick jump input
  • showTotal (function): Custom total text renderer
  • simple (boolean): Use simple mode
  • disabled (boolean): Disable pagination
  • loading (boolean): Loading state
  • size (‘sm’ | ‘md’ | ‘lg’): Component size
  • hideOnSinglePage (boolean): Hide when only one page
  • responsive (boolean): Enable responsive mode
  • align (‘left’ | ‘center’ | ‘right’): Alignment

Events

  • update:modelValue: Page number changed
  • change: Page changed
  • sizeChange: Page size changed
  • jump: Quick jump triggered

Slots

  • total: Custom total content
  • prev: Custom previous button
  • next: Custom next button
  • pageSize: Custom page size selector

Usage Examples

  1. Basic Pagination:
<template>
<UIPagination
v-model="page"
:total="100"
:pageSize="10"
/>
</template>
<script setup>
const page = ref(1)
</script>
  1. Advanced Data Table Pagination:
<template>
<div class="space-y-4">
<UITable
:data="tableData"
:columns="columns"
:loading="loading"
/>
<div class="flex items-center justify-between">
<div class="text-sm text-gray-500">
Showing {{ startIndex }} to {{ endIndex }} of {{ total }} entries
</div>
<UIPagination
v-model="pagination.page"
:total="total"
:pageSize="pagination.pageSize"
:showSizeChanger="true"
:pageSizeOptions="[10, 20, 50, 100]"
@change="fetchData"
@sizeChange="handleSizeChange"
>
<template #total="{ total }">
<span class="mr-4 text-sm text-gray-500">
Total {{ total }} items
</span>
</template>
</UIPagination>
</div>
</div>
</template>
<script setup>
const pagination = reactive({
page: 1,
pageSize: 10
})
const startIndex = computed(() => {
return (pagination.page - 1) * pagination.pageSize + 1
})
const endIndex = computed(() => {
return Math.min(pagination.page * pagination.pageSize, total.value)
})
const handleSizeChange = (size: number) => {
pagination.pageSize = size
pagination.page = 1
fetchData()
}
</script>
  1. Infinite Scroll with Load More:
<template>
<div class="space-y-4">
<div class="grid gap-4">
<ItemCard
v-for="item in items"
:key="item.id"
:item="item"
/>
</div>
<div
v-if="hasMore"
class="flex justify-center"
>
<UIPagination
v-model="page"
:total="total"
:pageSize="pageSize"
:simple="true"
:loading="loading"
>
<template #next>
<UIButton
:loading="loading"
@click="loadMore"
>
Load More
</UIButton>
</template>
</UIPagination>
</div>
</div>
</template>
<script setup>
const page = ref(1)
const pageSize = 20
const total = ref(0)
const items = ref([])
const loading = ref(false)
const hasMore = computed(() => {
return items.value.length < total.value
})
const loadMore = async () => {
if (loading.value) return
loading.value = true
try {
const newItems = await fetchItems(page.value, pageSize)
items.value.push(...newItems)
page.value++
} finally {
loading.value = false
}
}
</script>

Best Practices

  1. User Experience:

    • Clear navigation
    • Visual feedback
    • Consistent layout
    • Responsive design
  2. Performance:

    • Efficient updates
    • Debounced input
    • Optimized rendering
    • Memory management
  3. Accessibility:

    • ARIA labels
    • Keyboard navigation
    • Focus management
    • Screen reader support
  4. Mobile:

    • Touch targets
    • Simple mode
    • Responsive layout
    • Clear indicators

Common Use Cases

  1. Table Footer:
<template>
<div class="flex items-center justify-between py-4">
<div class="flex items-center space-x-4">
<UISelect
v-model="pageSize"
:options="pageSizeOptions"
size="sm"
class="w-20"
/>
<span class="text-sm text-gray-500">
items per page
</span>
</div>
<UIPagination
v-model="page"
:total="total"
:pageSize="pageSize"
size="sm"
/>
</div>
</template>
  1. Search Results:
<template>
<div class="space-y-6">
<div class="text-sm text-gray-500">
{{ totalResults }} results found
</div>
<div class="space-y-4">
<SearchResult
v-for="result in results"
:key="result.id"
:result="result"
/>
</div>
<UIPagination
v-model="page"
:total="totalResults"
:pageSize="10"
:showQuickJumper="true"
align="center"
@change="handleSearch"
/>
</div>
</template>
  1. Mobile List:
<template>
<div class="space-y-4">
<div class="divide-y">
<ListItem
v-for="item in items"
:key="item.id"
:item="item"
/>
</div>
<UIPagination
v-model="page"
:total="total"
:pageSize="pageSize"
:simple="true"
size="lg"
class="flex justify-center"
>
<template #prev>
<UIButton
variant="ghost"
:disabled="page === 1"
>
<ChevronLeftIcon class="w-5 h-5" />
Previous
</UIButton>
</template>
<template #next>
<UIButton
variant="ghost"
:disabled="page === totalPages"
>
Next
<ChevronRightIcon class="w-5 h-5" />
</UIButton>
</template>
</UIPagination>
</div>
</template>

Component Composition

The UIPagination component works well with:

  • UITable for data tables
  • UISelect for page size selection
  • UIButton for custom navigation
  • UIInput for quick jumper
  • UISpinner for loading states
  • UITooltip for page information