Header, Footer und Navigation mit DOS-Modus (MAIN-10) #5

Merged
rainer merged 1 commit from agent/full-stack-web-engineer/fbcbc5dcccbc into test/access-check-main-1 2026-11-03 18:30:47 +00:00
Owner

Closes MAIN-10. Builds on PR #3 (design system, MAIN-9), which builds on #1 (MAIN-8). Merge order: #1 → #3 → this PR. After that, change the base to the target branch.

What changed

  • Layout (layouts/default.vue): skip link «Zum Inhalt», header, <main id="main">, footer. /design-system keeps its own layout (layout: false).
  • Header (components/site/Header.vue): plain-text navigation (Leistungen, Referenzen, Projekte, Über mich, Kontakt) with the file name as a mono subtitle (maker.bin, clients.dat, projects.dir, about.txt, comm.sys). The file names are hidden from screen readers. The active page has aria-current="page" and an orange underline.
  • Mobile (< 1024 px): menu button with aria-expanded/aria-controls. Escape closes it and returns focus to the button; navigating closes it too. Every target is at least 44 px tall.
  • Footer (components/site/Footer.vue): DOS-style F-key bar (F1 Hilfe → Kontakt, F2–F5 main pages, F9 Datenschutz, F10 Impressum) plus copyright and «Kein Tracking».
  • DOS mode (DosToggle.vue, useDosMode.ts): toggle with aria-pressed that switches to the existing dark palette. Without a choice, the system setting applies. The choice is stored in localStorage (meowww-theme) and applied as data-theme on <html>. An inline script in nuxt.config.ts sets it before first paint, so there is no light flash.
  • Navigation data in one place: utils/navigation.ts.
  • Placeholder pages for every link target (SitePlaceholder, noindex). Prerendering runs with failOnError, so dead links would break the build. MAIN-11 to MAIN-16 replace them.
  • Docs: new section in docs/design-system.md, structure in the README.

Decision: no real F-key hotkeys

The F-keys are only links. Pressing F1–F12 is deliberately not intercepted: the browser needs them (F5 reload, F6 address bar, F7 caret browsing, F11 fullscreen, F12 devtools), and overriding them would hurt keyboard and screen-reader users. Keyboard navigation works through Tab/Enter.

How to test

npm ci && npm run dev
  • Tab from the top: skip link → logo → navigation → DOS toggle. Enter/Space work.
  • DOS mode on → reload → it stays on. Off → it stays off. Without a choice, it follows the OS dark setting.
  • At 360 px and 768 px: menu button, open/close, Escape, choosing a link closes the menu.

Verification

  • npm run lint, npm run typecheck and npm run generate pass locally. All 20 routes prerender without errors.
  • Generated HTML checked: inline theme script in <head>, aria-current, aria-expanded, aria-pressed present, CSS rules for data-theme present, no external URLs.
  • Not checked visually: headless Chromium doesn't start on the build machine (missing system libraries, no root). Please look at it on phone, tablet and desktop, and in DOS mode.

Known limitations

  • Without JavaScript, the mobile menu stays closed (the desktop navigation and footer links still work).
  • The dark token values appear twice in main.css (system setting and data-theme="dos") and must stay in sync. There's a comment next to them.
  • The project has no test framework, so there are no component tests.

🤖 Generated with Claude Code

Closes MAIN-10. Builds on PR #3 (design system, MAIN-9), which builds on #1 (MAIN-8). **Merge order: #1 → #3 → this PR.** After that, change the base to the target branch. ## What changed - **Layout** (`layouts/default.vue`): skip link «Zum Inhalt», header, `<main id="main">`, footer. `/design-system` keeps its own layout (`layout: false`). - **Header** (`components/site/Header.vue`): plain-text navigation (Leistungen, Referenzen, Projekte, Über mich, Kontakt) with the file name as a mono subtitle (`maker.bin`, `clients.dat`, `projects.dir`, `about.txt`, `comm.sys`). The file names are hidden from screen readers. The active page has `aria-current="page"` and an orange underline. - **Mobile** (< 1024 px): menu button with `aria-expanded`/`aria-controls`. Escape closes it and returns focus to the button; navigating closes it too. Every target is at least 44 px tall. - **Footer** (`components/site/Footer.vue`): DOS-style F-key bar (F1 Hilfe → Kontakt, F2–F5 main pages, F9 Datenschutz, F10 Impressum) plus copyright and «Kein Tracking». - **DOS mode** (`DosToggle.vue`, `useDosMode.ts`): toggle with `aria-pressed` that switches to the existing dark palette. Without a choice, the system setting applies. The choice is stored in `localStorage` (`meowww-theme`) and applied as `data-theme` on `<html>`. An inline script in `nuxt.config.ts` sets it before first paint, so there is no light flash. - **Navigation data** in one place: `utils/navigation.ts`. - **Placeholder pages** for every link target (`SitePlaceholder`, `noindex`). Prerendering runs with `failOnError`, so dead links would break the build. MAIN-11 to MAIN-16 replace them. - Docs: new section in `docs/design-system.md`, structure in the README. ## Decision: no real F-key hotkeys The F-keys are only links. Pressing F1–F12 is deliberately not intercepted: the browser needs them (F5 reload, F6 address bar, F7 caret browsing, F11 fullscreen, F12 devtools), and overriding them would hurt keyboard and screen-reader users. Keyboard navigation works through Tab/Enter. ## How to test ```bash npm ci && npm run dev ``` - Tab from the top: skip link → logo → navigation → DOS toggle. Enter/Space work. - DOS mode on → reload → it stays on. Off → it stays off. Without a choice, it follows the OS dark setting. - At 360 px and 768 px: menu button, open/close, Escape, choosing a link closes the menu. ## Verification - `npm run lint`, `npm run typecheck` and `npm run generate` pass locally. All 20 routes prerender without errors. - Generated HTML checked: inline theme script in `<head>`, `aria-current`, `aria-expanded`, `aria-pressed` present, CSS rules for `data-theme` present, no external URLs. - **Not checked visually:** headless Chromium doesn't start on the build machine (missing system libraries, no root). Please look at it on phone, tablet and desktop, and in DOS mode. ## Known limitations - Without JavaScript, the mobile menu stays closed (the desktop navigation and footer links still work). - The dark token values appear twice in `main.css` (system setting and `data-theme="dos"`) and must stay in sync. There's a comment next to them. - The project has no test framework, so there are no component tests. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat: Header, Footer und Navigation mit DOS-Modus (MAIN-10)
Some checks failed
CI / build (pull_request) Waiting to run
CI / build (push) Has been cancelled
b4840cfd3c
- Default-Layout mit Skip-Link, Header, Main und Footer
- Klartext-Navigation mit Dateinamen als Mono-Untertitel, aktive Seite
  mit aria-current, Menü-Button unter lg (aria-expanded, Escape)
- Footer mit F-Tasten-Leiste (Links, keine abgefangenen F-Tasten)
- DOS-Modus-Umschalter (aria-pressed), Wahl in localStorage, ohne Wahl
  gilt prefers-color-scheme; Inline-Skript verhindert hellen Blitz
- Platzhalterseiten für alle Navigationsziele, damit das Prerendering
  keine toten Links findet
- Doku in docs/design-system.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
rainer changed target branch from agent/full-stack-web-engineer/5f28348cf2ed to test/access-check-main-1 2026-11-03 18:30:47 +00:00
rainer merged commit 7238fdda84 into test/access-check-main-1 2026-11-03 18:30:47 +00:00
Author
Owner

Summary

PR #5 ist in test/access-check-main-1 gemergt (7238fdd).

Conflicts resolved

  • layouts/, composables/, utils/, components/site/ und die Platzhalter-Seiten → nach app/ (Nuxt 4).
  • app/pages/kontakt.vue, app/pages/projekte.vue → Die echten Seiten aus MAIN-15/MAIN-14 bleiben, die Platzhalter aus diesem PR wurden verworfen. Das eigene <main id="main"> und den Skip-Link dieser Seiten habe ich entfernt, weil app/layouts/default.vue beides liefert. Sonst gäbe es ein doppeltes id="main" und verschachtelte <main>. Geprüft: Jede vorgerenderte Seite hat genau ein <main>.
  • DOS-Modus-CSS (data-theme) → in die Tailwind-4-app/assets/css/main.css übernommen.
  • README.md, docs/design-system.md, Kommentar in nuxt.config.ts → Pfade auf app/ aktualisiert.

Verification (lokal, nach jeder Auflösung): npm run lint, npm run typecheck, npm test (23/23), npm run build, npm run test:e2e (5/5): alles grün. Forgejo-CI steht seit Tagen auf pending (auch auf dem Default-Branch), es läuft offenbar kein Runner.

## Summary PR #5 ist in `test/access-check-main-1` gemergt (`7238fdd`). ## Conflicts resolved - `layouts/`, `composables/`, `utils/`, `components/site/` und die Platzhalter-Seiten → nach `app/` (Nuxt 4). - `app/pages/kontakt.vue`, `app/pages/projekte.vue` → **Die echten Seiten aus MAIN-15/MAIN-14 bleiben**, die Platzhalter aus diesem PR wurden verworfen. Das eigene `<main id="main">` und den Skip-Link dieser Seiten habe ich entfernt, weil `app/layouts/default.vue` beides liefert. Sonst gäbe es ein doppeltes `id="main"` und verschachtelte `<main>`. Geprüft: Jede vorgerenderte Seite hat genau ein `<main>`. - DOS-Modus-CSS (`data-theme`) → in die Tailwind-4-`app/assets/css/main.css` übernommen. - `README.md`, `docs/design-system.md`, Kommentar in `nuxt.config.ts` → Pfade auf `app/` aktualisiert. **Verification** (lokal, nach jeder Auflösung): `npm run lint`, `npm run typecheck`, `npm test` (23/23), `npm run build`, `npm run test:e2e` (5/5): alles grün. Forgejo-CI steht seit Tagen auf *pending* (auch auf dem Default-Branch), es läuft offenbar kein Runner.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rainer/test!5
No description provided.