Skip to content

fix(public): bring in-content links up to WCAG 2.2 24px tap targets - #25

Merged
nish3451 merged 1 commit into
mainfrom
fix/public-in-content-link-targets
Aug 9, 2026
Merged

fix(public): bring in-content links up to WCAG 2.2 24px tap targets#25
nish3451 merged 1 commit into
mainfrom
fix/public-in-content-link-targets

Conversation

@nish3451

@nish3451 nish3451 commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

What

PR #22 brought the footer links up to the WCAG 2.2 (SC 2.5.8) 24px tap-target minimum. The in-content links on every public page stayed plain inline anchors with ~17px hit areas — including the trust-critical ones: support mailto emails, "Privacy choices and requests", top-nav, product links, and the homepage hero-rail links.

This change gives .top-nav a, .product-links a, .plain-list a, and .rail-item strong a the same treatment the footer got: display: inline-block; min-height: 24px; padding: 4px 0; (rendered ~31–43px tall). Copy, colors, and layout otherwise unchanged.

Regression

scripts/test-public-footer-targets.mjs renamed to scripts/test-public-link-targets.mjs and extended (wired into npm test and npm run ci):

  • A. Every in-content link on all 12 public pages lives in a styled container (top-nav / plain-list / product-links / rail-item strong) or is a CTA/chrome anchor covered by a 48px/42px class
  • B. Each container rule enforces the 24px minimum (block-level box, min-height: 24px, ≥4px vertical padding)
  • C. CTA rules (.button,.text-link, .ghost-button) still ≥ 24px
  • D. Footer-link coverage from PR fix(public): bring footer links up to WCAG 2.2 24px tap targets #22 still enforced
  • E. npm test/ci wiring self-check

The regression fails 8 ways against the pre-fix CSS and passes (74 checks) with the fix.

Rendered proof

Playwright at 390x844 against the built pages: zero in-content links below 24x24 on /promptly/privacy/, /drishti/privacy/, /privacy-choices/, /promptly/, /, /contact/, /terms/; zero horizontal overflow on every page. Samples (pre-fix → post-fix): "Promptly support email" 160x17 → 160x31, "Privacy choices and requests" ~17 → 204x31, top-nav 24.3 → 32, hero-rail links → 43.

Verify

  • /home/nish/.local/bin/test-gate npm test — pass
  • /home/nish/.local/bin/test-gate npm run ci — pass
  • git diff --check — clean
  • Playwright 390x844 audit — pass (script at /tmp/opencode/ts-tap-target-audit.mjs)

Closes the backlog item: "In-content links stay below the WCAG 2.2 24px tap-target minimum - merged PR #22 fixes only .footer-links".

Summary by CodeRabbit

  • Accessibility Improvements
    • Increased the clickable area and vertical spacing for navigation, content, product, and list links.
    • Improved consistency with WCAG 2.2 guidance for interactive link targets.
  • Quality Improvements
    • Expanded automated checks across public pages to verify link sizing, placement, styling, and key calls to action.
    • Updated test and continuous integration checks to use the broader link-target validation.

PR #22 fixed only .footer-links; the trust-critical in-content links on
the app and privacy pages - mailto support emails, plain-list navigation,
top-nav, product links, and the homepage hero-rail links - stayed plain
inline anchors with ~17px hit areas, below the WCAG 2.2 24px minimum on
every tinystudio.in page at mobile widths. Give .top-nav a, .product-links
a, .plain-list a, and .rail-item strong a the same treatment as the
footer: inline-block with min-height 24px and 4px vertical padding
(rendered ~31-43px), so the whole row is tappable.

Renames scripts/test-public-footer-targets.mjs to
scripts/test-public-link-targets.mjs and extends it (wired into npm test
and npm run ci) to assert every in-content link on all 12 public pages
lives inside a styled container or CTA class, that each container rule
enforces the 24px minimum, and that footer links stay covered.

verify: /home/nish/.local/bin/test-gate npm test; /home/nish/.local/bin/test-gate npm run ci; git diff --check; node --check scripts/test-public-link-targets.mjs; Playwright 390x844 audit on /promptly/privacy/, /drishti/privacy/, /privacy-choices/, /promptly/, /, /contact/, /terms/ shows zero in-content links below 24x24 (pre-fix: 17px)

Co-authored-by: Claude <noreply@anthropic.com>

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces footer-only link validation with checks across public pages and link styles. It adds 24px interactive link targets for several link groups and updates npm test and CI commands to run the new validator.

Changes

Public link target validation

Layer / File(s) Summary
Interactive link target styling
public/styles.css
Navigation, rail, product, and plain-list links now use inline-block layout, 24px minimum height, and vertical padding.
Site-wide link validation
scripts/test-public-link-targets.mjs, scripts/test-public-footer-targets.mjs
The new validator checks in-content link coverage, CSS sizing, CTA and header rules, footer placement, and failure reporting. The footer-only validator is removed.
Validation command wiring
package.json
The test and ci scripts now run test-public-link-targets.mjs. The check script remains unchanged.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary change: updating public in-content links to meet WCAG 2.2 24px tap-target requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/public-in-content-link-targets

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

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@public/styles.css`:
- Around line 150-152: Update each affected anchor selector in
public/styles.css, including the blocks near the existing min-height rules, to
enforce a minimum inline dimension of 24px by adding min-width or
min-inline-size. Extend scripts/test-public-link-targets.mjs to validate that
each matching selector declares the same 24px minimum-width requirement while
preserving the existing height checks.

In `@scripts/test-public-link-targets.mjs`:
- Around line 94-102: Update the coverage calculation around
countChromeOrCtaLinks(), linksInside(), and railItemStrongLinks() to track
covered anchors by source position, deduplicating overlaps across selectors.
Compare the resulting unique covered-anchor set against the complete anchor set,
while preserving the existing requirement that coverage is nonzero and reporting
accurate unique counts.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4cda208a-eecd-4e2e-be07-27e4a2374450

📥 Commits

Reviewing files that changed from the base of the PR and between 5298652 and 8c55659.

📒 Files selected for processing (4)
  • package.json
  • public/styles.css
  • scripts/test-public-footer-targets.mjs
  • scripts/test-public-link-targets.mjs
💤 Files with no reviewable changes (1)
  • scripts/test-public-footer-targets.mjs

Comment thread public/styles.css
Comment on lines +150 to +152
display: inline-block;
min-height: 24px;
padding: 4px 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Enforce the 24px inline dimension.

These rules only enforce target height. A short anchor can remain narrower than 24px and still pass scripts/test-public-link-targets.mjs, because that validator does not check width.

Add min-width: 24px or min-inline-size: 24px to each selector. Extend the validator to require the same property.

Also applies to: 325-329, 414-416, 698-702

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@public/styles.css` around lines 150 - 152, Update each affected anchor
selector in public/styles.css, including the blocks near the existing min-height
rules, to enforce a minimum inline dimension of 24px by adding min-width or
min-inline-size. Extend scripts/test-public-link-targets.mjs to validate that
each matching selector declares the same 24px minimum-width requirement while
preserving the existing height checks.

Comment on lines +94 to +102
const covered =
countChromeOrCtaLinks(content) +
linksInside(content, TOP_NAV) +
linksInside(content, PLAIN_LIST) +
linksInside(content, PRODUCT_LINKS) +
railItemStrongLinks(content)
ok(
total === covered && covered > 0,
`${page} has no uncovered in-content links (${covered}/${total} in styled containers or CTA classes)`

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

De-duplicate covered anchors before comparison.

A CTA link inside .top-nav counts once in countChromeOrCtaLinks() and again in linksInside(content, TOP_NAV). An uncovered anchor can offset that duplicate, so total === covered passes even though the page has an uncovered link.

Track each anchor by its source position and compare the unique covered-anchor set with the complete anchor set.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test-public-link-targets.mjs` around lines 94 - 102, Update the
coverage calculation around countChromeOrCtaLinks(), linksInside(), and
railItemStrongLinks() to track covered anchors by source position, deduplicating
overlaps across selectors. Compare the resulting unique covered-anchor set
against the complete anchor set, while preserving the existing requirement that
coverage is nonzero and reporting accurate unique counts.

@nish3451
nish3451 merged commit b0f5f06 into main Aug 9, 2026
3 checks passed
nish3451 added a commit that referenced this pull request Aug 22, 2026
… live check now green (#221)

PR #22 fixed only footer links; PR #25 (b0f5f06) brought the in-content
links (top-nav, plain-list, product-links, rail-item strong a) up to the
WCAG 2.2 24px minimum and is merged on main. Static guard: 77 checks,
0 failures. Live guard: 32 checks, 0 failures — the stale-deployment
gap from the PR #152 lane is closed.

Co-authored-by: minimax-vps <minimax-vps@MiniMax.local>
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
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.

1 participant