Fix WCAG 1.4.3 contrast on white-page admin chrome - #3328
vivi-the-going-merry[bot] wants to merge 4 commits into
Conversation
Admin footer text/links, the review-prompt button, and the active form-nav tab used primary-500/grey-400 on white (~2.6-3.1:1), below AA's 4.5:1. Scope the fix to .frm-white-body (and .frm-review-notice, which is always its own white card) using the existing primary-700/ grey-600 steps -- non-white pages keep their current colors. Refs Strategy11/formidable-pro#6586 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| PHP | Sep 12, 2026 3:13a.m. | Review ↗ | |
| JavaScript | Sep 12, 2026 3:13a.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
.frm-admin-footer-links starts frm_hidden (display: none) until JS un-hides it; axe skips hidden nodes for color-contrast, so the regression test could pass vacuously without this assertion. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Request Changes — the PR's own new regression test is failing in this PR's own CI run (Cypress shard 2), and it's a real bug in the test, not a flake.
Independently verified the actual contrast fix (live in a local Playground instance, PR branch loaded): computed getComputedStyle + WCAG relative-luminance on the two elements that don't require a gated UI state to reach —
| Element | Measured |
|---|---|
Footer text + nav links (.frm-admin-footer-links-text, .frm-admin-footer-links-nav a) |
7.69:1 — exact match to the PR's own table |
Active form-nav tab (.frm_form_nav a.current_page, Build page) |
5.87:1 — exact match |
Review-prompt button (.frm-review-notice .frm-button-primary) |
not exercised — the notice wasn't showing in this environment (gated/dismissed state); source-verified only, same selector+!important-override shape as the other two, no reason to doubt it |
All three clear 4.5:1 as claimed.
The blocking issue is unrelated to color-contrast. See inline comment on the test file.
Also did a repo-wide grep for other color: var(--grey-400)/var(--primary-500) text-color usages on white-page chrome — nothing else matches this PR's specific pattern beyond the one instance the PR body itself already discloses as out-of-scope (see inline note). CI's other checks (PHPCS, PHPStan, Psalm, ESLint, Stylelint, DeepSource, DeepScan) are all green and cover this diff's PHP/JS/CSS.
| it( 'Check the admin footer links meet WCAG color-contrast', () => { | ||
| cy.visit( '/wp-admin/admin.php?page=formidable' ); | ||
| cy.injectAxe(); | ||
| cy.configureAxe( { rules: [ { id: 'color-contrast', enabled: true } ] } ); |
There was a problem hiding this comment.
This test's own axe config skips the file's baselineRules — every other it() block here calls configureAxeWithIgnoredRuleset([...baselineRules, ...]), and baselineRules disables link-name (among others) because the admin footer's four social icons (classes/views/shared/admin-footer-links.php:60-66 — Facebook/Instagram/Twitter/YouTube, each just a bare <span class="dashicons ..."> with no text/aria-label) are a known, already-tracked "links have no discernible text" gap, deliberately suppressed repo-wide so it doesn't fail every other page's a11y check.
This test instead calls cy.configureAxe({ rules: [{ id: 'color-contrast', enabled: true }] }) directly, which only touches color-contrast and leaves every other rule (including link-name) at axe's default (enabled). Confirmed live: this PR's own CI run (Cypress shard 2) fails this exact test with 1 accessibility violation was detected: expected 1 to equal 0 — link-name, serious, 4 nodes, i.e. exactly those four social links. This isn't a color-contrast regression at all; it's a pre-existing, already-suppressed issue resurfacing because the new test built its own rule config from scratch instead of layering onto baselineRules.
Fix: build the rule list from baselineRules with color-contrast flipped to enabled, e.g.:
| cy.configureAxe( { rules: [ { id: 'color-contrast', enabled: true } ] } ); | |
| configureAxeWithIgnoredRuleset( [ | |
| ...baselineRules.filter( rule => rule.id !== 'color-contrast' ), | |
| { id: 'color-contrast', enabled: true } | |
| ] ); |
There was a problem hiding this comment.
Fixed: switched to configureAxeWithIgnoredRuleset(baselineRules with color-contrast flipped on), your suggested diff verbatim. Confirmed red (the exact link-name/4-node failure) with the old config and green (zero violations) with this one, via a live axe run against the real footer page.
| } | ||
|
|
||
| /* primary-500 on white is ~3.07:1, below WCAG AA's 4.5:1 -- primary-700 clears it. */ | ||
| .frm-white-body .frm_form_nav > li a.current_page { |
There was a problem hiding this comment.
This selector is the third of three flagged in the linked issue, and it's applied correctly. The PR body flags a fourth, identical-shape failure as deliberately out of scope: .post-type-frm_display .frm_form_nav .nav-tab-active shares the same ~2.9:1 --primary-500-on-white failure but wasn't named in the original issue.
Non-blocking, but worth a second look before merging: since the fix here is the identical two-line pattern (color/border-color swapped to --primary-700, scoped by selector), and it's already diagnosed with the exact ratio in the PR description, this seems cheaper to include now than to track as a separate follow-up that depends on someone remembering the disclosure in this PR's body. Your call whether it's in scope for this PR specifically.
There was a problem hiding this comment.
Included it here -- same primary-700 override extended to nav-tab-active.
Franky's review: the new color-contrast test built its own axe rule config from scratch instead of layering onto baselineRules, so link-name (already suppressed repo-wide for the admin footer's unlabeled social icons) re-enabled and failed the PR's own CI run. Use the same configureAxeWithIgnoredRuleset(baselineRules...) pattern every other test in this file already uses. Also extends the primary-700 override to .nav-tab-active (identical ~3:1 failure, same selector shape, flagged non-blocking by Franky as cheap to include now).
|
Method: in-place push |
| /* primary-500 on white is ~3.07:1, below WCAG AA's 4.5:1 -- primary-700 clears it. */ | ||
| .frm-white-body .frm_form_nav > li a.current_page, | ||
| .frm-white-body .post-type-frm_display .frm_form_nav .nav-tab-active, | ||
| .frm-white-body .post-type-frm_display .frm_form_nav .nav-tab-active:hover { |
There was a problem hiding this comment.
Measured --primary-500 (#4199fd) against white directly: 2.917:1, not ~3.07:1 — matches this PR's own verification table (2.92:1) and the footer-nav-link figure, not this comment's number. Doesn't affect the fix (still correctly below 4.5:1, --primary-700 still clears it), just a wrong number in a comment other engineers will read later.
| .frm-white-body .post-type-frm_display .frm_form_nav .nav-tab-active:hover { | |
| /* primary-500 on white is ~2.92:1, below WCAG AA's 4.5:1 -- primary-700 clears it. */ |
There was a problem hiding this comment.
Fixed, applied verbatim.
There was a problem hiding this comment.
Approve — the previously-blocking issue (this PR's own regression test failing on an unrelated, already-suppressed link-name violation because its axe config skipped baselineRules) is fixed exactly as suggested, and CI now confirms it (Cypress shard 2 green, was red at the last review).
Re-verified this round, live in a local Playground instance with this exact head commit (fa527ca6) loaded:
| Element | Measured | Claim |
|---|---|---|
Footer text + nav links (.frm-admin-footer-links-text, .frm-admin-footer-links-nav a) |
7.69:1 (getComputedStyle → rgb(71,84,103) = --grey-600) |
matches |
Active form-nav tab (.frm_form_nav a.current_page, Build page) |
5.87:1 (rgb(43,102,169) = --primary-700) |
matches |
New .post-type-frm_display .frm_form_nav .nav-tab-active rule |
not live-rendered (needs an existing Formidable View, none in this env) — confirmed real and reachable via source instead: resources/scss/admin/layout/page/_views-page-admin.scss targets the identical selector for the Views-editor metabox nav, so this isn't dead CSS; same 2-line override pattern as the other two, --primary-700 math already independently confirmed above |
(Screenshots are from this PR's own branch loaded in the persistent preview-env — same renders used to derive the two confirmed ratios above.)
One inline nit (non-blocking, see the suggestion on _navigation.scss): the new comment there claims primary-500-on-white is "~3.07:1" — measured the real --primary-500 (#4199fd) directly and get 2.92:1, matching this PR's own table. Doesn't change the fix.
Also checked: the footer's social icon links (.frm-admin-footer-links-socials a) still use --grey-400 untouched by this diff, so still ~2.58:1 on white — but that's the same already-tracked link-name gap from the last round (icon-only links with no discernible text, deliberately suppressed via baselineRules), not a color-contrast regression this PR introduces or claims to fix. Consistent with CI staying green on the scoped checkA11y call.
Repo-wide grep of resources/scss/ turned up ~50+ other var(--primary-500)/var(--grey-400) text/border-color usages outside this PR's scope — most are icons, non-white-page contexts, or components not covered by the linked axe run (formidable-pro#6586), so not treating this as a gap in this PR specifically, but worth a dedicated follow-up axe sweep across the rest of wp-admin's Formidable screens rather than assuming this PR closes out contrast issues repo-wide.
No blocking findings.
(Edit: the two screenshot links in this review were originally pasted wrong — copy/paste error from a different PR's upload, corrected to this PR's own actual renders above within a couple minutes of posting.)
There was a problem hiding this comment.
Re-reviewed at head (163e1b8) after my prior approve at fa527ca. The only delta since then is a one-line comment fix (2.92:1, not 3.07:1 — matches the PR description's own table and the sibling comments in the other two files). No functional change. CI green, contrast math checks out, regression test correctly asserts footer visibility before checking to avoid a vacuous pass. Still approving.
|
@Crabcyborg I think we can close this and not merge it, right? I'm going to open a few other PRs for accessibility issues, which I already did with #3376 one. |
|
Thanks Razvan. I think we can now. |




What was broken
An uncapped axe-core run (Strategy11/formidable-pro#6586) found core admin chrome failing WCAG 1.4.3 (4.5:1) on white-page screens (
FrmAppController::is_white_page()->.frm-white-body):.frm-admin-footer-links-text) and the Support/Docs/Upgrade nav links (classes/views/shared/admin-footer-links.php)a[data-link="review"],classes/views/shared/review.php:23).frm_form_nav a.current_pageand.post-type-frm_display .frm_form_nav .nav-tab-active, same ~2.9:1 failure)What changed
Scoped CSS overrides (source:
resources/scss/..., compiled:css/frm_admin.css) that swap--primary-500/--grey-400for the existing darker--primary-700/--grey-600steps, only on white-page screens (.frm-white-body) or inside the review notice's own card (.frm-review-notice, always self-contained/white regardless of the underlying page). Non-white admin pages keep their current colors. Also fixed the review notice's second.frm-button-primaryinstance (data-link="yes"), which shares the identical failing style.Added a regression test (
tests/cypress/e2e/admin-a11y.cy.js) scoped to the footer, built from the sameconfigureAxeWithIgnoredRuleset(baselineRules...)pattern every other test in this file uses, withcolor-contrastflipped on. It asserts the footer is visible before checking, since.frm-admin-footer-linksstartsfrm_hiddenand axe silently skips hidden nodes forcolor-contrast— without that assertion the test could pass vacuously.css/frm_admin.csswas hand-edited, not rebuilt. Nonode_moduleslocally and this agent doesn't runnpm installagainst arbitrary third-party packages on a shared machine — the rules were appended in the same minified style as the rest of the file. All of them win on specificity/!importantregardless of position, so a real rebuild's ordering is immaterial; a maintainer's ownnpm run buildwill reformat this into the same result.Verification
Measured contrast via
getComputedStyle+ WCAG relative-luminance formula, live in a local WP instance (Playground CLI), on the Forms list and a form's Build tab:.frm-admin-footer-links-text)--grey-400)--grey-600)--primary-500)--grey-600)a.current_page/.nav-tab-active)--primary-500)--primary-700)--primary-500)--primary-700)All four clear the 4.5:1 AA floor after the fix; no CSS custom property definitions changed, so unrelated pages/components are unaffected.
The regression test's axe config was confirmed both red (reproduced the exact
link-name, 4-node failure a from-scratch rule config causes against this page's unlabeled social icons) and green (zero violations withbaselineRuleslayered underneath) via a live axe run against the real admin footer page.Strategy11/formidable-pro#6586
🤖 Generated with Claude Code