From 93ac4d275d8d836749d33fb013c15f5a4b7382ff Mon Sep 17 00:00:00 2001 From: Ralksta <16941050+ralksta@users.noreply.github.com> Date: Sun, 31 May 2026 10:04:49 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Add=20skip-to-content?= =?UTF-8?q?=20link=20for=20keyboard=20accessibility=20(#169)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What: Added a "Skip to content" link that is visually hidden by default but appears when focused via keyboard. Pointed it to the main content area using `id="main-content"` and `tabIndex={-1}`. 🎯 Why: Keyboard users and screen readers must otherwise tab through the entire navigation menu on every page load before reaching the actual page content. This is tedious and a poor UX. 📸 Before/After: Before, keyboard focus started on "Home" in the header. After, the first tab press shows the "Skip to content" link at the top left of the screen. ♿ Accessibility: Massively improves WCAG compliance (Bypass Blocks) and keyboard navigation efficiency. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: ralksta --- .Jules/palette.md | 4 ++++ app/globals.css | 21 +++++++++++++++++++++ app/layout.tsx | 7 ++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/.Jules/palette.md b/.Jules/palette.md index 8321d34..63893f1 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -10,6 +10,10 @@ **Learning:** When building interactive card components that contain multiple pieces of text or badges (like titles and photo counts), screen readers may announce them in a fragmented or confusing way. **Action:** Always apply a comprehensive `aria-label` to the parent link/container that encompasses all meaningful visual data (e.g., titles and item counts). Use `aria-hidden="true"` on redundant text or visual child elements, and set `alt=""` on decorative images to consolidate screen reader announcements into a single, accurate interaction point. +## 2025-05-07 - Skip-to-Content Navigation +**Learning:** Keyboard users and screen readers need a way to bypass repetitive header navigation links. Without a visually hidden skip link that becomes visible on focus, these users must tab through every nav item before reaching the main content on every page load. +**Action:** Always include a "Skip to content" link as the first focusable element in the DOM, anchored to the main content container. Ensure the main container has `tabIndex={-1}` so it can programmatically receive focus without interrupting normal tab flow. + ## 2024-06-18 - Dynamic Numeric Counters ARIA **Learning:** When displaying dynamic numeric text changes during navigation (like a lightbox image counter), the visual presentation (e.g., "1 / 5") does not provide sufficient context for screen reader users and might not be announced automatically. **Action:** Wrap the counter container with `aria-live="polite"` and `aria-atomic="true"`. Use `.sr-only` to provide a context-rich screen reader string (e.g., "Photo 1 of 5") and hide the visual short-hand using `aria-hidden="true"`. diff --git a/app/globals.css b/app/globals.css index 67b610c..65af6fe 100644 --- a/app/globals.css +++ b/app/globals.css @@ -7,6 +7,27 @@ @import url('./tokens.css'); +/* ── Skip to content link ─────────────────────────── */ +.skip-link { + position: absolute; + top: -40px; + left: 0; + background: var(--bg-card); + color: var(--text-primary); + padding: 8px 16px; + z-index: 1000; + transition: top 0.2s ease; + border-bottom-right-radius: var(--radius-sm); + font-family: var(--font-sans); + font-weight: 500; + font-size: 0.85rem; +} + +.skip-link:focus { + top: 0; + outline: 2px solid var(--text-primary); +} + /* ── Header / Navigation ──────────────────────────── */ .header { position: fixed; diff --git a/app/layout.tsx b/app/layout.tsx index 15362eb..c6ef554 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -90,6 +90,9 @@ export default function RootLayout({ children }: { children: React.ReactNode }) + + Skip to content +
-
{children}
+
+ {children} +