Add numbered pagination and redesign the IT/EN language switch
Blog and category archives now show a numbered page list (first, last, current +/-1, collapsing gaps into an ellipsis) instead of only previous/next — see shared/utils/pagination.ts's paginationRange(). Renders page links via NuxtLink's custom/v-slot API rather than letting it render its own <a>: RouterLink's built-in active-class/aria-current detection compares only the route's path, not its query string, so every ?page=N link was incorrectly marked as the current page. The language switch now shows both "Italiano / English" at all times, with the current one as plain non-interactive text and the other as a link, moved to the header's top-right corner instead of stacked under the logo.
This commit is contained in:
@@ -20,7 +20,11 @@ export const STRINGS = {
|
||||
footerFollowAriaLabel: 'Seguici',
|
||||
contactLabel: 'Contatti:',
|
||||
copyright: 'Tutti i diritti riservati.',
|
||||
langSwitchLabel: 'English',
|
||||
langSwitch: {
|
||||
ariaLabel: 'Lingua del sito',
|
||||
it: 'Italiano',
|
||||
en: 'English',
|
||||
},
|
||||
home: {
|
||||
heading: "La fine dell'Unione Europea per come l'abbiamo conosciuta.",
|
||||
img1Alt: 'Manifesti e scritte contro le banche durante una crisi bancaria',
|
||||
@@ -43,6 +47,7 @@ export const STRINGS = {
|
||||
prevPage: 'Pagina precedente',
|
||||
nextPage: 'Pagina successiva',
|
||||
pageOf: 'Pagina {current} di {total}',
|
||||
goToPage: 'Vai a pagina {page}',
|
||||
paginationAriaLabel: 'Paginazione',
|
||||
},
|
||||
category: {
|
||||
@@ -71,7 +76,11 @@ export const STRINGS = {
|
||||
footerFollowAriaLabel: 'Follow us',
|
||||
contactLabel: 'Contact:',
|
||||
copyright: 'All rights reserved.',
|
||||
langSwitchLabel: 'Italiano',
|
||||
langSwitch: {
|
||||
ariaLabel: 'Site language',
|
||||
it: 'Italiano',
|
||||
en: 'English',
|
||||
},
|
||||
home: {
|
||||
heading: "The end of the European Union as we've known it.",
|
||||
img1Alt: 'Banners and graffiti against banks during a banking crisis',
|
||||
@@ -94,6 +103,7 @@ export const STRINGS = {
|
||||
prevPage: 'Previous page',
|
||||
nextPage: 'Next page',
|
||||
pageOf: 'Page {current} of {total}',
|
||||
goToPage: 'Go to page {page}',
|
||||
paginationAriaLabel: 'Pagination',
|
||||
},
|
||||
category: {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
export type PaginationItem = number | 'ellipsis'
|
||||
|
||||
function range(start: number, end: number): number[] {
|
||||
const length = end - start + 1
|
||||
return Array.from({ length }, (_, i) => start + i)
|
||||
}
|
||||
|
||||
/**
|
||||
* Windowed page list for numbered pagination: always shows the first and
|
||||
* last page, the current page and its immediate siblings, collapsing any
|
||||
* gap into a single 'ellipsis' marker. Returns every page when the total
|
||||
* is small enough that no collapsing is needed.
|
||||
*/
|
||||
export function paginationRange(current: number, total: number, siblingCount = 1): PaginationItem[] {
|
||||
if (total <= 0) return []
|
||||
|
||||
const totalVisible = siblingCount * 2 + 5 // first + last + current + 2 siblings + 2 ellipses
|
||||
if (totalVisible >= total) return range(1, total)
|
||||
|
||||
const leftSibling = Math.max(current - siblingCount, 1)
|
||||
const rightSibling = Math.min(current + siblingCount, total)
|
||||
|
||||
const showLeftEllipsis = leftSibling > 2
|
||||
const showRightEllipsis = rightSibling < total - 1
|
||||
|
||||
if (!showLeftEllipsis && showRightEllipsis) {
|
||||
const leftRange = range(1, 3 + siblingCount * 2)
|
||||
return [...leftRange, 'ellipsis', total]
|
||||
}
|
||||
|
||||
if (showLeftEllipsis && !showRightEllipsis) {
|
||||
const rightRange = range(total - (3 + siblingCount * 2) + 1, total)
|
||||
return [1, 'ellipsis', ...rightRange]
|
||||
}
|
||||
|
||||
return [1, 'ellipsis', ...range(leftSibling, rightSibling), 'ellipsis', total]
|
||||
}
|
||||
Reference in New Issue
Block a user