Rework post page (lead, pager), add skip link, unified focus ring, reduced motion and keyboard-accessible menu #58

Merged
Tom merged 1 commits from design/post-page-a11y into main 2026-10-01 16:50:09 +02:00
Owner

Closes #46 (part of #37).

Post page

  • Title as the only h1, date as a meta line above it, first paragraph as a lead (larger, softer colour)
  • Reading column of ~68ch with line-height 1.75
  • "← Alle Beiträge" as a quiet button instead of an unlabelled <nav>
  • "Vorheriger / Nächster Beitrag" at the end; previous = older post. The order rule lives in the new PostNeighbors record, so it is not index arithmetic in the markup
  • New arrow-left icon (Feather)

Accessibility

  • Skip link "Zum Inhalt springen" as the first Tab stop on every page. It carries the current path (a bare #main would resolve to /#main because of <base href="/">) and data-enhance-nav="false"; otherwise blazor.web.js only scrolls and leaves the focus in the header
  • Unified focus ring: one global :focus-visible rule (accent outline with offset) for links, buttons, summaries, form fields and cards. Duplicate per-component rules removed; white variant (--color-focus-inverse) on header, hero and footer
  • Hamburger menu, still without JavaScript: the checkbox is visually hidden instead of display:none, so Tab reaches it and Space toggles it. It is named "Hauptmenü anzeigen" and points at the menu with aria-controls. Its checked state is announced as open/closed. A closed menu is visibility:hidden, so its links are neither Tab stops nor read out. Escape cannot close it without JS
  • Contrast: all colour pairs checked against WCAG AA in light and dark; results noted in the token block of app.css. Header blue darkened from #328fc6 to #2a77a6 (white text 3.6 → 4.9:1); nav pills are now dark washes
  • Reduced motion: prefers-reduced-motion turns off transitions, animations and smooth scrolling

Tests

  • PostNeighborsTests: middle, newest, oldest, single post, unknown slug, case-insensitive slug
  • RouteSmokeTests: exactly one h1 with the title on the post page; prev/next correct at start and end; skip link with its own path on every page route; menu checkbox named and tied to the menu

6 tests already fail on main (culture data "Mär"/"März" and four HTML expectations in the smoke tests). They are untouched here and tracked separately.

Manual check

Keyboard-only walkthrough of /, /board, /patrons, /posts, one post, /events, /faqs, /downloads at desktop and phone width:

  • the skip link moves the focus into the content
  • every Tab stop has a visible ring
  • no invisible Tab stops
  • the menu opens and closes with Space, and its links are reachable right away
Closes #46 (part of #37). ## Post page - Title as the only `h1`, date as a meta line above it, first paragraph as a lead (larger, softer colour) - Reading column of ~68ch with line-height 1.75 - "← Alle Beiträge" as a quiet button instead of an unlabelled `<nav>` - "Vorheriger / Nächster Beitrag" at the end; previous = older post. The order rule lives in the new `PostNeighbors` record, so it is not index arithmetic in the markup - New `arrow-left` icon (Feather) ## Accessibility - **Skip link** "Zum Inhalt springen" as the first Tab stop on every page. It carries the current path (a bare `#main` would resolve to `/#main` because of `<base href="/">`) and `data-enhance-nav="false"`; otherwise `blazor.web.js` only scrolls and leaves the focus in the header - **Unified focus ring**: one global `:focus-visible` rule (accent outline with offset) for links, buttons, summaries, form fields and cards. Duplicate per-component rules removed; white variant (`--color-focus-inverse`) on header, hero and footer - **Hamburger menu, still without JavaScript**: the checkbox is visually hidden instead of `display:none`, so Tab reaches it and Space toggles it. It is named "Hauptmenü anzeigen" and points at the menu with `aria-controls`. Its checked state is announced as open/closed. A closed menu is `visibility:hidden`, so its links are neither Tab stops nor read out. Escape cannot close it without JS - **Contrast**: all colour pairs checked against WCAG AA in light and dark; results noted in the token block of `app.css`. Header blue darkened from `#328fc6` to `#2a77a6` (white text 3.6 → 4.9:1); nav pills are now dark washes - **Reduced motion**: `prefers-reduced-motion` turns off transitions, animations and smooth scrolling ## Tests - `PostNeighborsTests`: middle, newest, oldest, single post, unknown slug, case-insensitive slug - `RouteSmokeTests`: exactly one `h1` with the title on the post page; prev/next correct at start and end; skip link with its own path on every page route; menu checkbox named and tied to the menu 6 tests already fail on `main` (culture data "Mär"/"März" and four HTML expectations in the smoke tests). They are untouched here and tracked separately. ## Manual check Keyboard-only walkthrough of `/`, `/board`, `/patrons`, `/posts`, one post, `/events`, `/faqs`, `/downloads` at desktop and phone width: - the skip link moves the focus into the content - every Tab stop has a visible ring - no invisible Tab stops - the menu opens and closes with Space, and its links are reachable right away
Tom added 1 commit 2026-10-01 16:50:00 +02:00
Tom merged commit ed6aa5d5ec into main 2026-10-01 16:50:09 +02:00
Tom deleted branch design/post-page-a11y 2026-10-01 16:50:10 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Tom/Elternbeirat#58