Skip to content

feat(frontend): marquee UX polish — mobile DeFi split + clickable cards#36

Merged
AntiD2ta merged 3 commits intomainfrom
feat/marquee-ux-polish
Apr 18, 2026
Merged

feat(frontend): marquee UX polish — mobile DeFi split + clickable cards#36
AntiD2ta merged 3 commits intomainfrom
feat/marquee-ux-polish

Conversation

@AntiD2ta
Copy link
Copy Markdown
Owner

What / why

Two UX gaps in the category browse flow shipped together:

  1. DeFi row split (mobile-only) — the DeFi section carries 24 repos and, with the marquee's 3× content duplication, renders 72 card nodes per loop. On a 390 px viewport that's ~16 viewport-widths of uninterrupted horizontal scroll — a cognitive-load soft flag from the 2026-04-18 critique rerun.
  2. Clickable repo cards — today only the small title text inside each card is a link; the description, avatar, star count, and padding are dead zones despite the hover glow making the whole card look actionable.

How

Row split — a new frontend/src/lib/split-marquee.ts exposes a pure shouldSplit(count, isDesktop) + splitInHalf(items) pair. On mobile, categories over 20 repos render two stacked RepoMarquee instances; desktop is untouched. Order is preserved (first-half/second-half mechanical split) so it matches repos.ts at a glance. A labelled role="group" wraps the two rows so screen readers still announce the section as a single unit.

Clickable card — the existing title anchor is extended via the stretched-link pattern (::after { position: absolute; inset: 0 }) to cover the whole card. The StarIndicator is wrapped in a relative z-10 container so the retry button escapes the overlay and keeps its own click handler. Anchor gains an explicit aria-label so screen readers announce the destination.

No schema change, no Saturn or RepoMarquee internal change, no new components. Saturn chip-highlight routing still works via the unchanged data-repo-key attribute on the <article>.

Tests

  • Unit: split-marquee.test.ts (11) — threshold, even/odd, empty, order; repo-card.test.tsx extended (5) — stretched-link classes, retry escape, anchor attributes.
  • E2E: home-mobile-defi-split.spec.ts (390 × 844 shows two rows, 1440 × 900 shows one); repo-card-clickable.spec.ts (description dead-zone opens new tab, anchor attributes).
  • Browser-validated at 1440 × 900 via Chrome MCP: dead-zone hit-tests land on the <A> anchor, retry wrapper has position:relative; z-index:10.

Acceptance

Covers the 12 criteria in plan/phase-defi-row-split.md. All four local reviewers (spec, security, efficiency, quality) approved; two minor quality notes (test-label rot, index-based key) addressed inline.

Categories above 20 repos (today just DeFi at 24) render two stacked
horizontally-scrolling marquees below the md breakpoint. Desktop keeps
a single row unchanged. Preserves definition order via a mechanical
first-half/second-half split and wraps both rows in a labelled group
so screen readers still announce the section as a single unit.
The title anchor now extends its hit area over the whole card via a
CSS ::after { inset: 0 } overlay, turning the description and padding
dead zones into clickable surface. The StarIndicator is wrapped in a
relative z-10 container so the retry button escapes the overlay and
keeps its own click handler. Adds an explicit aria-label on the anchor
so screen readers announce the destination.
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ethstar Ready Ready Preview, Comment Apr 18, 2026 4:28pm

The marquee renders three DOM copies of each card to power the seamless
loop and parks scrollLeft in the middle copy, so the cards users see
are almost always duplicates. Those duplicates were marked
inert={true}, which blocks pointer events — the stretched-link fix
from the previous commit only worked on copy 0, which is usually off-
screen. Neither the title click nor the whole-card click fired on the
visible copies.

Replace inert with tabindex=-1 plumbed through a new focusable prop on
RepoCard. Duplicates keep aria-hidden for screen-reader dedup and stay
out of the Tab order, but the anchor and retry button once again
receive pointer events on every copy.
@AntiD2ta AntiD2ta merged commit 43ada21 into main Apr 18, 2026
14 checks passed
@AntiD2ta AntiD2ta deleted the feat/marquee-ux-polish branch April 18, 2026 20:02
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