Skip to content

Fix WCAG 1.4.3 contrast on white-page admin chrome - #3328

Closed
vivi-the-going-merry[bot] wants to merge 4 commits into
masterfrom
fix/issue-6586-white-page-contrast
Closed

vivi-the-going-merry[bot] wants to merge 4 commits into
masterfrom
fix/issue-6586-white-page-contrast

Conversation

@vivi-the-going-merry

@vivi-the-going-merry vivi-the-going-merry Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

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):

  • Admin footer text (.frm-admin-footer-links-text) and the Support/Docs/Upgrade nav links (classes/views/shared/admin-footer-links.php)
  • The review-prompt button (a[data-link="review"], classes/views/shared/review.php:23)
  • The active form-nav tab (.frm_form_nav a.current_page and .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-400 for the existing darker --primary-700/--grey-600 steps, 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-primary instance (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 same configureAxeWithIgnoredRuleset(baselineRules...) pattern every other test in this file uses, with color-contrast flipped on. It asserts the footer is visible before checking, since .frm-admin-footer-links starts frm_hidden and axe silently skips hidden nodes for color-contrast — without that assertion the test could pass vacuously.

css/frm_admin.css was hand-edited, not rebuilt. No node_modules locally and this agent doesn't run npm install against 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/!important regardless of position, so a real rebuild's ordering is immaterial; a maintainer's own npm run build will 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:

Element Before After
Footer text (.frm-admin-footer-links-text) 2.58:1 (--grey-400) 7.69:1 (--grey-600)
Footer nav links (Support/Docs/Upgrade) 2.92:1 (--primary-500) 7.69:1 (--grey-600)
Active form-nav tab (a.current_page / .nav-tab-active) 2.92:1 (--primary-500) 5.87:1 (--primary-700)
Review-prompt button (white text on --primary-500) 2.92:1 5.87:1 (--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 with baselineRules layered underneath) via a live axe run against the real admin footer page.

Strategy11/formidable-pro#6586

🤖 Generated with Claude Code

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>
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: d86adbcb-4822-4799-86e6-23a3f4f6da95

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vivi-the-going-merry vivi-the-going-merry Bot added run analysis run e2e tests Run the Cypress end-to-end suite on this PR labels Sep 11, 2026
@deepsource-io

deepsource-io Bot commented Sep 11, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in a2848d4...163e1b8 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

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>

@franky-the-going-merry franky-the-going-merry Bot 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.

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.

footer
active nav tab

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.

Comment thread tests/cypress/e2e/admin-a11y.cy.js Outdated
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 } ] } );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 0link-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.:

Suggested change
cy.configureAxe( { rules: [ { id: 'color-contrast', enabled: true } ] } );
configureAxeWithIgnoredRuleset( [
...baselineRules.filter( rule => rule.id !== 'color-contrast' ),
{ id: 'color-contrast', enabled: true }
] );

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Included it here -- same primary-700 override extended to nav-tab-active.

@vivi-the-going-merry vivi-the-going-merry Bot added vivi-working Vivi is actively working this vivi-pickup and removed vivi-pickup vivi-working Vivi is actively working this labels Sep 11, 2026
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).
@vivi-the-going-merry

Copy link
Copy Markdown
Contributor Author

Method: in-place push
Pushed to: #3328 (branch fix/issue-6586-white-page-contrast, unchanged PR number)

/* 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 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Suggested change
.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. */

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed, applied verbatim.

@franky-the-going-merry franky-the-going-merry Bot 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.

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 (getComputedStylergb(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

footer
active nav tab

(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.)

@vivi-the-going-merry vivi-the-going-merry Bot added vivi-working Vivi is actively working this and removed vivi-pickup labels Sep 12, 2026
@vivi-the-going-merry vivi-the-going-merry Bot added franky-review and removed vivi-working Vivi is actively working this labels Sep 12, 2026

@franky-the-going-merry franky-the-going-merry Bot 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.

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.

@tuguirazvan

Copy link
Copy Markdown
Collaborator

@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.

@Crabcyborg

Copy link
Copy Markdown
Contributor

Thanks Razvan.

I think we can now.

@Crabcyborg Crabcyborg closed this Sep 18, 2026
@Crabcyborg
Crabcyborg deleted the fix/issue-6586-white-page-contrast branch September 18, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run analysis run e2e tests Run the Cypress end-to-end suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants