From d97f2cee35a36a4a4232dd7775c6609200c3179d Mon Sep 17 00:00:00 2001 From: "nicolas T." Date: Fri, 20 Mar 2026 14:37:41 +0100 Subject: [PATCH 1/7] feat(templates): add i18n skip-nav partial and translate skip link (story 3.8) - Create templates/partials/skip-nav.html with i18n trans() skip link - Update base.html to include skip-nav partial - Add skip_to_main translation keys to zola.toml (EN + FR) - Update compare.html skip link text via existing lang-detection JS Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../3-8-provide-skip-navigation-links.md | 148 ++++++++++++++++++ static/compare.html | 4 + templates/base.html | 2 +- templates/partials/skip-nav.html | 1 + zola.toml | 2 + 5 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 _bmad-output/implementation-artifacts/3-8-provide-skip-navigation-links.md create mode 100644 templates/partials/skip-nav.html diff --git a/_bmad-output/implementation-artifacts/3-8-provide-skip-navigation-links.md b/_bmad-output/implementation-artifacts/3-8-provide-skip-navigation-links.md new file mode 100644 index 0000000..066eafa --- /dev/null +++ b/_bmad-output/implementation-artifacts/3-8-provide-skip-navigation-links.md @@ -0,0 +1,148 @@ +# Story 3.8: Provide Skip Navigation Links + +Status: review + +## Story + +As a **keyboard user or screen reader user**, +I want to skip over repetitive navigation links, +So that I can quickly reach the main content on each page. + +## Acceptance Criteria + +1. **Skip link visibility**: Skip link appears at the top of the page when focused (Tab pressed on page load) +2. **Skip link target**: Clicking/activating the skip link jumps focus to the main content area (`#main-content`) +3. **Not hidden by default**: Skip link is visible when focused — not permanently hidden +4. **Every page**: Skip link works on every page (all Zola templates + `compare.html`) +5. **Keyboard accessible**: Skip link is the first focusable element in `` and is reachable via Tab +6. **i18n**: Skip link text is translated in both languages (EN: "Skip to main content" / FR: "Passer au contenu principal") +7. **Partial used**: A `partials/skip-nav.html` partial exists and is included via `base.html` (per project-context.md rule) + +## Tasks / Subtasks + +- [ ] Task 1 — Create `templates/partials/skip-nav.html` and update `base.html` to use it (AC: #5, #6, #7) + - [ ] 1.1 Create the `templates/partials/` directory if it does not exist + - [ ] 1.2 Create `templates/partials/skip-nav.html` containing the skip link using the `trans()` i18n function: `` + - [ ] 1.3 In `templates/base.html` line 38: replace the hardcoded `` with `{% include "partials/skip-nav.html" %}` + +- [ ] Task 2 — Add `skip_to_main` i18n key to `zola.toml` (AC: #6) + - [ ] 2.1 Add `skip_to_main = "Skip to main content"` to `[languages.en.translations]` in `zola.toml` + - [ ] 2.2 Add `skip_to_main = "Passer au contenu principal"` to `[languages.fr.translations]` in `zola.toml` + +- [ ] Task 3 — Verify all page templates inherit the skip link via `base.html` (AC: #4) + - [ ] 3.1 Confirm `index.html`, `section.html`, `page.html`, `taxonomy_list.html`, `taxonomy_single.html`, and `404.html` all begin with `{% extends "base.html" %}` — no standalone template missing it + - [ ] 3.2 Confirm `
` exists in `base.html` (the skip link target) + +- [ ] Task 4 — Validate `compare.html` skip link (AC: #4, #5) + - [ ] 4.1 Confirm `` is present and is the first focusable element in `` of `static/compare.html` (added in story 3-5) + - [ ] 4.2 Confirm `
` exists in `compare.html` as the skip target + - [ ] 4.3 Since `compare.html` is a standalone static file (not a Zola template), it cannot use `trans()` — add a small inline JS snippet to update the skip link text based on `localStorage.getItem('cloudlandscape_lang')` matching the existing lang-detection script pattern already used in that file + +- [ ] Task 5 — Run verification checks (AC: all) + - [ ] 5.1 Run `mise run build` — must complete with 0 errors + - [ ] 5.2 Run `mise run check` (zola check) — must validate all links with 0 errors + - [ ] 5.3 Run `mise run a11y` (axe-core) — must report 0 violations on all tested pages + +## Dev Notes + +### Current State — What Already Works ✅ + +- **Skip link in `base.html`**: `` at line 38 — first child of `` ✅ +- **Skip link CSS**: `.skip-link { position: absolute; top: -40px; ... }` and `.skip-link:focus { top: 0; }` fully defined in `static/style.css` (~lines 879–896) ✅ +- **Skip target**: `
` at line 65 of `base.html` ✅ +- **`compare.html` skip link**: `` at line 106 — added in story 3-5 ✅ +- **`compare.html` skip target**: `
` at line 112 of `compare.html` ✅ +- **All page templates extend `base.html`**: `index.html`, `section.html`, `page.html`, `taxonomy_list.html`, `taxonomy_single.html`, `404.html` all begin with `{% extends "base.html" %}` — skip link is inherited site-wide ✅ +- **i18n infrastructure**: `trans(key="...", lang=lang)` pattern already used throughout `base.html` (e.g., `lang_nav_label`, `footer_copyright`) ✅ + +### Gaps to Fix 🔧 + +1. **`templates/partials/` directory does not exist** — project-context.md rule states "Every page template must include `partials/skip-nav.html`". The partial directory and file must be created, and `base.html` updated to use `{% include "partials/skip-nav.html" %}`. + +2. **Skip link text is hardcoded English** — `base.html` line 38 has `"Skip to main content"` as a literal string. It must use `{{ trans(key="skip_to_main", lang=lang) }}` so it renders in the correct language per page. + +3. **`skip_to_main` i18n key is missing from `zola.toml`** — Neither `[languages.en.translations]` nor `[languages.fr.translations]` contain this key. Both must be added before the partial can use `trans()`. + +4. **`compare.html` skip link text is hardcoded English** — Since `compare.html` is a standalone static file in `static/` (not processed by Zola Tera), it cannot use `trans()`. The text should be updated dynamically via JavaScript using the same `cloudlandscape_lang` localStorage key already used in that file for the `lang` attribute. + +### Key File Locations + +- `templates/base.html` — global layout; skip link at line 38; replace with `{% include "partials/skip-nav.html" %}` +- `templates/partials/skip-nav.html` — **new file** to create; contains the i18n skip link +- `zola.toml` — add `skip_to_main` key to both `[languages.en.translations]` (line ~26) and `[languages.fr.translations]` (~line 82) +- `static/compare.html` — standalone static HTML; skip link at line 106; update text via JS + +### Implementation Guidance + +**`templates/partials/skip-nav.html`** (new file): +```html + +``` + +**`templates/base.html` line 38** — replace: +```html +{# Before #} + + +{# After #} +{% include "partials/skip-nav.html" %} +``` + +**`zola.toml`** — add to `[languages.en.translations]`: +```toml +skip_to_main = "Skip to main content" +``` +Add to `[languages.fr.translations]`: +```toml +skip_to_main = "Passer au contenu principal" +``` + +**`static/compare.html`** — update skip link text with JS (add immediately after the existing lang-detection ` diff --git a/templates/base.html b/templates/base.html index 49f41c6..a9d688d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -35,7 +35,7 @@ - + {% include "partials/skip-nav.html" %}