🎨 Palette: Add accessible Skip to Content link #53

Closed
ragusa-it wants to merge 1 commits from palette-skip-link-1932083823078854221 into main
ragusa-it commented 2026-02-04 01:37:39 +00:00 (Migrated from github.com)

💡 What: Added a "Skip to content" link that is hidden by default and becomes visible when focused (e.g. via Tab key). It links directly to the main content area.

🎯 Why: This is a critical accessibility requirement (WCAG 2.1 2.4.1) that allows keyboard users to bypass repetitive navigation links and jump straight to the page content.

Accessibility:

  • Added visible-on-focus skip link.
  • Added id="main-content" and tabIndex={-1} to main wrappers for programmatic focus.
  • Updated translations for EN/DE.

PR created automatically by Jules for task 1932083823078854221 started by @ragusa-it

💡 **What**: Added a "Skip to content" link that is hidden by default and becomes visible when focused (e.g. via Tab key). It links directly to the main content area. 🎯 **Why**: This is a critical accessibility requirement (WCAG 2.1 2.4.1) that allows keyboard users to bypass repetitive navigation links and jump straight to the page content. ♿ **Accessibility**: - Added visible-on-focus skip link. - Added `id="main-content"` and `tabIndex={-1}` to main wrappers for programmatic focus. - Updated translations for EN/DE. --- *PR created automatically by Jules for task [1932083823078854221](https://jules.google.com/task/1932083823078854221) started by @ragusa-it*
google-labs-jules[bot] commented 2026-02-04 01:37:41 +00:00 (Migrated from github.com)

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to **Reactive Mode**. When this mode is on, I will only act on comments where you specifically mention me with `@jules`. You can find this option in the **Pull Request** section of your [global Jules UI settings](https://jules.google.com/settings). You can always switch back! New to Jules? Learn more at [jules.google/docs](https://jules.google/docs). --- *_For security, I will only act on instructions from the user who triggered this task._*
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-02-04 01:42:05 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds an accessible “Skip to content” link to allow keyboard users to bypass repetitive navigation and jump directly to the main content area, including i18n strings and basic UI test coverage.

Changes:

  • Introduced a SkipLink UI component (with CSS) and rendered it at the top of App.
  • Added id="main-content" and tabIndex={-1} to page <main> wrappers so the skip link can target them.
  • Added EN/DE translations and a small UI test for the skip link.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/App.tsx Renders SkipLink early in the app layout so it’s first in tab order
src/components/ui/SkipLink.tsx New skip link component using i18n text
src/components/ui/SkipLink.module.css Styling to visually hide the skip link until focused
src/components/ui/index.ts Exposes SkipLink via the UI barrel export
src/components/ui/tests/SkipLink.test.tsx Adds a basic render/link-target test for skip link
src/pages/Home.tsx Makes <main> targetable/focusable via id + tabIndex
src/pages/About.tsx Makes <main> targetable/focusable via id + tabIndex
src/pages/Contact.tsx Makes <main> targetable/focusable via id + tabIndex
src/i18n/en.ts Adds nav.skipToContent translation
src/i18n/de.ts Adds nav.skipToContent translation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview Adds an accessible “Skip to content” link to allow keyboard users to bypass repetitive navigation and jump directly to the main content area, including i18n strings and basic UI test coverage. **Changes:** - Introduced a `SkipLink` UI component (with CSS) and rendered it at the top of `App`. - Added `id="main-content"` and `tabIndex={-1}` to page `<main>` wrappers so the skip link can target them. - Added EN/DE translations and a small UI test for the skip link. ### Reviewed changes Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | src/App.tsx | Renders `SkipLink` early in the app layout so it’s first in tab order | | src/components/ui/SkipLink.tsx | New skip link component using i18n text | | src/components/ui/SkipLink.module.css | Styling to visually hide the skip link until focused | | src/components/ui/index.ts | Exposes `SkipLink` via the UI barrel export | | src/components/ui/__tests__/SkipLink.test.tsx | Adds a basic render/link-target test for skip link | | src/pages/Home.tsx | Makes `<main>` targetable/focusable via `id` + `tabIndex` | | src/pages/About.tsx | Makes `<main>` targetable/focusable via `id` + `tabIndex` | | src/pages/Contact.tsx | Makes `<main>` targetable/focusable via `id` + `tabIndex` | | src/i18n/en.ts | Adds `nav.skipToContent` translation | | src/i18n/de.ts | Adds `nav.skipToContent` translation | </details> --- 💡 <a href="/ragusa-it/ragusaitweb/new/main/.github/instructions?filename=*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@@ -50,0 +50,4 @@
id="main-content"
tabIndex={-1}
style={{ outline: 'none' }}
className={styles.about}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-04 01:42:05 +00:00

The inline style={{ outline: 'none' }} suppresses the global :focus-visible focus indicator (src/styles/global.css:66-70). That makes the skip-link target focus invisible to keyboard users after jumping to content. Remove the inline outline reset or add a dedicated :focus-visible style for #main-content.


The inline `style={{ outline: 'none' }}` suppresses the global `:focus-visible` focus indicator (`src/styles/global.css:66-70`). That makes the skip-link target focus invisible to keyboard users after jumping to content. Remove the inline outline reset or add a dedicated `:focus-visible` style for `#main-content`. ```suggestion ```
@@ -50,1 +53,4 @@
className={styles.about}
key={location.key}
>
{/* Hero Section */}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-04 01:42:05 +00:00

key={location.key} will change when the URL hash updates (e.g., activating the skip link adds #main-content), causing <main> to unmount/remount and potentially drop focus right after the skip link is used. Use a stable key (or remove the key) so hash navigation doesn’t remount the main container.

`key={location.key}` will change when the URL hash updates (e.g., activating the skip link adds `#main-content`), causing `<main>` to unmount/remount and potentially drop focus right after the skip link is used. Use a stable key (or remove the key) so hash navigation doesn’t remount the main container.
@@ -135,3 +135,3 @@
return (
<main className={styles.contact}>
<main id="main-content" tabIndex={-1} style={{ outline: 'none' }} className={styles.contact}>
{/* Hero */}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-04 01:42:04 +00:00

style={{ outline: 'none' }} on the <main> target prevents any visible focus ring when keyboard users activate the skip link. Since the app has a global :focus-visible outline (src/styles/global.css:66-70), consider removing this inline style or providing an explicit :focus-visible style for the main content target instead.

    <main id="main-content" tabIndex={-1} className={styles.contact}>
`style={{ outline: 'none' }}` on the `<main>` target prevents any visible focus ring when keyboard users activate the skip link. Since the app has a global `:focus-visible` outline (`src/styles/global.css:66-70`), consider removing this inline style or providing an explicit `:focus-visible` style for the main content target instead. ```suggestion <main id="main-content" tabIndex={-1} className={styles.contact}> ```
@@ -4,3 +4,3 @@
return (
<main>
<main id="main-content" tabIndex={-1} style={{ outline: 'none' }}>
<Hero />
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-04 01:42:04 +00:00

style={{ outline: 'none' }} removes the global :focus-visible outline (see src/styles/global.css:66-70), so when the skip link moves focus to <main>, there will be no visible focus indicator. Remove the inline outline reset, or replace it with an explicit focus style on the main content container (e.g., CSS #main-content:focus-visible { ... }).

    <main id="main-content" tabIndex={-1}>
`style={{ outline: 'none' }}` removes the global `:focus-visible` outline (see `src/styles/global.css:66-70`), so when the skip link moves focus to `<main>`, there will be no visible focus indicator. Remove the inline outline reset, or replace it with an explicit focus style on the main content container (e.g., CSS `#main-content:focus-visible { ... }`). ```suggestion <main id="main-content" tabIndex={-1}> ```

Pull request closed

Sign in to join this conversation.