Skip to content

Accessibility-ready remediation - #4601

Open
HardeepAsrani wants to merge 21 commits into
developmentfrom
feat/a11y
Open

Accessibility-ready remediation#4601
HardeepAsrani wants to merge 21 commits into
developmentfrom
feat/a11y

Conversation

@HardeepAsrani

Copy link
Copy Markdown
Member

Summary

Remediation of every finding from the WordPress.org accessibility-ready review (Trac #285870, tracked in Codeinwp/neve-pro-addon#3240), plus a self-audit against the current theme accessibility guidelines. All 18 guidelines are covered; the work is verified by a new dedicated e2e suite (65 tests, wired into the existing Playwright CI matrix) and by manual keyboard + VoiceOver passes.

Navigation & disclosure

  • Desktop submenu toggles are real <button> elements with aria-expanded, unique accessible names ("{item} submenu"), and aria-controls pointing at id-stamped submenu <ul>s; Enter/Space/Escape all work, Escape returns focus to the toggle.
  • Hover-opened submenus are now Escape-dismissable without moving the pointer (WCAG 1.4.13).
  • Mega menu and header search close correctly from the keyboard; the shared focus trap gained a per-trap onClose and reliable teardown (a stale trap used to swallow Tab).

Focus & contrast

  • Visible focus indicators restored everywhere (outline: none removals fixed; default ring or ≥2px outline).
  • Default palette tuned for contrast (secondary accent, nv-c-1/nv-c-2, form borders, placeholders, button hovers) — same hues, darkened to pass; sites with customized colors are untouched.
  • Links in prose are underlined (content, comments, footer, WooCommerce breadcrumbs); hover changes more than color; pagination links have "Page N" accessible names.

Structure, landmarks, forms

  • Unique landmark names per nav instance and device; no nav-in-nav; guaranteed single H1 on every page type (SR-only fallback when titles are hidden); navigation-widgets html5 support.
  • Visible, associated labels on 404/no-results search forms; decorative SVGs aria-hidden; search trigger/palette switch/hamburger are proper buttons with synced state; 24px minimum targets (carets, palette switch).
  • Bundled block patterns: real alt text, corrected heading structure (no pattern H1s), unique CTA texts, valid hrefs.

Motion & context

  • prefers-reduced-motion honored (scroll-to-top, sidebar/overlay transitions, Woo filter sidebar); "(opens in a new tab)" screen-reader text on new-tab links; off-canvas cart falls back to the dropdown mini-cart when the pro booster can't run, and focus alone never opens it.
  • .screen-reader-text upgraded to the core clip pattern with a :focus reveal, documented in the new accessibility.txt (all 7 sections per the wpaccessibility.org standard).
  • Metadata trued up: Tested up to 7.1, tag lists reconciled between style.css and readme.txt.

Testing infrastructure

  • New e2e-tests/specs/a11y-ready/ suite (65 tests) behind playwright.a11y.config.ts with its own a11y-ready fixture env (bin/envs/a11y-ready/fixtures.sh), including axe-core WCAG A/AA scans on 7 page types. Already added to the playwright.yml matrix, so it gates CI from the first merged commit. Size budgets updated: frontend.js 9.75 KB, style-main-new.min.css 40.5 KB.

How this was tested

Every finding went through four independent passes, both before the fix (to reproduce the broken state) and after it (to confirm the remediation):

  1. Source-level audit — Claude reviewed the relevant code paths against the reviewer's findings and the wpaccessibility.org guidelines.
  2. Live browser verification — every fix exercised on a local dev site (keyboard walks, hover/focus states, reduced-motion emulation), including a full VoiceOver screen-reader session driven through VoiceOver's AppleScript API with verbatim announcements logged.
  3. Automated e2e — the new Playwright a11y suite (65 tests + axe-core WCAG A/AA scans) runs in the GitHub Actions matrix and gates every future commit.
  4. Manual QA by @HardeepAsrani — each finding reproduced by hand pre-fix and re-tested post-fix before it was considered done.

Finally, the branch was compared page-by-page and component-by-component (paired screenshots, desktop + mobile) against a pre-remediation development install to confirm no unintended visual regressions.

Will affect visual aspect of the product

YES — intentional, minimal: slightly darker default accent/palette colors and form borders (contrast), underlined prose links, visible focus rings, 24px caret/palette-switch targets. Sites with customized colors keep their saved values.

Test instructions

  • QA reference: test against the reviewer's findings spreadsheet from Trac #285870 and the full accessibility-ready theme guidelines — not just the changes in this PR; anything the guidelines require that we missed is in scope for this review.
  • Keyboard-only walk: Tab from the address bar — skip link first, every control reachable and operable with Enter/Space, Escape closes submenus/search/sidebar and returns focus.
  • Enable "Reduce motion" in OS settings — no sliding/smooth-scroll animations remain.
  • With a screen reader: unique nav landmark names, "{item} submenu" toggles announcing expanded state, "(opens in a new tab)" suffixes, exactly one H1 per page.

Check before Pull Request is ready:

  • I have written a test and included it in this PR
  • I have run all tests and they pass
  • The code passes when running the PHP CodeSniffer
  • Code meets WordPress Coding Standards for PHP, HTML, CSS and JS
  • Security and Sanitization requirements have been followed
  • I have assigned a reviewer or two to review this PR

Closes #4557.
Part of Codeinwp/neve-pro-addon#3240 (Trac #285870).

🤖 Generated with Claude Code

HardeepAsrani and others added 20 commits August 19, 2026 13:11
60 tests in 8 spec files encoding the accessibility-ready acceptance
criteria (see neve-pro-addon a11y.md / Trac #285870):

- submenu keyboard/ARIA behavior incl. screen-reader activation path
- focus visibility, tab order, stray tabindex
- structure: single H1, duplicate IDs, landmark naming
- form labels, link underline/hover/ambiguity
- block pattern source lint + rendered checks
- axe-core WCAG A/AA sweep over the reviewer's page types
- skip link, prefers-reduced-motion, new-window warnings

Own config (playwright.a11y.config.ts) running logged-out with no auth
dependency; fixtures provisioned by bin/envs/a11y-ready (idempotent,
reusable locally via WP-CLI); wired into the playwright.yml CI matrix
as the a11y-ready env/spec pair, run via yarn test:a11y. Adds
@axe-core/playwright dev dependency.

Most tests fail against the unfixed theme by design (baseline
42 failed / 18 passed) — they describe the required end state and
become the permanent regression gate once remediation lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the div[role=button] submenu toggles with native buttons that
expose aria-expanded, unique labels, and a single click-driven open
state — covering mouse, Enter, Space, and screen-reader activation
with one code path. Add Escape-to-close with focus return, and close
desktop submenus when focus leaves the item.

Remove the Enter-only inline script, aria-pressed handling, and the
.wrap.active CSS; fix the @extend cascade bug that kept .dropdown-open
submenus invisible on desktop; replace the dead li:focus mega-menu
selector with :focus-within.

Move Nav_Walker's static inline CSS into the compiled stylesheet,
which obsoletes Secondary_Nav_Walker's proxy hook (b757ea2).

Raise the frontend.js size budget to 9 KB (baseline was already at
~8.04 KB; the ARIA/keyboard logic adds ~0.75 KB).

Refs Trac #285870; closes #4539, keyboard part of #4425.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove every outline suppression (inputs, nav search item, hamburger,
select2) so the browser-default focus ring shows on all interactive
elements, and scope the .caret transition to transform/color — the bare
shorthand meant 'all' and animated the focus ring in from zero width.
Add tabindex="-1" to #content so the skip link genuinely moves focus.

e2e: the focus-indicator helper now enforces the review's bar (default
ring or >=2px outline; box-shadow glows no longer count) and a new sweep
test Tabs through every interactive element on three fixture pages.

Refs Trac #285870; focus-visibility part of #4425.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Palette: distinct darker/lighter hover accent (nv-secondary-accent was
identical to the primary, so hover states changed nothing); nv-c-1/nv-c-2
deepened past their borderline 4.51:1; dark-mode equivalents fixed too.
Forms: border #dddddd -> #8c8c8c (>=3:1 on both backgrounds), placeholder
opacity 0.5 -> 0.7 (>=4.5:1), search submit label no longer uses the
border color as text color. Buttons: hover defaults now differ from rest
(fill darkens, outline fills with the light background); the global
a:hover accent no longer clobbers button-like links' text color (it put
a dark accent on core's dark button background).
Links: underline drops on hover as the non-color cue; classed prose links
are underlined too. Pagination: hover/focus style, screen-reader 'Page N'
names, labelled nav wrapper. Nav carets: 24px minimum touch target
(WCAG 2.5.8). Adds an a11y-w3-showcase fixture page for visual review.

All 7 axe scans and the whole links spec now pass (suite 24 failed /
37 passed, zero regressions).

Refs Trac #285870.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Buttons get href attributes (keyboard reachable); every pattern image
gets alt text — the text-as-image transcribed, team portraits named,
standalone photos described, gallery thumbs generic; the two pattern
H1s become H2s; headings added where the review asked (team members,
gallery grid) and first-heading H3s promoted so patterns start at H2;
the three identical LEARN MORE links get distinct names. Also removes
a duplicate three-columns-images-text registration in patterns.php.

Refs Trac #285870.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Featured images on the archive posts and a footer-menu component on both
desktop and mobile builder rows — without these, the thumbnail-link tests
and the duplicate-id/footer-landmark tests passed vacuously (nothing
rendered to check). Suite baseline moves 10 -> 14 failed, all W5/W6 scope.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ready

Headings: 404 gets an H1; hidden page/archive titles render as a
screen-reader-only H1 instead of disappearing. Forms: search input gets
an associated label (visible on the 404/no-results forms), decorative
search/close SVGs are aria-hidden. Landmarks: the header row wrapper is
a div (no nav-in-nav), menu landmarks are named per device, footer menu
ids are unique per device (closes #4557), sidebars get unique ids and
labels. Controls: search trigger and palette switch are real buttons
with aria-expanded/aria-pressed state, the hamburger has one naming
source, the logo aria-label no longer overrides a visible title,
thumbnail links lose the title attr and gain the post title as their
name, comment links carry SR-only post context. Keyboard order: excerpt
tabindex removed; scroll-to-top renders after the footer, and its
focus() no longer cancels its own smooth scroll (regression from
tabindex=-1 on #content); palette button inherits color (icon was
white-on-white in light mode).

e2e: scroll-to-top completion regression test; search-form specs scoped
to the content area; fixtures render search/palette/secondary-menu so
their coverage is not vacuous. frontend.js budget 9 -> 9.25 KB.

Refs Trac #285870; closes #4557.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- scroll-to-top jumps instantly when prefers-reduced-motion is set
- HFG Button component appends a screen-reader-only '(opens in a new
  tab)' warning when open-in-new-tab is enabled (reuses existing string)
- a11y fixtures render a new-tab Button so the warning test isn't vacuous

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mega menu reveal no longer uses :focus-within, which kept the panel
painted after its toggle closed it while focus remained on the toggle —
Escape now actually hides the panel. The shared focus trap in
navigation.js gains a per-trap onClose so Escape on the header search
closes the panel instead of the menu sidebar, returns focus to the
trigger button (backFocus was an unfocusable div, dropping focus to
body), and the trap ends on every close path (trigger re-click, close
button, click-away overlay) instead of going stale and swallowing Tab.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…itch target size

The off-canvas cart drawer is now a real modal dialog: the template
renders role=dialog/aria-modal/aria-label, an initial inert attribute,
a real Close button instead of an href=# link, and aria-haspopup +
aria-expanded on the opener (which stays a plain link to the cart page
as the no-JS fallback). The hover/:focus-within mini-cart reveal
excludes the drawer so focusing the cart icon can no longer slide it
open (WCAG 3.2.1). should_load_pro_features() additionally requires
Sparks, mirroring the booster's own should_load(), so a saved
off-canvas mod falls back to the dropdown mini-cart when the feature
cannot actually run instead of leaving a dead drawer with no Customizer
control to undo it.

Mega menu column lists switch to visibility:inherit so links inside a
closed panel are no longer focusable off-screen.

The palette switch toggle gets a 24x24 minimum hit area (WCAG 2.5.8);
it rendered at 16x16 (the icon size) at every viewport.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Primary nav instances from pro (primary-menu_2/_3) rendered identical
landmark labels; the nav template now numbers them the way the
customizer does (Primary Menu 1 (Desktop)) and keeps the ul id unique
when two instances share a row. The unique-toggle-names spec asserts
uniqueness per navigation landmark, since the same menu may legitimately
render in several labelled navs.

Menu dividers (legacy title convention or the pro mega menu's
contentType class) render as aria-hidden empty list items instead of
role=presentation, which axe's list rule rejects as a direct ul child.

The responsive search panel drops its untranslatable aria-label on a
role-less div — the form inside is the real search landmark — with a
regression check in the forms spec.

The dropdown mini cart's cart-dropdown-open reveal moved out of the
mobile media query so the pro booster's auto-expand (and any width) can
open it by class; the base element is display:none, which inline styles
never could override.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The new-tab indicator echo folds into a single wrapped line so the
embedded-php tag sniffs pass without introducing whitespace inside the
button text, and both output branches run through wp_kses_post.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
the_title_attribute()'s array shape only accepts a WP_Post for 'post',
so the thumbnail link's aria-label now builds the same escaped title
via get_the_title() with the resolved post id.

The modern frontend.js bundle grew past the 9.25KB budget with the
accessibility disclosure work; raise it to 9.5KB to match the built
size (9.43KB), same as the earlier 8KB -> 9.25KB bump on this branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Brings in the Theme Check fixes shipped on development (WordPress
spelling, themeisle-sdk 3.3.60, dist-zip excludes for composer
installed.json and the SDK changelog) plus the fixes since the branch
was cut. Conflict resolution: the primary menu id now uses
development's Nav::get_menu_id() (device + row) with this branch's
pro-instance suffix on top, and the footer menu id takes development's
device + row form.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The breadcrumb links were distinguished from the surrounding crumb
text only by the palette link color (1.69:1 on defaults) — axe
link-in-text-block, WCAG 1.4.1. Underline them like content links.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Users who ask the OS for reduced motion now get instant show/hide on
the significant movement: the mobile menu sidebar slide and the page
shift it causes (.wrapper/.tcb/.hfg-ov) and the Woo off-canvas filter
sidebar. Opacity-only fades stay.

.screen-reader-text adopts core's clip pattern (clip-path inset(50%),
word-wrap normal — the legacy left:-10000px variant can force RTL
horizontal scroll) and gains the :focus reveal so plugin skip links on
this class become visible when focused.

Also carries the .nv-hover-off rule that navigation.js (next commit)
drives to make hover-opened submenus Escape-dismissable, covering the
pro submenu animation flavors via !important. Size budgets:
style-main-new 40 -> 40.5 KB, frontend.js 9.5 -> 9.75 KB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Submenus revealed by pure CSS :hover had no dismissal mechanism —
content that obscures the page must be dismissable without moving the
pointer. Escape now sets body.nv-hover-off (the stylesheet hides
li:hover > .sub-menu under it, keyboard-opened .dropdown-open panels
excluded); the pointer leaving the hovered item re-arms hover.

New e2e regression: hover-open -> Escape dismisses with the pointer
parked -> re-hover re-opens. Verified against all three submenu
flavors including the pro slide/fade animations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Classic navigation-type widgets (Pages, Categories, Archives, Nav
Menu…) now render wrapped in labeled nav landmarks instead of bare
lists. Part of the W5 landmarks scope that never landed; block widgets
are unaffected (verified byte-identical output), and the only change
for classic widgets is the nav wrapper — no theme CSS targets it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
accessibility.txt (theme root, ships in the dist zip) documents the
accessibility statement, audit status, testing methodology, the
screen-reader-text class, features, and where to get help or report
issues — the sections the accessibility-ready review requires since
June 2026.

Metadata drift fixed: Tested up to 6.2/6.4 -> 7.1 in style.css and
readme.txt, the plugin-ism 'Stable tag: trunk' removed, tag lists made
identical (block-patterns added to style.css; custom-header and
flexible-header removed everywhere — the theme has no
add_theme_support('custom-header'); featured-image-header stays, the
cover header uses the featured image). readme.md regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The footer copyright component renders its credit links inside a
sentence with no visual distinction from the surrounding text — same
color, same weight, no underline. Links in text must not rely on color
alone, so the copyright component's anchors now carry an explicit
underline. Footer menu links are unaffected (navigation is exempt).

Found during the close-out visual comparison against a pre-remediation
development install; present there too, so this was a pre-existing gap
rather than a regression. Adds a links.spec regression test; suite now
65 tests, style-main-new.min.css at 40.46KB of the 40.5KB budget.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@HardeepAsrani HardeepAsrani changed the title Accessibility-ready remediation (Trac #285870) Accessibility-ready remediation Aug 25, 2026
@HardeepAsrani
HardeepAsrani requested a review from abaicus August 25, 2026 17:49
@pirate-bot

pirate-bot commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Plugin build for fd7437e is ready 🛎️!

@pirate-bot

Copy link
Copy Markdown
Collaborator

🌍 i18n String Review Report

📊 Summary

Category Count
➕ Added 3
➖ Removed 1
🔄 Changed 0
Total 4
➕ Added Strings (3) - Click to expand
String Location Words Suggested Match
%s submenu neve/inc/views/nav_walker... 2 Open Submenu
Page not found neve/inc/views/content_404... 3 No close match
Posts pagination neve/inc/views/pluggable/pa... 2 No close match
Total 7
➖ Removed Strings (1) - Click to expand
String Location
Open Submenu neve/inc/views/nav_walker...

@abaicus abaicus left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HardeepAsrani Looks fine, I couldn't spot much. We can also run a copilot review on the PR and make sure the tests pass before merging.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Introduces a broad accessibility remediation pass aimed at meeting WordPress.org “accessibility-ready” re-review expectations, and adds a dedicated Playwright-based acceptance suite (including axe-core) to prevent regressions.

Changes:

  • Updates theme markup/ARIA for landmarks, navigation toggles, sidebars, search forms, pagination, and headings (unique IDs/names, correct roles/states, visible labels where required).
  • Adds a new “a11y-ready” Playwright acceptance suite (plus fixtures + CI matrix entry) and integrates axe-core scans.
  • Improves accessibility-related styling/behavior (focus visibility, reduced-motion handling, link affordances/hover states, contrast-related defaults).

Reviewed changes

Copilot reviewed 80 out of 83 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
yarn.lock Locks new dev dependency (@axe-core/playwright) and related resolution changes.
package.json Adds @axe-core/playwright and a dedicated test:a11y script; updates bundle size thresholds.
views/sidebar.php Makes sidebar IDs unique per position and adds an aria-label for the complementary landmark.
views/page-header.php Ensures an H1 exists even when titles are visually hidden (screen-reader-only).
style.css Updates “Tested up to” and tags to reflect newer WP version and block-pattern support.
sidebar.php Fixes duplicate sidebar IDs and labels the complementary landmark.
sidebar-shop.php Fixes duplicate sidebar IDs and labels the complementary landmark.
searchform.php Correctly associates <label for> with the search input and supports a visible label mode.
readme.txt Updates tags formatting and bumps “Tested up to” version.
readme.md Updates tags formatting and bumps “Tested up to” version.
inc/views/template_parts.php Removes redundant title attribute and uses aria-label for thumbnail links to avoid double announcements.
inc/views/secondary_nav_walker.php Documents why the constructor intentionally does not call the parent.
inc/views/scroll_to_top.php Moves scroll-to-top button later in DOM order and adjusts button markup.
inc/views/pluggable/pagination.php Adds accessible pagination context (“Page N”) and wraps pagination in a labeled nav landmark.
inc/views/partials/post_meta.php Disambiguates comment-count link names with SR-only post context.
inc/views/partials/excerpt.php Removes stray tabindex from non-interactive excerpt wrapper.
inc/views/nav_walker.php Refactors submenu toggles to native buttons with aria-expanded and a single shared open state; improves divider semantics.
inc/views/layouts/layout_sidebar.php Derives a human-readable sidebar label from registered sidebars for aria-label usage.
inc/views/header.php Converts header search trigger/close to buttons and adds aria-expanded handling hooks.
inc/views/content_none.php Requests visible search labels for no-results contexts.
inc/views/content_404.php Adds a visible H1 and requests visible search labels for 404 contexts.
inc/customizer/options/form_fields.php Improves default form border color for contrast.
inc/core/styles/frontend.php Updates default CSS variable for form field border color.
inc/core/front_end.php Enables navigation-widgets HTML5 support.
inc/compatibility/patterns.php Removes a duplicate pattern registration entry.
inc/compatibility/block-patterns/two-columns-image-text.php Adds meaningful alt text, fixes heading markup, and adds href for button-like links.
inc/compatibility/block-patterns/two-columns-centered-content.php Adds meaningful alt text and corrects headings to avoid H1 / improve structure.
inc/compatibility/block-patterns/three-columns-images-texts-content.php Adds meaningful alt text, adjusts heading levels, and fixes href-less links.
inc/compatibility/block-patterns/three-columns-images-text.php Adds meaningful alt text and adjusts headings to avoid invalid H1 usage.
inc/compatibility/block-patterns/testimonials-columns.php Adds descriptive alt text for testimonial avatar images.
inc/compatibility/block-patterns/light-header-left-aligned-content.php Adds meaningful alt text, avoids H1 in pattern content, and fixes href-less links.
inc/compatibility/block-patterns/gallery-title-buttons.php Adds alt text for gallery images and fixes href-less links.
inc/compatibility/block-patterns/gallery-grid-buttons.php Adds a heading for structure, adds alt text, and fixes href-less links.
inc/compatibility/block-patterns/four-columns-team-members.php Adds section heading and descriptive alt text for team member images.
inc/compatibility/block-patterns/dark-header-centered-content.php Avoids H1 in pattern content and fixes href-less links.
header.php Makes the skip-link target focusable via tabindex=-1.
header-footer-grid/templates/row-wrapper-mobile.php Removes redundant aria-label/value to rely on a single naming source for the menu toggle.
header-footer-grid/templates/row-wrapper-main.php Prevents nested navigation landmarks by changing the wrapper from <nav> to <div>.
header-footer-grid/templates/components/component-search-responsive.php Removes stray aria-label on generic div and hides decorative SVG from AT.
header-footer-grid/templates/components/component-palette-switch.php Uses a button element and adds aria-pressed for the palette toggle.
header-footer-grid/templates/components/component-nav.php Ensures repeated navigation landmarks have unique accessible names and unique menu IDs per instance and device.
header-footer-grid/templates/components/component-nav-secondary.php Ensures secondary nav landmark names are unique per device.
header-footer-grid/templates/components/component-nav-footer.php Ensures footer nav landmark names are unique per device.
header-footer-grid/templates/components/component-menu-icon.php Avoids duplicate naming sources and conditionally adds aria-label only when needed.
header-footer-grid/templates/components/component-logo.php Avoids unnecessary aria-label overrides when visible branding text already names the element.
header-footer-grid/templates/components/component-cart-icon.php Improves off-canvas cart semantics (dialog attrs, inert) and converts close control to a button.
header-footer-grid/templates/components/component-button.php Adds SR-only warning text for links that open in a new tab.
header-footer-grid/Core/Components/PaletteSwitch.php Updates CSS for button-based toggle and syncs aria-pressed state via JS.
header-footer-grid/Core/Components/CartIcon.php Avoids rendering pro-only cart markup when required dependency (Sparks) is not present.
globals/utilities.php Makes search icon decorative (aria-hidden), converts trigger to button semantics, and adjusts default palette colors for contrast/hover affordance.
globals/migrations.php Improves default button hover affordances (non-color-only cues and contrast-friendly hover colors).
e2e-tests/specs/a11y-ready/submenu-keyboard.spec.ts Adds desktop/mobile submenu toggle keyboard/state/name tests including NVDA activation path.
e2e-tests/specs/a11y-ready/structure.spec.ts Adds landmark naming/uniqueness, duplicate ID, and heading structure tests.
e2e-tests/specs/a11y-ready/patterns.spec.ts Adds block pattern source lint + rendered checks for href-less links, empty alts, and H1 usage.
e2e-tests/specs/a11y-ready/motion-context-window.spec.ts Adds skip-link focus behavior, reduced-motion scroll-to-top, and new-tab warning/rel checks.
e2e-tests/specs/a11y-ready/links.spec.ts Adds tests for underlines, hover non-color changes, pagination naming, and thumbnail link announcements.
e2e-tests/specs/a11y-ready/forms.spec.ts Adds tests for visible persistent labels and decorative SVG aria-hidden requirements.
e2e-tests/specs/a11y-ready/focus-visibility.spec.ts Adds focus indicator coverage and tab order regression tests.
e2e-tests/specs/a11y-ready/axe.spec.ts Adds automated axe-core WCAG A/AA sweep gate for key page types.
e2e-tests/specs/a11y-ready/a11y-utils.ts Adds shared helpers for permalink resolution, accessible name collection, focus indicator checks, and duplicate ID detection.
e2e-tests/specs/a11y-ready/README.md Documents the acceptance suite intent, fixtures, and how to run locally/CI.
e2e-tests/playwright.a11y.config.ts New Playwright config for the dedicated a11y suite (logged-out, baseURL driven).
bin/envs/a11y-ready/start.sh Adds a CI environment entry to provision the a11y-ready fixtures.
bin/envs/a11y-ready/fixtures.sh Adds deterministic WP-CLI fixtures required by the a11y acceptance suite.
assets/scss/elements/_mega-menu.scss Aligns mega menu open state with .dropdown-open instead of impossible li:focus.
assets/scss/components/main/_typography.scss Improves link hover affordances with non-color cues and avoids breaking button-like links.
assets/scss/components/main/_a11y.scss Updates .screen-reader-text to core-like clip pattern, adds hover-dismiss support, and reduced-motion transitions.
assets/scss/components/hfg/frontend/layout/_footer.scss Ensures footer copyright links are underlined (non-color-only).
assets/scss/components/elements/navigation/_nav-toggle.scss Removes custom focus outline override to rely on UA focus ring.
assets/scss/components/elements/navigation/_nav-search.scss Removes outline suppression and strips UA button styling for search triggers.
assets/scss/components/elements/navigation/_nav-menu.scss Avoids animating focus outline; adds .dropdown-open submenu open state and button caret styling.
assets/scss/components/elements/form-elements/_inputs.scss Stops suppressing outlines; improves placeholder contrast.
assets/scss/components/elements/blog/_pagination.scss Adds visible hover/focus styling for pagination links.
assets/scss/components/elements/_mega-menu.scss Aligns mega menu open state with .dropdown-open and fixes visibility inheritance to avoid tabbable hidden links.
assets/scss/components/elements/_form-elements.scss Supports visible search labels layout and improves search button text contrast.
assets/scss/components/compat/woocommerce/_sidebar.scss Disables sidebar transitions for reduced-motion users.
assets/scss/components/compat/woocommerce/_nav-cart.scss Fixes cart dropdown reveal logic across widths and prevents dialog opening on focus.
assets/scss/components/compat/woocommerce/_checkout.scss Stops suppressing outline on open select2 container.
assets/scss/components/compat/woocommerce/_breadcrumbs.scss Underlines breadcrumb links to avoid color-only distinction.
assets/js/src/scroll-to-top.js Honors prefers-reduced-motion, prevents focus() from canceling smooth scroll, and removes redundant keydown handler.
assets/js/src/frontend/navigation.js Unifies submenu toggle logic around native buttons, aria-expanded, overlay close behavior, Escape handling, and focus trap close hooks.
accessibility.txt Adds an accessibility statement describing targets, testing methodology, and support/issue reporting paths.
.github/workflows/playwright.yml Adds an “a11y-ready” matrix entry and runs the new test:a11y suite in CI.
Suppressed comments (3)

inc/views/scroll_to_top.php:1

  • When AMP is enabled, $amp is a full attribute string (on=\"...\") and escaping it with esc_attr() will turn quotes into &quot;, producing malformed markup (and it’s also concatenated without a leading space). Build a proper attribute fragment that includes a leading space and only escape the attribute value (or output the hardcoded AMP attribute without esc_attr() since it’s not user input).
    globals/utilities.php:1
  • The search button’s aria-label is built with __() inside an HTML attribute; translations can include characters that need attribute-escaping, so this should use esc_attr__() (or wrap with esc_attr()). Also, $amp_state still injects role=\"button\" even when the wrapper is now a native <button>, which is redundant and can trigger ARIA validator/axe noise—consider only adding role=\"button\" when the wrapper is a non-button element.
    globals/utilities.php:1
  • The search button’s aria-label is built with __() inside an HTML attribute; translations can include characters that need attribute-escaping, so this should use esc_attr__() (or wrap with esc_attr()). Also, $amp_state still injects role=\"button\" even when the wrapper is now a native <button>, which is redundant and can trigger ARIA validator/axe noise—consider only adding role=\"button\" when the wrapper is a non-button element.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread assets/scss/components/main/_a11y.scss
The copyright underline shipped against .builder-item--footer_copyright,
a Pro-only component class — the free theme renders the credit as
.builder-item.cr, so the rule and its regression test matched nothing on
CI. Both now cover the free and Pro markup.

Also adds core's legacy clip: rect(1px,1px,1px,1px) fallback to
.screen-reader-text per Copilot review, with the matching clip: auto
reset on :focus so skip links still reveal. CSS budget raised 40.5 →
40.6 KB for the added rules (built size 41508 bytes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants