A11y/critical fixes#154
Conversation
- Skip-to-content link in the base layout, visible on focus - aria-label="Primary" + aria-current="page" on header nav; dedup home-icon's accessible name - id="main" tabindex="-1" on every page's <main> - Active footer link bumped to AA contrast in dark mode; logo links use aria-label instead of paired sr-only spans - Introduces shared .focus-ring utility Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Always-rendered visually-hidden <h1> on the photo detail page; overlay heading demoted to <h2> - aria-expanded / aria-controls / dynamic aria-label on the info toggle; role="region" on the panel; Escape closes - Disabled prev/next render as inert <a> (was <span>); collapsed the duplicated template into a v-for - Removes duplicate id="icon" on EXIF SVGs; adds missing focal-length sr-only label - Focus ring + focus-dim siblings on gallery thumbnails Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Wraps the live default-browser cell in aria-live="polite" with a dynamic aria-label - Skips no-op SSE writes so the live region only announces real changes - motion-safe: on the connection-pulse animation - role="status" on browser-stats loading, role="alert" on errors - Forces the unovis legend label color to AA contrast in dark mode (the library's body.theme-dark switch isn't wired here) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rkup - .focus-ring on bento cards, HotStuff tiles, and gradient CTAs - :focus-visible companion to the hover-dim sibling effect - aria-hidden on decorative CTA SVGs; redundant alt text removed from Mastodon/GitHub icons - <h4> -> <h3> in MySkills (heading-level skip) - Underline on /uses list links so they aren't bold-only Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Improves site accessibility by adding consistent skip-navigation targets, standardized focus-visible styling, and better ARIA semantics across key UI components.
Changes:
- Adds a global “Skip to content” link and makes page
<main>regions programmatically focusable viaid="main"+tabindex="-1". - Introduces a reusable
.focus-ringutility and applies it broadly to interactive elements to ensure visible keyboard focus. - Enhances assistive-technology support with improved ARIA attributes/roles (e.g.,
aria-current,aria-live,aria-hidden) and heading structure tweaks.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/styles/index.css | Adds shared .focus-ring focus-visible styling utility. |
| src/pages/index.astro | Adds main target, focus styling on links, and improves icon accessibility. |
| src/pages/about.astro | Adds id="main" + tabindex="-1" to support skip link. |
| src/pages/imprint.astro | Adds id="main" + tabindex="-1" to support skip link. |
| src/pages/privacy-policy.astro | Adds id="main" + tabindex="-1" to support skip link. |
| src/pages/reads/index.astro | Adds skip-link target and adjusts heading utility class order. |
| src/pages/reads/[...id].astro | Adds skip-link target on main content. |
| src/pages/uses/index.astro | Adds skip-link target and applies focus-ring/ARIA improvements to CTAs/icons. |
| src/pages/uses/browserstats.astro | Adds skip-link target and minor text reflow. |
| src/pages/grid/index.astro | Adds skip-link target on main content. |
| src/pages/grid/[...id].astro | Adds skip-link target and an SR-only page heading. |
| src/layouts/Basic.astro | Adds “Skip to content” link. |
| src/components/Header.astro | Adds aria-label, aria-current, and focus-visible styling to primary nav. |
| src/components/Footer.astro | Improves link/icon accessibility labels and focus styling. |
| src/components/UsesList.astro | Adds focus-ring/link styling to external links. |
| src/components/MySkills.astro | Adjusts heading level for improved document structure. |
| src/components/LatestSection.astro | Extends dimming behavior to keyboard focus state and applies focus-ring to cards. |
| src/components/HotStuff.astro | Extends dimming behavior to keyboard focus state and applies focus-ring to links. |
| src/components/grid/GridGallery.astro | Applies focus-ring to grid tiles and adds focus-based dimming behavior. |
| src/components/grid/GridImageNavigation.vue | Refactors prev/next buttons into data-driven rendering with improved ARIA. |
| src/components/grid/GridImageInfoOverlay.vue | Adds region semantics, improves headings, removes duplicate SVG ids, adds Escape close. |
| src/components/grid/GridImageInfoButton.vue | Adds ARIA expanded/controls and improves button labeling. |
| src/components/CurrentBrowser.vue | Adds live-region semantics and reduces unnecessary reactive updates. |
| src/components/BrowserStats.vue | Adds role="alert" / role="status" and improves dark-mode legend label styling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| &:has(.moment:focus-visible) { | ||
| .moment:not(:focus-visible) { |
There was a problem hiding this comment.
The :focus-visible selector here will never match .moment because focus lands on the <a> inside the <li>, not the <li> itself. As a result, the intended “dim non-focused tiles when keyboard focusing” behavior won’t work. Use :focus-within on .moment (or :has(a:focus-visible)) and update the corresponding :not(...) selector accordingly.
| &:has(.moment:focus-visible) { | |
| .moment:not(:focus-visible) { | |
| &:has(.moment:focus-within) { | |
| .moment:not(:focus-within) { |
|
|
||
| .hot-stuff:has(:hover) li:not(:hover) { | ||
| .hot-stuff:has(:hover) li:not(:hover), | ||
| .hot-stuff:has(:focus-visible) li:not(:focus-visible) { |
There was a problem hiding this comment.
li:not(:focus-visible) won’t match when the focused element is the <a> inside the <li>, so this rule won’t dim non-focused items during keyboard navigation. Use li:focus-within / li:not(:focus-within) (or a :has(a:focus-visible)-based selector) to reflect descendant focus.
| .hot-stuff:has(:focus-visible) li:not(:focus-visible) { | |
| .hot-stuff:has(:focus-visible) li:not(:focus-within) { |
| rel="noopener noreferrer" | ||
| class="block opacity-75 transition-opacity duration-150 hover:opacity-100" | ||
| class="focus-ring block opacity-75 transition-opacity duration-150 hover:opacity-100 focus-visible:opacity-100" | ||
| ><span class="sr-only">Florian van der Galiën on Github</span><img |
There was a problem hiding this comment.
Brand name typo in the screen-reader-only text: “Github” should be “GitHub”.
| ><span class="sr-only">Florian van der Galiën on Github</span><img | |
| ><span class="sr-only">Florian van der Galiën on GitHub</span><img |
Tab still walks the gallery linearly. Arrow keys add spatial navigation: ArrowLeft/Right move through document order, ArrowUp/Down jump rows column-aware via getBoundingClientRect (adapts to 1/2/3-column responsive breakpoints). Home and End jump to first and last. Modifier+arrow is ignored so browser scroll shortcuts keep working. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The .focus-ring utility renders an outset box-shadow ring, which the gallery's nested overflow-hidden parents (li.moment + a) clip away. An inset shadow on the <a> would be hidden by the absolute-positioned image. Fix by drawing the indicator on a focus-visible::after pseudo overlay with a two-color inset shadow (white inner + slate-900 outer) that stays readable against any photo content. Also fix the dim-siblings selector: .moment:focus-visible never matched because <li> isn't focusable; switch to :has(a:focus-visible). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
No description provided.