diff --git a/docs/frontend.md b/docs/frontend.md index 5482bb4..b242a93 100644 --- a/docs/frontend.md +++ b/docs/frontend.md @@ -155,8 +155,17 @@ layout shift results. prefix and date formatting. - `app/components/SocialIcon.vue` — inlines SVG brand marks from `simple-icons` at build time (`?raw` imports) rather than bundling the whole icon set. -- `app/components/LanguageSwitch.vue` — the header's language-switch link; reads - `useLangSwitchState()` and `useLocale()`, computes the equivalent path in the other language. +- `app/components/LanguageSwitch.vue` — the header's language toggle: both language names are + always shown (`Italiano / English`), the current one as plain non-interactive text + (`aria-current="true"`), the other as a link — reads `useLangSwitchState()` and `useLocale()` to + compute the target path, per the fallback rules in [English content](#english-content). +- `app/components/PaginationNav.vue` — numbered pagination (not just prev/next): first, last, the + current page and its immediate neighbors, collapsing gaps into a single `…` via + `shared/utils/pagination.ts`'s `paginationRange()`. Used by `BlogIndexView`/`CategoryView`. + Renders page links via `NuxtLink`'s `custom`/`v-slot` API rather than letting the component + render its own `` — `RouterLink`'s built-in active-class/`aria-current` detection compares + only the route's `path`, not its query string, so with plain `NuxtLink`s every `?page=N` link + would end up (wrongly) marked as the current page. - `app/components/views/*.vue` (`HomeView`, `BlogIndexView`, `ArticleView`, `CategoryView`) — the actual page markup/logic, parametrized by a `locale` prop; the real `pages/**` and `pages/en/**` files are thin wrappers around these (see [English content](#english-content)). Registered diff --git a/frontend/app/assets/css/main.css b/frontend/app/assets/css/main.css index 5eec6b2..eddde6a 100644 --- a/frontend/app/assets/css/main.css +++ b/frontend/app/assets/css/main.css @@ -94,6 +94,19 @@ h3 { color: var(--color-muted); } +/* Visually hidden but still announced by screen readers. */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + /* Small uppercase label used for categories, dates and section headings. */ .kicker { margin: 0; @@ -223,16 +236,3 @@ h3 { font-size: 0.9em; } -.pagination { - display: flex; - flex-wrap: wrap; - gap: 1rem 2rem; - align-items: center; - justify-content: center; - margin-top: var(--gap-section); - padding-top: 2rem; - border-top: 1px solid var(--color-border); - font-size: 0.85rem; - letter-spacing: 0.06em; - text-transform: uppercase; -} diff --git a/frontend/app/components/LanguageSwitch.vue b/frontend/app/components/LanguageSwitch.vue index 8e0ab73..59d5821 100644 --- a/frontend/app/components/LanguageSwitch.vue +++ b/frontend/app/components/LanguageSwitch.vue @@ -1,37 +1,71 @@ diff --git a/frontend/app/components/PaginationNav.vue b/frontend/app/components/PaginationNav.vue new file mode 100644 index 0000000..2d3fd66 --- /dev/null +++ b/frontend/app/components/PaginationNav.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/frontend/app/components/views/BlogIndexView.vue b/frontend/app/components/views/BlogIndexView.vue index 9a9ace9..d864a30 100644 --- a/frontend/app/components/views/BlogIndexView.vue +++ b/frontend/app/components/views/BlogIndexView.vue @@ -47,21 +47,7 @@ useSeo({ - + diff --git a/frontend/app/components/views/CategoryView.vue b/frontend/app/components/views/CategoryView.vue index e23ba31..bce7165 100644 --- a/frontend/app/components/views/CategoryView.vue +++ b/frontend/app/components/views/CategoryView.vue @@ -55,21 +55,7 @@ useSeo({ - + diff --git a/frontend/app/layouts/default.vue b/frontend/app/layouts/default.vue index 16e9a64..376d663 100644 --- a/frontend/app/layouts/default.vue +++ b/frontend/app/layouts/default.vue @@ -11,16 +11,15 @@ const strings = computed(() => STRINGS[locale.value])