Skip to content

refactor(ui): ProductList i18n data + link-card redesign#18815

Open
myelinated-wackerow wants to merge 11 commits into
devfrom
product-list
Open

refactor(ui): ProductList i18n data + link-card redesign#18815
myelinated-wackerow wants to merge 11 commits into
devfrom
product-list

Conversation

@myelinated-wackerow

Copy link
Copy Markdown
Collaborator

Summary

Rebuilds ProductList and migrates its four consumers.

  • Component — simplified the API (required, self-descriptive ctaLabel; parentHeadingLevel; pure presentational), then rebuilt items as ghost link cards: the whole card is the link (href on Card + CardButtonFake as the sole action, no nested links), a logo thumbnail beside title/description, and a CTA that goes full-width on narrow cards and fit-content once the card is wide (@container/card).
  • Content / i18n — moved hardcoded product titles/descriptions/CTAs into intl namespaces (new component-prediction-market-products.json, component-restaking-products.json); CTAs use a shared "Visit {brand}" skeleton fed a translated brand key rather than a hardcoded literal; stablecoins tool titles are now keyed (Dune/Visa keep a long title key separate from the short CTA brand); dropped an inline link from the Luna copy (invalid inside a card-link).
  • Gridcolumns={1} support (the asChild prop that briefly landed here was removed; nothing uses it).
  • Docs — design-system skill: the interpolate-a-translated-value i18n rule; ProductList documented as a card grid.

Test plan

  • /stablecoins tools list, AI-agents lists, prediction-markets, restaking: cards render, whole card links, single CTA works.
  • Light + dark (ghost hover fill; Dune logo dark-invert).
  • Responsive: 1-col (wide -> fit CTA), 2-col (stablecoins), narrow/mobile (full-width CTA).
  • RTL (ar): logo/text/CTA layout mirrors.

myelinated-wackerow and others added 11 commits July 3, 2026 15:41
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Require a complete, self-descriptive ctaLabel per item and drop the shared actionLabel fallback and its synthesized aria-label, so the component is pure presentational -- no getTranslations, no async.

Headings derive from a parentHeadingLevel prop, and the CTA now stacks below the content at every width instead of sitting inline on wide rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Move hardcoded product titles, descriptions, and CTAs into their intl namespaces and render the lists from async Server Components via getTranslations.

CTAs use a shared "Visit {brand}" skeleton that interpolates a translated brand key, rather than repeating the prefix across labels or injecting hardcoded English literals.

Stablecoins tool titles become keys too; Dune and Visa keep a long title key separate from the short CTA brand key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
Document the Grid-as-semantic-list pattern (asChild ul, list-none plus role=list, fold-independent dividers) and the bare ul/li legacy-style gotcha.

Clarify the translation boundary -- getTranslations for Server Components, the custom useTranslation hook for genuine client components, never next-intl useTranslations directly -- and the rule to interpolate a translated value rather than a hardcoded literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
# Conflicts:
#	.claude/skills/design-system/references/i18n-rtl.md
#	.claude/skills/design-system/references/server-vs-client.md
Render each item as a ghost Card whose whole surface links to the product: href on the Card with a CardButtonFake as the sole action, so there are no nested links in the copy.

Layout is a row -- a fixed-width logo thumbnail beside a content column. The CTA sits at the bottom of the column, full-width on narrow cards and fit-content once the card is wide enough (@container/card). Drops the old semantic-list + fold-independent-divider structure for the plain card-grid convention.

Story updated to the current API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
The whole ProductList card is now a single link, so a nested anchor in the copy is invalid HTML. Flatten Luna's TikTok link in its description to plain (bold) text.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
ProductList no longer uses the Grid-as-semantic-list + fold-independent-divider pattern, so remove that section from components.md and the now-dangling cross-reference from the bare-ul/li gotcha.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
asChild was added to support a Grid-as-<ul> semantic-list pattern that ProductList no longer uses, and nothing else consumes it. Remove the prop, its Slot import, and the doc bullet; the cols=1 support from the same original change stays.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: wackerow <54227730+wackerow@users.noreply.github.com>
@netlify

netlify Bot commented Jul 15, 2026

Copy link
Copy Markdown

Deploy Preview for ethereumorg ready!

Name Link
🔨 Latest commit 3fe1c29
🔍 Latest deploy log https://app.netlify.com/projects/ethereumorg/deploys/6a581b801e115e0008fe95b8
😎 Deploy Preview https://deploy-preview-18815.ethereum.it
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
7 paths audited
Performance: 58 (🟢 up 2 from production)
Accessibility: 95 (no change from production)
Best Practices: 100 (no change from production)
SEO: 98 (no change from production)
PWA: 59 (🔴 down 1 from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added content 🖋️ This involves copy additions or edits translation 🌍 This is related to our Translation Program labels Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔎 First-pass review — ✅ Looks mergeable

Rebuilds ProductList into a ghost link-card grid and migrates its four consumers (stablecoins tools, AI-agents, prediction-markets, restaking), lifting hardcoded product titles/descriptions/CTAs into intl namespaces. Scope is coherent, conventions hold, and the risky bits check out: Card/CardButtonFake/hoverLift/href are used as the component actually exposes them, grid-cols-auto-1 resolves via the grid-cols-auto-* @utility, and the three consumers converted to async server components render only inside server-rendered MDX (async MDX components are already an established pattern here, e.g. CategoryAppsGrid). Lint/type-check and unit tests are green.

Since this is a visual redesign, it wants a design eye on the Chromatic diffs and a dev sign-off — hence the routing labels. Nothing blocking.

Analysis

Lane: code (component + consumers), with English-intl content extraction.

Checked:

  • No unused vars/params introduced; alt = "" default and id are both consumed.
  • i18n: follows the repo's own t("visit-brand", { brand: t("<brand-key>") }) interpolation rule (translated value, not a hardcoded literal) — matches the doc added in this PR.
  • grid.tsx only adds a 1: entry to the existing cva; no bulk migration expected. The forwardRef reflow is a no-op style change.
  • columns prop narrowed to 2 — no consumer passes columns={1} to ProductList.
  • luna-description-1 English string changed (inline link removed); the intl pipeline will re-propagate — correct not to hand-edit locales.

Non-blocking:

  • productListSets[list] still returns undefined for an unknown list prop and would throw in .map — pre-existing behavior, all live MDX uses valid keys.
  • translation 🌍 label came from the src/intl/** path match; PR only touches en/, but new keys do feed the translation program, so leaving it.

CI: lint/type-check ✅, unit ✅; Chromatic + Netlify still running.

Generated by PR Reviewer (team) for #18815 · 106 AIC · ⌖ 27.5 AIC · ⊞ 5.2K ·

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

content 🖋️ This involves copy additions or edits translation 🌍 This is related to our Translation Program

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant