mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 00:55:25 +00:00
feat: pagination go to button (#7158)
* feat: paginator go to button - Added a way in the paginator to select the page number you want to go to instead of clicking the arrow's. * localization --------- Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
<template v-if="page > 1">
|
||||
<ButtonLink
|
||||
v-if="linkFunction"
|
||||
aria-label="Previous Page"
|
||||
v-tooltip="formatMessage(messages.previousPage)"
|
||||
:aria-label="formatMessage(messages.previousPage)"
|
||||
:href="linkFunction(page - 1)"
|
||||
type="quiet"
|
||||
class="!w-9 !px-0 !rounded-full"
|
||||
@@ -11,7 +12,13 @@
|
||||
>
|
||||
<ChevronLeftIcon aria-hidden="true" />
|
||||
</ButtonLink>
|
||||
<IconButton v-else label="Previous Page" type="quiet" @click="switchPage(page - 1)">
|
||||
<IconButton
|
||||
v-else
|
||||
v-tooltip="formatMessage(messages.previousPage)"
|
||||
:label="formatMessage(messages.previousPage)"
|
||||
type="quiet"
|
||||
@click="switchPage(page - 1)"
|
||||
>
|
||||
<ChevronLeftIcon aria-hidden="true" />
|
||||
</IconButton>
|
||||
</template>
|
||||
@@ -24,9 +31,35 @@
|
||||
}"
|
||||
class="page-number-container"
|
||||
>
|
||||
<div v-if="item === '-'" class="rotate-90 grid place-content-center">
|
||||
<EllipsisVerticalIcon />
|
||||
</div>
|
||||
<form v-if="item === '-'" class="grid place-content-center" @submit.prevent="goToPage">
|
||||
<StyledInput
|
||||
v-if="showPageInput === index"
|
||||
:ref="focusInput"
|
||||
v-model="pageInput"
|
||||
v-tooltip="formatMessage(messages.goToPage)"
|
||||
type="number"
|
||||
:min="1"
|
||||
:max="props.count"
|
||||
placeholder="..."
|
||||
clamp
|
||||
class="w-14"
|
||||
:aria-label="formatMessage(messages.goToPage)"
|
||||
@focusout="showPageInput = undefined"
|
||||
@keydown.escape="showPageInput = undefined"
|
||||
/>
|
||||
|
||||
<div v-else class="rotate-90">
|
||||
<button
|
||||
v-tooltip="formatMessage(messages.goToPage)"
|
||||
type="button"
|
||||
:aria-label="formatMessage(messages.goToPage)"
|
||||
class="grid place-content-center"
|
||||
@click="openPageInput(index)"
|
||||
>
|
||||
<EllipsisVerticalIcon aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<template v-else>
|
||||
<ButtonLink
|
||||
v-if="linkFunction"
|
||||
@@ -57,7 +90,8 @@
|
||||
<template v-if="page !== pages[pages.length - 1]">
|
||||
<ButtonLink
|
||||
v-if="linkFunction"
|
||||
aria-label="Next Page"
|
||||
v-tooltip="formatMessage(messages.nextPage)"
|
||||
:aria-label="formatMessage(messages.nextPage)"
|
||||
:href="linkFunction(page + 1)"
|
||||
type="quiet"
|
||||
class="!w-9 !px-0 !rounded-full"
|
||||
@@ -65,7 +99,13 @@
|
||||
>
|
||||
<ChevronRightIcon aria-hidden="true" />
|
||||
</ButtonLink>
|
||||
<IconButton v-else label="Next Page" type="quiet" @click="switchPage(page + 1)">
|
||||
<IconButton
|
||||
v-else
|
||||
v-tooltip="formatMessage(messages.nextPage)"
|
||||
:label="formatMessage(messages.nextPage)"
|
||||
type="quiet"
|
||||
@click="switchPage(page + 1)"
|
||||
>
|
||||
<ChevronRightIcon aria-hidden="true" />
|
||||
</IconButton>
|
||||
</template>
|
||||
@@ -73,14 +113,19 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ChevronLeftIcon, ChevronRightIcon, EllipsisVerticalIcon } from '@modrinth/assets'
|
||||
import { computed } from 'vue'
|
||||
import { type ComponentPublicInstance, computed, ref } from 'vue'
|
||||
|
||||
import { defineMessages, useVIntl } from '#ui/composables/i18n.ts'
|
||||
|
||||
import { Button, ButtonLink, IconButton } from './buttons'
|
||||
import StyledInput from './StyledInput.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
'switch-page': [page: number]
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
page: number
|
||||
@@ -92,6 +137,8 @@ const props = withDefaults(
|
||||
count: 1,
|
||||
},
|
||||
)
|
||||
const showPageInput = ref<number | undefined>(undefined)
|
||||
const pageInput = ref<number | undefined>(undefined)
|
||||
|
||||
const pages = computed(() => {
|
||||
const pages: ('-' | number)[] = []
|
||||
@@ -129,4 +176,40 @@ const pages = computed(() => {
|
||||
function switchPage(newPage: number) {
|
||||
emit('switch-page', Math.min(Math.max(newPage, 1), props.count))
|
||||
}
|
||||
|
||||
function focusInput(element: Element | ComponentPublicInstance | null) {
|
||||
if (element && 'focus' in element) {
|
||||
const styledInput = element as InstanceType<typeof StyledInput>
|
||||
styledInput.focus()
|
||||
}
|
||||
}
|
||||
|
||||
function openPageInput(index: number) {
|
||||
pageInput.value = undefined
|
||||
showPageInput.value = index
|
||||
}
|
||||
|
||||
function goToPage() {
|
||||
if (pageInput.value !== undefined && pageInput.value >= 1 && pageInput.value <= props.count) {
|
||||
switchPage(pageInput.value)
|
||||
}
|
||||
|
||||
showPageInput.value = undefined
|
||||
pageInput.value = undefined
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
goToPage: {
|
||||
id: 'ui.pagination.go-to-page',
|
||||
defaultMessage: 'Go to page',
|
||||
},
|
||||
previousPage: {
|
||||
id: 'ui.pagination.previous-page',
|
||||
defaultMessage: 'Previous page',
|
||||
},
|
||||
nextPage: {
|
||||
id: 'ui.pagination.next-page',
|
||||
defaultMessage: 'Next page',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -6530,6 +6530,15 @@
|
||||
"ui.confirm-leave-modal.title": {
|
||||
"defaultMessage": "Leave page?"
|
||||
},
|
||||
"ui.pagination.go-to-page": {
|
||||
"defaultMessage": "Go to page"
|
||||
},
|
||||
"ui.pagination.next-page": {
|
||||
"defaultMessage": "Next page"
|
||||
},
|
||||
"ui.pagination.previous-page": {
|
||||
"defaultMessage": "Previous page"
|
||||
},
|
||||
"ui.stacked-admonitions.alert-count": {
|
||||
"defaultMessage": "{count, plural, one {# alert} other {# alerts}}"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user