Skip to content

fix(a11y): brand-dark text on pink accent CTAs (#96) - #116

Open
KhyFee wants to merge 5 commits into
philaconvalley:mainfrom
KhyFee:fix/a11y-pink-cta-contrast-96
Open

fix(a11y): brand-dark text on pink accent CTAs (#96)#116
KhyFee wants to merge 5 commits into
philaconvalley:mainfrom
KhyFee:fix/a11y-pink-cta-contrast-96

Conversation

@KhyFee

@KhyFee KhyFee commented Aug 3, 2026

Copy link
Copy Markdown

Summary

  • Button primary: text-whitetext-brand-dark on bg-accent-400
  • Same swap on pink CTA/hero sections across about, events, projects, resources, support, join, contact submit, and _blog
  • Outline buttons on pink sections follow the Button default (no redundant !text-brand-dark overrides)
  • e2e/contrast.spec.ts asserts the shared primary Button via /support data-testid="primary-cta" (/about has no primary Button)

Matches the approach already used in the header/event bar (#95).

Closes #96

Test plan

  • npm run build
  • Spot-check the seven pages’ pink CTAs (dark text readable)
  • npx playwright test e2e/contrast.spec.ts (or CI equivalent)

@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

@KhyFee is attempting to deploy a commit to the PhilaCon Valley Team on Vercel.

A member of the Team first needs to authorize it.

@KhyFee

KhyFee commented Aug 4, 2026

Copy link
Copy Markdown
Author

Friendly ping — Vercel reported this PR needs team authorization for the preview deploy. Happy to tweak the contrast swaps if review feedback comes back before that auth lands. Thanks for considering the a11y fix for #96!

@traksaw traksaw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Overview

Thanks for picking this up. The core change is right: #1A1A1A on #FF66A8 is 6.40:1 (vs. 2.72:1 for white), and the hover state accent-500 #F07AAC is 6.70:1 — both clear AA for normal text, and it matches the header approach from #95.

Two things need attention before merge: the new test doesn't assert on what it claims, and six of the ten files touch sections that aren't pink.


Blocking

1. The new e2e test asserts on the wrong element

e2e/contrast.spec.ts:121page.locator('section.bg-accent-400 a').first() on /about.

/about has exactly one bg-accent-400 section (about.astro:293), and its first anchor is <Button href="/join" variant="secondary"> (about.astro:300) — bg-primary-300 text-brand-dark, which already passed before this PR. /about contains no variant="primary" Button at all, so the regression guard this PR is built around isn't guarding anything. It passes today, and it would still pass if Button primary reverted to text-white.

Suggested fix — target a real primary Button by test id rather than DOM order. Button.astro already accepts data-testid:

<!-- src/pages/join.astro:122 -->
<Button href="/projects" variant="primary" data-testid="primary-cta" class="w-full">
await page.goto('/join');
const cta = page.getByTestId('primary-cta');

effectiveColours reads the element's own background, so the button doesn't need to sit inside a pink section for the assertion to be meaningful.

2. Six files restyle coral/purple sections, not pink ones

The description says "same swap on pink CTA/hero sections," but these heroes are not pink:

File Section Actual background
about.astro:16 hero bg-brand-coral #EF657F
about.astro:243 Who We Serve bg-brand-coral
events.astro:22 hero bg-brand-purple #B383C3
resources/index.astro:25 hero bg-brand-coral
projects/index.astro:63 hero bg-brand-purple
support.astro:16 hero bg-brand-purple

In each case only the <p> changed; the wrapping <section class="... text-white"> and the <h1>/<h2> are untouched. The result is a white heading directly above dark-grey body copy on the same coral/purple panel — a visible regression on six pages. resources/index.astro:30 also still has a text-white/50 line in that same hero, now sitting between white and dark text.

Only join.astro:12 is genuinely bg-accent-400, and that one is handled correctly (section and subtitle both flipped).

Recommendation: revert the six non-pink paragraph changes and keep this PR scoped to accent-400, matching the title and #96. Purple/coral contrast is a real problem worth its own issue — white on #B383C3 is 3.02:1, which only barely clears the 3:1 large-text threshold, and the text-white/85 subtitles on purple land around 2.6:1 and genuinely fail. That deserves a deliberate fix rather than a partial one.


Non-blocking

  • Redundant outline overrides. outline already resolves to border-2 border-current text-brand-dark. The new class="!text-brand-dark !border-brand-dark hover:!bg-brand-dark/10" on the seven CTA outline buttons re-states the default; the only real delta is hover /10 vs. the variant's /5. Dropping the class prop entirely would remove seven !important escapes and let the component own its styling.
  • contact.astro:251 duplicates the primary variant by hand. This is exactly why the fix needed touching in two places. Worth a follow-up to render <Button type="submit"> (needs a type prop on the component) so the token lives in one file.
  • Pink-on-pink. In these CTA sections a variant="primary" button would be accent-400 on an accent-400 background — near-invisible except for the shadow. None of the changed CTAs currently use primary there (they use secondary), so it isn't a bug today, but it's a trap for the next contributor.

Risks

Low blast radius — pure Tailwind class changes, no logic, no dependencies, no security surface. The realistic risk is visual: item 2 ships mixed-contrast headers/body on six pages, and item 1 means CI won't catch a future revert of the actual fix.

Verdict: the Button.astro / contact.astro / pink-CTA changes are good and should merge as-is. Please pull the six coral/purple paragraph edits back out, and re-point the e2e test at a real primary Button.

@KhyFee

KhyFee commented Aug 4, 2026

Copy link
Copy Markdown
Author

Thanks for the thorough review, @traksaw — really helpful, and you're right on both blocking points.

I'll:

  1. Re-point the e2e guard at a real primary Button on /join via data-testid="primary-cta" (instead of the secondary on /about).
  2. Revert the six coral/purple paragraph-only edits so this PR stays scoped to pink/accent-400 as the title and White-on-pink CTAs fail WCAG AA contrast across Button and seven page sections #96 intend.

Agree purple/coral contrast deserves its own deliberate pass — happy to open a separate issue once this lands.

On non-blocking: I'll drop the redundant outline !important classes if they're pure noise after the primary fix, and leave contact.astro / shared Button type as a follow-up unless you'd like them in this PR.

Pushing a fix commit shortly.

@KhyFee

KhyFee commented Aug 4, 2026

Copy link
Copy Markdown
Author

Pushed in c77078b:

  1. E2E now hits /join + getByTestId('primary-cta') on a real primary Button.
  2. Reverted the six coral/purple hero paragraph edits; pink/accent-400 sections stay as-is.

Left the non-blocking outline class overrides alone for now so the diff stays tight — happy to strip those in a follow-up if you'd like.

@traksaw

traksaw commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Code review

Found 1 issue:

  1. docs/design-system.md still documents the pattern this PR removes. The Accessibility section says hero text uses white on pink backgrounds, but the PR flips every bg-accent-400 surface to text-brand-dark. Left as-is, the doc points a future contributor straight back into White-on-pink CTAs fail WCAG AA contrast across Button and seven page sections #96.

- All interactive elements have visible focus styles using `accent-400`
- Buttons maintain contrast ratios against their backgrounds
- Hero text uses white on dark backgrounds (coral, purple, pink) for readability
- The homepage hero uses dark text on yellow

Checked and clear: contrast math holds (#1A1A1A on #FF66A8 = 6.40:1, hover #F07AAC = 6.70:1, both over AA 4.5:1), the new test's primary-cta testid resolves to the one variant="primary" Button on /join, and no non-pink surface was restyled.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@KhyFee

KhyFee commented Aug 5, 2026

Copy link
Copy Markdown
Author

Thanks @traksaw — good catch on the design-system doc. Updating Accessibility guidance to match brand-dark on accent-400 now.

@KhyFee

KhyFee commented Aug 5, 2026

Copy link
Copy Markdown
Author

Pushed design-system update: primary CTA docs + Accessibility bullets now say brand-dark on pink/accent-400 (coral/purple heroes stay white-on-dark). Thanks again for the careful review.

@KhyFee

KhyFee commented Aug 6, 2026

Copy link
Copy Markdown
Author

Thanks @traksaw — agree the design-system doc needed to match. This PR already updates docs/design-system.md Accessibility to brand-dark on pink CTAs (same change as the components). If anything still looks like white-on-pink in that section after the latest head, tell me the line and I'll patch again.

@traksaw traksaw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@KhyFee

The core change is correct: #1A1A1A on #FF66A8 computes to 6.40:1 (6.70:1 against the accent-500 hover), comfortably clearing AA, and every bg-accent-400 section in src/ is covered with no stragglers left on text-white.

Four issues, one blocking, left as inline comments:

  1. Blockingsrc/pages/join.astro:340: the outline-button swap was applied to a section that is not pink, producing a 1.00:1 invisible button.
  2. src/pages/join.astro:122 — will fail CI format:check.
  3. docs/design-system.md:76 — will fail CI format:check.
  4. docs/design-system.md:107 — encoding corruption (? where an em dash belongs).

Non-blocking notes

  • e2e/contrast.spec.ts:14-17 (outside the diff): the file's header docstring still says the bad pairing "still exists on the shared Button component and on several page-level CTA sections that predate this work — tracked separately rather than silently restyled here." This PR is that restyle, so the comment now describes the opposite of the code.
  • The new test guards only the shared Button. None of the eight page-level CTA sections this PR touched are covered — including the join hero and the hand-rolled contact.astro:251 submit button, which isn't a Button component at all — so a regression on any of them still ships silently.
  • The PR description says the test asserts a primary Button on /about; it actually navigates to /join. The wiring itself is fine — data-testid already passes through Button.astro.

Comment thread src/pages/join.astro Outdated
Comment thread src/pages/join.astro Outdated
Comment thread docs/design-system.md Outdated
Comment thread docs/design-system.md Outdated
@KhyFee

KhyFee commented Aug 10, 2026

Copy link
Copy Markdown
Author

Addressed review notes:

  • Reverted bottom "Get in Touch" on bg-brand-dark back to white outline (was 1:1 brand-dark-on-brand-dark)
  • Prettier format for primary-cta Button + design-system table
  • Restored em dash in the WCAG AA accessibility bullet

Thanks again for the precise reviews — ready when you are.

@KhyFee
KhyFee force-pushed the fix/a11y-pink-cta-contrast-96 branch from 31b002c to 33ad323 Compare August 10, 2026 07:01
@KhyFee

KhyFee commented Aug 10, 2026

Copy link
Copy Markdown
Author

Rebased onto latest main (design system / Brand Book updates). Reviews still applied:

  • brand-dark text on pink/accent primary CTAs
  • white outline on dark bottom “Get in Touch”
  • design-system a11y + format fixes

Force-pushed a clean history — please take another look when you can. Thanks again.

@traksaw traksaw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for taking this one on — and the core fix is right. I verified text-brand-dark on #FF66A8 measures 6.40:1, comfortably past AA, and you caught every bg-accent-400 surface including the outline overrides. That part is ready to merge as-is.

The issue is scope. This branch is based on current main (57a09df), which means the deletions in this diff are real deletions rather than something git will reconcile on merge — and a lot of the diff reverts PRs #131 and #132 that landed yesterday. My guess is a rebase or a merge resolution picked up the pre-#131 versions of these files.

Two things I'd flag as genuinely blocking, both in the inline comments:

  1. about.astro reintroduces a WCAG AA failuretext-white/80 at text-lg over #EF657F is 2.47:1. Worth catching precisely because this is an accessibility PR; it'd likely get merged on the strength of the title.
  2. docs/design-system.md deletes the accessibility section added in #132 and replaces it with guidance that white-on-coral is readable. It isn't (3.06:1), so the a11y doc would be documenting a failing pairing as approved.

What I'd suggest: keep Button.astro:25 and the eight page-level bg-accent-400 swaps, and drop everything else — all of about.astro, all of join.astro except the two hero class swaps, the docs/design-system.md rewrite, the contact.astro transition change, and the four re-title-cased H1s. That leaves a tight, obviously-correct PR.

One more that's outside the diff so I couldn't anchor it inline: src/pages/join.astro:4 still imports FirstPRWalkthrough after its only usage was removed. astro/tsconfigs/strict doesn't set noUnusedLocals, so astro check won't catch it — flagging it mostly because it suggests that deletion wasn't deliberate.

Happy to help with the rebase if it's fighting you.

Comment thread src/pages/about.astro Outdated
Comment thread docs/design-system.md
Comment thread src/pages/join.astro
Comment thread src/pages/join.astro Outdated
Comment thread src/pages/join.astro Outdated
Comment thread src/pages/about.astro Outdated
Comment thread e2e/contrast.spec.ts Outdated
Comment thread e2e/contrast.spec.ts Outdated
Comment thread src/pages/contact.astro Outdated
Comment thread src/pages/projects/index.astro Outdated
@KhyFee

KhyFee commented Aug 11, 2026

Copy link
Copy Markdown
Author

Rebuilt this PR color-only from current main after the design/motion work:

  • Button primary: brand-dark on accent-400 (not white)
  • Pink (bg-accent-400) section copy + outline CTAs match
  • Bottom CTAs on bg-brand-dark stay white outline
  • Design-system table + primary variant note — no Accessibility section deletion, no join card-grid rewrite, no H1/motion/title-case churn

Thanks again for the detailed re-review notes — ready when you are.

@KhyFee
KhyFee force-pushed the fix/a11y-pink-cta-contrast-96 branch from 33ad323 to ad3d5e4 Compare August 11, 2026 00:53

@traksaw traksaw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review findings.

e2e/contrast.spec.ts — The PR description says this file was extended to test a primary Button on /about. The diff shows no change to this file. The test file's own comment says it deliberately skips the shared Button component and page-level CTA sections as "tracked separately." So the text-white to text-brand-dark swap across Button.astro and seven pages ships with no automated contrast test to catch a regression.

Comment thread docs/design-system.md
Comment thread src/pages/about.astro
@KhyFee

KhyFee commented Aug 17, 2026

Copy link
Copy Markdown
Author

Thanks @traksaw — really helpful catch on both Aug 16 notes.

Pushed a fix commit:

  1. Removed the duplicate Button variant table header/separator in docs/design-system.md.
  2. Dropped the redundant !text-brand-dark !border-brand-dark outline overrides on pink CTA sections (about + the same pattern on the other accent-400 footers) so pages follow Button.astro defaults.

Happy to tweak anything else that still looks off.

@traksaw

traksaw commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

@KhyFee Code review finding: the PR description says it extends e2e/contrast.spec.ts to assert a primary Button on /about, but the diff does not touch this file (confirmed with git diff main...pr116 --stat).

This is a real gap: a reviewer may approve believing the pink-CTA fix has an automated regression test. It does not. A future change that reverts the primary Button back to text-white — the state before this fix, where the PR's own docs update notes "white-on-pink fails AA, about 2.7:1" — would ship with no test to catch it.

Everything else checks out: the text-whitetext-brand-dark swap on bg-accent-400 is applied consistently site-wide, and computed contrast ratios clear AA (~6.4:1 default, ~6.7:1 hover, ~5.6:1 for the opacity-90 paragraph text).

@KhyFee

KhyFee commented Aug 19, 2026

Copy link
Copy Markdown
Author

Thanks @traksaw — you're right, the description promised a primary-Button guard that wasn't in the diff.

/about has no variant="primary" Button (only secondary + outline on the pink footer), so I added data-testid="primary-cta" on the always-rendered Donate CTA on /support and an e2e assertion that the shared primary variant stays AA. That catches a text-white revert on Button.astro without depending on about-page chrome.

PR description updated to match.

@KhyFee

KhyFee commented Aug 19, 2026

Copy link
Copy Markdown
Author

Latest push adds the /support primary-cta e2e guard traksaw asked for — still blocked on Vercel team auth for preview deploy. Ready for another look when convenient.

@KhyFee

KhyFee commented Aug 24, 2026

Copy link
Copy Markdown
Author

Still standing by after the /support e2e guard — ready for another review pass whenever Vercel auth isn't blocking you.

@KhyFee

KhyFee commented Aug 26, 2026

Copy link
Copy Markdown
Author

Thanks again @traksaw — really appreciate the thorough reviews on this one.

Rebased onto latest main (picked up #138/#139). Current branch should match what you asked for:

  1. Core pink/accent-400 + shared Button primary → text-brand-dark only
  2. No duplicate button table header; Accessibility section from Reconcile the design system doc against the Brand Book #132 kept, with a pink CTA note added
  3. Redundant outline !text-brand-dark overrides dropped; dark-section outlines stay white
  4. E2E gates the shared primary Button on /support via data-testid="primary-cta" (PR description already reflects that — /about has no primary Button)

Ready for another look when you have a moment. Thanks!

@KhyFee
KhyFee force-pushed the fix/a11y-pink-cta-contrast-96 branch from a1caa82 to c5a2f85 Compare August 26, 2026 03:27
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.

White-on-pink CTAs fail WCAG AA contrast across Button and seven page sections

2 participants