Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
793b1ac
refactor: inline single-child _components/ wrappers into page.tsx
pettinarip Apr 30, 2026
11e7a41
fix: remove excessive min-height gap in staking product cards
pettinarip Apr 30, 2026
6dc51d3
perf(homepage): right-size carousel and trust images to cut 200kb
pettinarip May 1, 2026
eb84d8e
feat(skills): add design-system skill
myelinated-wackerow May 4, 2026
43a2d4a
docs: point at design-system skill
myelinated-wackerow May 4, 2026
87e874c
docs: soften cva-migration phrasing
myelinated-wackerow May 4, 2026
bbb0e78
docs(skills): correct ui/ story file location
myelinated-wackerow May 5, 2026
5827997
feat(storybook): add Dialog story
myelinated-wackerow May 5, 2026
73c4992
feat(storybook): expand Modal story coverage
myelinated-wackerow May 5, 2026
73eef01
feat(storybook): add Sheet story
myelinated-wackerow May 5, 2026
996f69a
feat(storybook): add Popover story
myelinated-wackerow May 5, 2026
9d13c6c
feat(storybook): add DropdownMenu story
myelinated-wackerow May 5, 2026
bf06297
feat(storybook): add Select story
myelinated-wackerow May 5, 2026
4f8df0c
feat(storybook): add PersistentPanel story
myelinated-wackerow May 5, 2026
6b4953c
refactor(skills): split performance into references
pettinarip May 4, 2026
e0cc48b
docs(skills): add sizes prop guidance to performance/images
pettinarip May 5, 2026
4f4c9c4
perf(homepage): drop quality=65 override, keep sizes fix
pettinarip May 5, 2026
ceac6b9
perf(images): right-size next/image sizes across pages and swap prior…
pettinarip May 5, 2026
67b9d16
perf(images): right-size next/image sizes across remaining pages and …
pettinarip May 5, 2026
3cd8917
feat(storybook): add Command story
myelinated-wackerow May 5, 2026
46b2e39
docs(skills): mark Swiper deprecation track explicitly
myelinated-wackerow May 5, 2026
9981ff6
docs(skills): drop unused components, add Faq, update Callout consoli…
myelinated-wackerow May 6, 2026
c0503c3
ci: consolidate workflows into ci.yml
pettinarip May 7, 2026
91cc2d1
i18n(ar): LLM translation
wackerow May 7, 2026
e453863
i18n(bn): LLM translation
wackerow May 7, 2026
1f5d7e4
i18n(cs): LLM translation
wackerow May 7, 2026
c69c2cc
i18n(de): LLM translation
wackerow May 7, 2026
111dc50
i18n(es): LLM translation
wackerow May 7, 2026
6bebb56
i18n(fr): LLM translation
wackerow May 7, 2026
e1045fb
i18n(hi): LLM translation
wackerow May 7, 2026
39994a4
i18n(id): LLM translation
wackerow May 7, 2026
f2e3c3c
i18n(it): LLM translation
wackerow May 7, 2026
e34d658
i18n(ja): LLM translation
wackerow May 7, 2026
8380121
i18n(ko): LLM translation
wackerow May 7, 2026
d748d12
i18n(mr): LLM translation
wackerow May 7, 2026
ddfc7df
i18n(pl): LLM translation
wackerow May 7, 2026
44e9037
i18n(pt-br): LLM translation
wackerow May 7, 2026
160559c
i18n(ru): LLM translation
wackerow May 7, 2026
b13512e
i18n(sw): LLM translation
wackerow May 7, 2026
1278682
i18n(ta): LLM translation
wackerow May 7, 2026
002b01e
i18n(te): LLM translation
wackerow May 7, 2026
94d124d
i18n(tr): LLM translation
wackerow May 7, 2026
7840455
i18n(uk): LLM translation
wackerow May 7, 2026
5379d6c
i18n(ur): LLM translation
wackerow May 7, 2026
c478e79
i18n(vi): LLM translation
wackerow May 7, 2026
025a489
i18n(zh): LLM translation
wackerow May 7, 2026
869f8f5
i18n(zh-tw): LLM translation
wackerow May 7, 2026
b32036e
i18n: sanitize translation output
wackerow May 7, 2026
d83b890
i18n: merge tmp-intl/run-0507-1802 into intl/pending-dev
wackerow May 7, 2026
0092128
build(deps): bump icu-minify from 4.9.1 to 4.11.0
dependabot[bot] May 8, 2026
e3579cd
build(deps): bump next-intl from 4.9.1 to 4.9.2
dependabot[bot] May 8, 2026
4c7e97f
fix: remove dead molochdao.com link that redirects to spam
tenderdeve May 8, 2026
6f604d3
build(deps): bump hono from 4.12.12 to 4.12.18
dependabot[bot] May 8, 2026
396cfc1
build(deps): bump fast-xml-builder from 1.1.5 to 1.2.0
dependabot[bot] May 8, 2026
490710d
build(deps): bump fast-uri from 3.0.6 to 3.1.2
dependabot[bot] May 8, 2026
d51b16f
refactor(ui): ExpandableCard defaults
wackerow May 9, 2026
5ec4b6c
build(deps): bump @babel/plugin-transform-modules-systemjs
dependabot[bot] May 9, 2026
943043c
i18n: sync external app and tool descriptions
actions-user May 11, 2026
210ec3c
patch(i18n): page-community namespace usage
wackerow May 11, 2026
77949b9
Merge branch 'dev' into refactor/inline-page-server-components
wackerow May 11, 2026
a17d370
Merge pull request #18079 from ethereum/fix/staking-product-card-gap
wackerow May 11, 2026
69df51a
Merge pull request #18119 from ethereum/refactor/perf-skill-split
wackerow May 11, 2026
cc56814
Merge pull request #18128 from ethereum/perf/homepage-image-delivery
wackerow May 11, 2026
4725d56
Merge branch 'dev' into refactor/inline-page-server-components
wackerow May 11, 2026
857e32b
Merge pull request #18078 from ethereum/refactor/inline-page-server-c…
wackerow May 11, 2026
b40af24
Merge branch 'master' into dev
wackerow May 11, 2026
65f8f52
patch: hong kong co-working signup url
wackerow May 12, 2026
33c04bb
Merge pull request #18164 from tenderdeve/fix/18149-remove-molochdao-…
wackerow May 12, 2026
11816eb
docs: update README.md [skip ci]
allcontributors[bot] May 12, 2026
af8539d
docs: update .all-contributorsrc [skip ci]
allcontributors[bot] May 12, 2026
c174d23
Merge pull request #18170 from ethereum/all-contributors/add-tenderdeve
wackerow May 12, 2026
d1d9f74
docs: update README.md [skip ci]
allcontributors[bot] May 12, 2026
7ed5f07
docs: update .all-contributorsrc [skip ci]
allcontributors[bot] May 12, 2026
bfceb57
Merge pull request #18171 from ethereum/all-contributors/add-nikolay-…
wackerow May 12, 2026
3708e24
Replace bug bounty submission link
fredrik0x May 12, 2026
be0b1a9
Replace bbp-form in BugBountyCards.tsx
fredrik0x May 12, 2026
e1b8790
Merge pull request #18173 from ethereum/bounty-form-update
wackerow May 12, 2026
ea8bec5
feat(ui): update border-radius to `2xl` token
wackerow May 12, 2026
4cf2c4e
fix: use unique key for list items
wackerow May 12, 2026
c0d29e5
Merge branch 'dev' into expandable-card
wackerow May 12, 2026
c679334
Merge remote-tracking branch 'origin/dev' into intl/pending-dev
myelinated-wackerow May 12, 2026
8ccbb26
i18n: fix critical translation issues
myelinated-wackerow May 12, 2026
14e54f3
Merge pull request #18145 from ethereum/intl/pending-dev
wackerow May 12, 2026
219dc33
Merge pull request #18139 from ethereum/ci/consolidate-workflows
wackerow May 12, 2026
deca48a
testing(design-system): initial skill evals
myelinated-wackerow May 12, 2026
10e0bab
build(deps): bump @protobufjs/utf8 from 1.1.0 to 1.1.1
dependabot[bot] May 12, 2026
ad24b32
fix(qa): filter past hackathons and add site name to page titles
May 13, 2026
f33c03b
Merge pull request #18162 from ethereum/i18n/external-descriptions-20…
wackerow May 13, 2026
cfaa1a1
Merge pull request #18147 from ethereum/dependabot/npm_and_yarn/icu-m…
wackerow May 13, 2026
509aaa7
Merge pull request #18148 from ethereum/dependabot/npm_and_yarn/next-…
wackerow May 13, 2026
6390a9a
Merge pull request #18154 from ethereum/dependabot/npm_and_yarn/hono-…
wackerow May 13, 2026
d008b21
build(deps): bump protobufjs from 7.5.4 to 7.5.8
dependabot[bot] May 13, 2026
69bbf59
build(deps): bump next from 16.2.3 to 16.2.6
dependabot[bot] May 13, 2026
8dd2d3a
config: update codeowners, team
wackerow May 13, 2026
dcb9d36
Merge pull request #18155 from ethereum/dependabot/npm_and_yarn/fast-…
wackerow May 13, 2026
62389ec
Merge pull request #18156 from ethereum/dependabot/npm_and_yarn/fast-…
wackerow May 13, 2026
df21361
Merge pull request #18159 from ethereum/dependabot/npm_and_yarn/babel…
wackerow May 13, 2026
e076e73
Merge pull request #18178 from ethereum/dependabot/npm_and_yarn/proto…
wackerow May 13, 2026
8918ba9
Merge pull request #18182 from ethereum/codeowners
pettinarip May 13, 2026
2834845
Merge pull request #18157 from ethereum/expandable-card
pettinarip May 13, 2026
7f6afa2
Merge pull request #18168 from ethereum/update-link
pettinarip May 13, 2026
430b71f
Merge pull request #18174 from ethereum/fix-key-warning
pettinarip May 13, 2026
1c1ee20
Merge pull request #18177 from ethereum/dependabot/npm_and_yarn/proto…
wackerow May 13, 2026
a5cdbdf
Merge pull request #18179 from ethereum/dependabot/npm_and_yarn/next-…
wackerow May 13, 2026
c2c95be
build(deps): bump hono from 4.12.12 to 4.12.18
dependabot[bot] May 13, 2026
c973027
chore(storybook): disable Chromatic snapshots on new overlay stories
myelinated-wackerow May 13, 2026
4988b78
Merge pull request #18180 from ethereum/fix/qa-weekly-issues-may-2026
wackerow May 13, 2026
d2f422f
Merge pull request #18186 from ethereum/dependabot/npm_and_yarn/hono-…
wackerow May 13, 2026
f98f0fe
Merge branch 'master' into dev
wackerow May 13, 2026
2736682
i18n(ar): LLM translation
wackerow May 13, 2026
f91e96f
i18n(bn): LLM translation
wackerow May 13, 2026
dcfacae
i18n(cs): LLM translation
wackerow May 13, 2026
560a0dc
i18n(de): LLM translation
wackerow May 13, 2026
27b16ce
i18n(es): LLM translation
wackerow May 13, 2026
17e355b
i18n(fr): LLM translation
wackerow May 13, 2026
ad77ce9
i18n(hi): LLM translation
wackerow May 13, 2026
19b3c75
i18n(id): LLM translation
wackerow May 13, 2026
631d8b1
i18n(it): LLM translation
wackerow May 13, 2026
fdc5cc7
i18n(ja): LLM translation
wackerow May 13, 2026
8b46df9
i18n(ko): LLM translation
wackerow May 13, 2026
9dadf63
i18n(mr): LLM translation
wackerow May 13, 2026
2623b10
i18n(pl): LLM translation
wackerow May 13, 2026
f042f1b
i18n(pt-br): LLM translation
wackerow May 13, 2026
38401e7
i18n(ru): LLM translation
wackerow May 13, 2026
9608110
i18n(sw): LLM translation
wackerow May 13, 2026
ea20ad0
i18n(ta): LLM translation
wackerow May 13, 2026
8a62b24
i18n(te): LLM translation
wackerow May 13, 2026
f6051e0
i18n(tr): LLM translation
wackerow May 13, 2026
2511785
i18n(uk): LLM translation
wackerow May 13, 2026
a4dd07c
i18n(ur): LLM translation
wackerow May 13, 2026
29a27c2
i18n(vi): LLM translation
wackerow May 13, 2026
489495a
i18n(zh): LLM translation
wackerow May 13, 2026
a37e4fb
i18n(zh-tw): LLM translation
wackerow May 13, 2026
a8b2914
i18n: sanitize translation output
wackerow May 13, 2026
2a67b37
i18n: merge tmp-intl/run-0513-1530 into intl/pending-dev
wackerow May 13, 2026
9eb4d45
Merge pull request #18122 from ethereum/feat/storybook-overlay-primit…
pettinarip May 13, 2026
69e1a0e
i18n: fix translation errors in clear-signing
myelinated-wackerow May 13, 2026
d1a72ff
Merge pull request #18188 from ethereum/intl/pending-dev
wackerow May 13, 2026
b96b850
Merge pull request #18120 from ethereum/feat/design-system-skill
pettinarip May 14, 2026
cdd4fde
11.6.2
pettinarip May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 18 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -14222,6 +14222,24 @@
"contributions": [
"bug"
]
},
{
"login": "tenderdeve",
"name": "TenderDeve",
"avatar_url": "https://avatars.githubusercontent.com/u/171561659?v=4",
"profile": "https://manmit07.netlify.app/",
"contributions": [
"maintenance"
]
},
{
"login": "nikolay-udovik",
"name": "Nikolay Udovik",
"avatar_url": "https://avatars.githubusercontent.com/u/73495276?v=4",
"profile": "https://github.com/nikolay-udovik",
"contributions": [
"maintenance"
]
}
],
"contributorsPerLine": 7,
Expand Down
126 changes: 126 additions & 0 deletions .claude/skills/design-system/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
name: design-system
description: Use when building, refactoring, or styling any UI in the ethereum.org Next.js site (`src/components/`, `app/`, `src/styles/`, `public/content/`, or any `.tsx`/`.mdx`/`.css` change that affects the rendered UI). Provides canonical component choices, design tokens, RTL/i18n rules, server/client guidance, and the "use a variant, not a new component" pattern for the project's Tailwind v4 + Radix + shadcn-style design system.
---

# ethereum.org Design System

Tailwind v4 (CSS-first config, no `tailwind.config.ts`) + React 18 / Next.js App Router + Radix UI primitives + shadcn-style component layer. Tokens live in CSS. Read this file fully on activation; pull from `references/` only when the listed trigger applies.

## The Core Habit: Reuse Over Reinvent

The single highest-leverage habit for keeping this codebase consistent: **when you need new UI, look for a primitive or variant first, only invent if nothing fits.** Most "new component" instincts are actually "new variant" instincts in disguise.

Before you write any UI code, ask:
- Is there a primitive that already does this? (`Card`, `Button`, `Alert`, `Tag`, `Hero/*`)
- Is the difference small enough to express as a *variant* on an existing primitive?
- Can I compose existing primitives instead of inlining a long Tailwind class chain?

If you find yourself writing `flex items-center gap-X rounded-Y border bg-... p-Z` for a card-like thing, you're reinventing `<Card>`. If you write `<p className="text-4xl font-bold">N</p>` for a stat, you're reinventing `<BigNumber>`. If you write `<div className="text-5xl font-bold">Title</div>`, you're reinventing `<h1>` (which is already styled by `base.css`). **Compose, don't inline.**

When the existing primitive doesn't quite fit, the answer is usually "add a variant," not "create a new file." See `references/variant-vs-new.md`.

## Top Rules

1. **No raw `<a>` or `<button>`.** Use `<Button>`/`<ButtonLink>` from `@/components/ui/buttons/Button` and `InlineLink`/`BaseLink`/`LinkWithArrow` from `@/components/ui/Link`. These primitives handle event tracking, external-link safety, locale routing, and focus rings.
2. **No raw color values.** Use semantic tokens (`text-body`, `bg-background`, `border-border`, `text-primary`). Hex literals and `rgb()` calls bypass dark mode.
3. **Prefer adding a variant** to an existing primitive over creating a new component. Card, Button, Alert, Tag are the most common targets.
4. **Server Components by default.** Only `"use client"` when you need state, effects, browser APIs, or inline event handlers.
5. **All text is translatable.** `getTranslations` (server) or `useTranslations` (client) from `next-intl`. Never hard-code user-facing English.
6. **Logical CSS for direction.** Use `ms-`/`me-`/`ps-`/`pe-`/`inset-s-`/`inset-e-`/`border-s`/`border-e`/`text-start`/`text-end`. The site supports Arabic and Urdu (RTL). Hard-coded `left-`/`right-`/`ml-`/`mr-`/`pl-`/`pr-` breaks RTL.
7. **Locale-aware formatters.** `numberFormat()` from `@/lib/utils/numbers`, `dateTimeFormat()` from `@/lib/utils/date`. Never `toLocaleString` / `Intl.NumberFormat` directly.
8. **`useRtlFlip()` for directional icons** (right-pointing arrows/chevrons). Or use `ChevronNext`/`ChevronPrev` from `@/components/Chevron`.
9. **Markdown content goes through `MdComponents`.** The legacy `@/components/Card` (default export) is reserved for markdown shortcodes -- never import it from app code; use `@/components/ui/card`.
10. **Storybook stories ship with new UI components.** No automated unit tests; Storybook + Chromatic + types are the verification layer.

## Highest-Value Gotchas (read these now)

These are landmines where the code looks reasonable but the pattern is wrong. The full set is in `references/gotchas.md`; these are the ones that come up most often.

### Imports that look right but aren't

- **Cards**: `import { Card } from "@/components/ui/card"` is canonical. **Not** `import Card from "@/components/Card"` (default export of that file is reserved for markdown shortcodes).
- **Tooltips**: `import Tooltip from "@/components/Tooltip"` (mobile-aware, Matomo-tracked, scroll-close). **Not** `import { Tooltip } from "@/components/ui/tooltip"` (that's the bare Radix primitive used internally).
- **Modals**: `import Modal from "@/components/ui/dialog-modal"` (default export, the high-level convenience) for typical modal needs. `@/components/ui/dialog` is the vanilla shadcn-style primitive for fine-grained Radix control. Same names exported from both files; **do not mix sources within a feature**.
- **Heroes**: import from `@/components/Hero` (`ContentHero`, `SimpleHero`, `HubHero`, `MdxHero`, `HomeHero`). **Not** `@/components/PageHero` (deprecation track).

### Stale shadcn token names that don't resolve

`bg-popover`, `text-popover-foreground`, `bg-accent`, `text-accent-foreground`, `bg-muted`, `text-muted-foreground`, `focus:ring-ring`, `ring-offset-background` appear in `ui/select.tsx`, `ui/dialog.tsx`, `ui/dropdown-menu.tsx`, `ui/tabs.tsx` but are **NOT defined** in this project's tokens. They render incorrectly. If you touch these files, replace with project semantic tokens (`bg-background-highlight`, `text-body`, `bg-accent-a`, `text-body-medium`, etc.). Don't introduce new uses.

### `useColorModeValue` is a Chakra leftover

Used in 5 places. Don't introduce new uses. Use Tailwind `dark:` variant + semantic tokens.

### Subtle component behaviors

- `<Button isSecondary>` only takes effect on `outline` and `ghost` variants. Silent no-op on `solid`/`link`.
- `<CardBanner fit="contain">` with a single `<Image>` child auto-clones it as a blurred backdrop. Pass two children and you lose this magic.
- `LinkBox` requires a `LinkOverlay` somewhere inside; without it, the whole-card-clickable pattern doesn't work.
- `commonControlClasses` in `ui/checkbox.tsx` is shared by `Switch`. Editing it changes both.

### No `Heading` primitive -- use semantic tags

`base.css` styles `<h1>`-`<h6>` with the right sizes and `font-bold`. Just write `<h1>Title</h1>`. Override the size class on the heading element when really needed (`<h2 className="text-4xl">`). Reinventing with `<div className="text-5xl font-bold">` loses semantics and screen-reader navigation.

### One stray `toLocaleString` in `ui/chart.tsx:241`

Don't add more. Use `numberFormat()`.

## Quick "Where Do I Import From?" Cheatsheet

| I need... | Import |
|---|---|
| Card | `import { Card, CardBanner, CardContent, CardTitle, CardParagraph } from "@/components/ui/card"` |
| Modal/Dialog (typical) | `import Modal from "@/components/ui/dialog-modal"` (default export) |
| Side sheet | `import { Sheet, ... } from "@/components/ui/sheet"` |
| Tooltip | `import Tooltip from "@/components/Tooltip"` (NOT `@/components/ui/tooltip`) |
| Button | `import { Button, ButtonLink } from "@/components/ui/buttons/Button"` |
| Anchor (in prose) | `import InlineLink from "@/components/ui/Link"` (default) |
| Anchor (CTA with arrow) | `import { LinkWithArrow } from "@/components/ui/Link"` |
| Page hero | `import { ContentHero, SimpleHero, HubHero, MdxHero } from "@/components/Hero"` |
| Inline alert | `import { Alert, AlertContent, AlertDescription } from "@/components/ui/alert"` |
| Top-of-page banner | `import BannerNotification from "@/components/Banners/BannerNotification"` |
| Big numeric display | `import BigNumber from "@/components/BigNumber"` |
| Layout | `import { Stack, HStack, VStack, Flex, Center } from "@/components/ui/flex"` |
| Number formatting | `import { numberFormat } from "@/lib/utils/numbers"` |
| Date formatting | `import { dateTimeFormat } from "@/lib/utils/date"` |
| RTL flip helper | `import { useRtlFlip } from "@/hooks/useRtlFlip"` |

For full decision trees with all the look-alike landmines, see `references/canonical-imports.md`.

## When to Load Each Reference

Pull these in only when the trigger applies. Don't read them all upfront.

- **`references/canonical-imports.md`** -- Load when you're about to import a component and aren't sure which file is canonical (Card, Modal, Tooltip, Hero, Tabs all have multiple plausible imports).
- **`references/components.md`** -- Load when you need the full inventory: what each component is for, its variants, its canonical usage example.
- **`references/tokens.md`** -- Load when you need to add a new token, define a gradient, choose a z-index, or are unsure which semantic token applies. Also: when working in `src/styles/`.
- **`references/spacing-typography.md`** -- Load when laying out a page or section, deciding heading sizes, choosing spacing rhythms, or working with text density.
- **`references/gotchas.md`** -- Load when you hit unexpected behavior in a primitive (auto-blur backdrop, slot-prop coupling, hidden client boundary, etc.) or want the long-tail confusion patterns beyond what's inline above.
- **`references/variant-vs-new.md`** -- Load when you're tempted to create a new component file. Read this first to confirm whether a variant is the right answer.
- **`references/cleanup-playbook.md`** -- Load when refactoring existing code that has anti-patterns (one-off styling, raw `<a>`/`<button>`, hex colors, hard-coded English, etc.). The "old pattern -> new pattern" map.
- **`references/i18n-rtl.md`** -- Load when adding user-facing text, formatting numbers/dates, working with directional spacing, or writing translation keys.
- **`references/server-vs-client.md`** -- Load when deciding whether to mark a component `"use client"`, structuring a page that mixes static and interactive parts, or refactoring across the SSR boundary.
- **`references/a11y.md`** -- Load when adding interactive elements (modals, dropdowns, custom click targets), building forms, or working with images and headings.
- **`references/card-walkthrough.md`** -- Load when starting any card-shaped UI work; an end-to-end worked example.
- **`references/page-hero-walkthrough.md`** -- Load when starting a new page that needs a hero; an end-to-end worked example.
- **`references/new-component-checklist.md`** -- Load before opening a PR for a new component. The pre-merge checklist.

## Other Project Skills That May Apply

- **`data-layer`** -- For data fetching/sources. UI work that needs data should compose with this.

## Pre-Merge Smoke Test

Before opening a PR for any UI work:

- [ ] No raw `<a>` or `<button>`
- [ ] No hard-coded colors (`#hex`, `rgb()`, `hsla()`); semantic tokens only
- [ ] No `left-`/`right-`/`ml-`/`mr-`/`pl-`/`pr-` (use logical equivalents)
- [ ] All user-facing strings translatable
- [ ] `numberFormat()`/`dateTimeFormat()` for formatting (not native APIs)
- [ ] Server Components wherever possible
- [ ] New UI primitives have a `.stories.tsx`
- [ ] Headings use `<h1>`-`<h6>` (not `<div className="text-5xl font-bold">`)
- [ ] If introducing a new component, justify why it isn't a variant of an existing one
76 changes: 76 additions & 0 deletions .claude/skills/design-system/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"skill_name": "design-system",
"notes": "Output evals for the design-system skill. Each prompt exercises a distinct high-leverage rule (variant-over-new, canonical imports, i18n/RTL, hero family + server/client, modal disambiguation + raw-element ban).",
"evals": [
{
"id": 1,
"name": "variant-over-new-stat-block",
"prompt": "hey can you add a little stat block to the bottom of app/[locale]/staking/page.tsx? something like \"$45.2B\" on top in big bold text and \"ETH staked\" underneath. I want it centered. probably just spin up a new component for it, call it StakingStat or something",
"expected_output": "Skill should resist the 'new component' framing and steer toward the existing BigNumber primitive (and/or Card composition). Should also flag that user-facing strings need translation and that the number should go through numberFormat() if it isn't a static literal.",
"files": [],
"assertions": [
{"text": "Output uses BigNumber primitive (imports from @/components/BigNumber)"},
{"text": "Output does NOT create a new top-level component named StakingStat (or similar) in outputs"},
{"text": "All visible English strings ('ETH staked', any label) routed through a next-intl translation function (getTranslations or t())"},
{"text": "Output does NOT inline a div with `text-5xl font-bold` (or similar manual size+weight) for the stat number"},
{"text": "notes.md explicitly names BigNumber (and/or Card) as the chosen primitive and explains the pushback on the user's 'new component' framing"}
]
},
{
"id": 2,
"name": "tooltip-canonical-import",
"prompt": "the \"Bridge\" button in src/components/Nav/Mobile/index.tsx needs a little info tooltip on hover explaining what bridging is. can you wire that up? grab whatever tooltip the project uses",
"expected_output": "Skill should pick the high-level Tooltip default export from @/components/Tooltip (mobile-aware, Matomo-tracked, scroll-close) and explicitly NOT import { Tooltip } from @/components/ui/tooltip (which is the bare Radix primitive). Translatable copy expected.",
"files": [],
"assertions": [
{"text": "Output imports Tooltip from `@/components/Tooltip` (the mobile-aware default export)"},
{"text": "Output does NOT import from `@/components/ui/tooltip` (which is the bare Radix primitive)"},
{"text": "Tooltip content text is routed through a next-intl translation function (not a hard-coded English literal)"},
{"text": "notes.md justifies the Tooltip import choice and references the mobile-aware/Matomo-tracked rationale"}
]
},
{
"id": 3,
"name": "i18n-rtl-and-number-format",
"prompt": "on the contributors page (app/[locale]/contributing/page.tsx) i want to show \"There are 3,847 open issues right now\" with the number in bold. put it in a div with ml-4 mt-6 so it sits indented under the section heading. the count comes from a `count` variable thats already in scope",
"expected_output": "Skill should: (a) replace ml-4 with logical ms-4 (RTL safety), (b) replace the hard-coded English string with a getTranslations call and translation key, (c) format the count with numberFormat() rather than toLocaleString or a raw interpolation, (d) NOT recommend Intl.NumberFormat directly.",
"files": [],
"assertions": [
{"text": "Output uses `ms-4` (logical inline-start) instead of `ml-4`"},
{"text": "Output does NOT contain `ml-4`, `pl-`, `pr-`, `mr-`, `left-`, or `right-` Tailwind classes"},
{"text": "Output imports and uses `numberFormat()` from `@/lib/utils/numbers`"},
{"text": "Output does NOT call `count.toLocaleString()` or `new Intl.NumberFormat(...)` directly"},
{"text": "User-facing English ('There are', 'open issues right now', 'open issues') is routed through `getTranslations` / `t()` / `t.rich()` rather than appearing as a bare JSX literal"}
]
},
{
"id": 4,
"name": "hero-family-and-server-component",
"prompt": "we're adding a new landing page at app/[locale]/community/online/page.tsx. it needs a hero up top with a title, a one-paragraph blurb, an illustration on the right (use public/images/community.png), and two CTA buttons. should i build the hero from scratch or is there a pattern? just give me the file",
"expected_output": "Skill should recommend a hero from the @/components/Hero family (likely ContentHero or SimpleHero depending on shape) and explicitly avoid @/components/PageHero (deprecation track). Should keep the page as a Server Component (no 'use client'), use ButtonLink for CTAs (not raw <a>), and use getTranslations for copy.",
"files": [],
"assertions": [
{"text": "Output imports a hero from the `@/components/Hero` family (ContentHero, SimpleHero, HubHero, or MdxHero)"},
{"text": "Output does NOT import from `@/components/PageHero` (deprecation track)"},
{"text": "Output does NOT include `'use client'` at the top of page.tsx (Server Component default)"},
{"text": "CTA buttons use `ButtonLink` (or are passed via the hero's `buttons` prop), not raw `<a>` or `<button>` elements"},
{"text": "Page-level copy (title, blurb, CTA labels) is routed through `getTranslations` from `next-intl/server`"}
]
},
{
"id": 5,
"name": "modal-import-and-no-raw-button",
"prompt": "add a \"Delete account\" button to src/components/Profile/Settings.tsx that pops a confirm dialog (\"are you sure? this cant be undone\"). on confirm it calls deleteAccount(). use a plain html button for the trigger and a basic radix dialog, im not sure what this repo prefers",
"expected_output": "Skill should refuse the raw <button> in favor of <Button> from @/components/ui/buttons/Button, and pick the high-level Modal default export from @/components/ui/dialog-modal rather than wiring up @/components/ui/dialog from scratch. Should mark the file 'use client' (interactivity) and use translations for the prompts.",
"files": [],
"assertions": [
{"text": "Output imports the default-export `Modal` from `@/components/ui/dialog-modal`"},
{"text": "Output does NOT import named primitives directly from `@/components/ui/dialog` or `@radix-ui/react-dialog`"},
{"text": "Trigger uses `<Button>` from `@/components/ui/buttons/Button` (NOT a raw `<button>` element)"},
{"text": "File begins with `'use client'` (needed for useState + handlers)"},
{"text": "All user-facing copy ('Delete account' label, 'are you sure?' warning, confirm/cancel) routed through `useTranslations` (no hard-coded English literals in JSX)"},
{"text": "notes.md explicitly notes the pushback on the user's 'plain html button' and 'basic radix dialog' framing"}
]
}
]
}
Loading
Loading