Skip to content

Commit

Permalink
feat(Pagination): add first and last page buttons (#842)
Browse files Browse the repository at this point in the history
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
Co-authored-by: Max Steinwand <msteinwand@kues.de>
  • Loading branch information
3 people committed Oct 25, 2023
1 parent 9c05b3a commit c5ce997
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>

<template>
<UPagination v-model="page" :total="items.length" :ui="{ rounded: 'first-of-type:rounded-s-md last-of-type:rounded-e-md' }">
<template #first="{ onClick }">
<UTooltip text="First page">
<UButton icon="i-heroicons-arrow-uturn-left" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:first-child]:rotate-180 me-2" @click="onClick" />
</UTooltip>
</template>

<template #last="{ onClick }">
<UTooltip text="Last page">
<UButton icon="i-heroicons-arrow-uturn-right-20-solid" color="primary" :ui="{ rounded: 'rounded-full' }" class="rtl:[&_span:last-child]:rotate-180 ms-2" @click="onClick" />
</UTooltip>
</template>
</UPagination>
</template>
35 changes: 35 additions & 0 deletions docs/content/5.navigation/3.pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Use the `size` prop to change the size of the buttons.
baseProps:
modelValue: 1
total: 100
showLast: true
showFirst: true
props:
size: 'sm'
---
Expand Down Expand Up @@ -89,6 +91,33 @@ excludedProps:
---
::

### First / Last :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}

Use the `first-button` and `last-button` props to customize the first and last buttons of the Pagination.

::component-card
---
baseProps:
modelValue: 1
total: 100
showFirst: true
showLast: true
props:
firstButton:
icon: 'i-heroicons-arrow-small-left-20-solid'
label: First
color: 'gray'
lastButton:
icon: 'i-heroicons-arrow-small-right-20-solid'
trailing: true
label: Last
color: 'gray'
excludedProps:
- firstButton
- lastButton
---
::

## Slots

### `prev` / `next`
Expand All @@ -97,6 +126,12 @@ Use the `#prev` and `#next` slots to set the content of the previous and next bu

:component-example{component="pagination-example-prev-next-slots"}

### `first` / `last` :u-badge{label="New" class="align-middle ml-2 !rounded-full" variant="subtle"}

Use the `#first` and `#last` slots to set the content of the first and last buttons.

:component-example{component="pagination-example-first-last-slots"}

## Props

:component-props
Expand Down
78 changes: 69 additions & 9 deletions src/runtime/components/navigation/Pagination.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
<template>
<div :class="ui.wrapper" v-bind="attrs">
<slot name="first" :on-click="onClickFirst">
<UButton
v-if="firstButton && showFirst"
:size="size"
:disabled="!canGoFirstOrPrev"
:class="[ui.base, ui.rounded]"
v-bind="{ ...ui.default.firstButton, ...firstButton }"
:ui="{ rounded: '' }"
aria-label="First"
@click="onClickFirst"
/>
</slot>

<slot name="prev" :on-click="onClickPrev">
<UButton
v-if="prevButton"
:size="size"
:disabled="!canGoPrev"
:disabled="!canGoFirstOrPrev"
:class="[ui.base, ui.rounded]"
v-bind="{ ...ui.default.prevButton, ...prevButton }"
:ui="{ rounded: '' }"
Expand All @@ -28,14 +41,27 @@
<UButton
v-if="nextButton"
:size="size"
:disabled="!canGoNext"
:disabled="!canGoLastOrNext"
:class="[ui.base, ui.rounded]"
v-bind="{ ...ui.default.nextButton, ...nextButton }"
:ui="{ rounded: '' }"
aria-label="Next"
@click="onClickNext"
/>
</slot>

<slot name="last" :on-click="onClickLast">
<UButton
v-if="lastButton && showLast"
:size="size"
:disabled="!canGoLastOrNext"
:class="[ui.base, ui.rounded]"
v-bind="{ ...ui.default.lastButton, ...lastButton }"
:ui="{ rounded: '' }"
aria-label="Last"
@click="onClickLast"
/>
</slot>
</div>
</template>

Expand Down Expand Up @@ -94,6 +120,22 @@ export default defineComponent({
type: Object as PropType<Button>,
default: () => config.default.inactiveButton as Button
},
showFirst: {
type: Boolean,
default: false
},
showLast: {
type: Boolean,
default: false
},
firstButton: {
type: Object as PropType<Button>,
default: () => config.default.firstButton as Button
},
lastButton: {
type: Object as PropType<Button>,
default: () => config.default.lastButton as Button
},
prevButton: {
type: Object as PropType<Button>,
default: () => config.default.prevButton as Button
Expand Down Expand Up @@ -192,8 +234,24 @@ export default defineComponent({
return items
})
const canGoPrev = computed(() => currentPage.value > 1)
const canGoNext = computed(() => currentPage.value < pages.value.length)
const canGoFirstOrPrev = computed(() => currentPage.value > 1)
const canGoLastOrNext = computed(() => currentPage.value < pages.value.length)
function onClickFirst () {
if (!canGoFirstOrPrev.value) {
return
}
currentPage.value = 1
}
function onClickLast () {
if (!canGoLastOrNext.value) {
return
}
currentPage.value = pages.value.length
}
function onClickPage (page: number | string) {
if (typeof page === 'string') {
Expand All @@ -204,15 +262,15 @@ export default defineComponent({
}
function onClickPrev () {
if (!canGoPrev.value) {
if (!canGoFirstOrPrev.value) {
return
}
currentPage.value--
}
function onClickNext () {
if (!canGoNext.value) {
if (!canGoLastOrNext.value) {
return
}
Expand All @@ -226,11 +284,13 @@ export default defineComponent({
currentPage,
pages,
displayedPages,
canGoPrev,
canGoNext,
canGoLastOrNext,
canGoFirstOrPrev,
onClickPrev,
onClickNext,
onClickPage
onClickPage,
onClickFirst,
onClickLast
}
}
})
Expand Down
10 changes: 10 additions & 0 deletions src/runtime/ui.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,16 @@ export const pagination = {
inactiveButton: {
color: 'white'
},
firstButton: {
color: 'white',
class: 'rtl:[&_span:first-child]:rotate-180',
icon: 'i-heroicons-chevron-double-left-20-solid'
},
lastButton: {
color: 'white',
class: 'rtl:[&_span:last-child]:rotate-180',
icon: 'i-heroicons-chevron-double-right-20-solid'
},
prevButton: {
color: 'white',
class: 'rtl:[&_span:first-child]:rotate-180',
Expand Down

1 comment on commit c5ce997

@vercel
Copy link

@vercel vercel bot commented on c5ce997 Oct 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ui – ./

ui-git-dev-nuxt-js.vercel.app
ui.nuxt.com
ui-nuxt-js.vercel.app

Please sign in to comment.