Skip to content

refactor(patterns): finish DemoSection framework-split migration and drop legacy fallback#172

Merged
masuP9 merged 6 commits into
mainfrom
refactor/demo-section-split-remaining
May 11, 2026
Merged

refactor(patterns): finish DemoSection framework-split migration and drop legacy fallback#172
masuP9 merged 6 commits into
mainfrom
refactor/demo-section-split-remaining

Conversation

@masuP9
Copy link
Copy Markdown
Owner

@masuP9 masuP9 commented May 11, 2026

Summary

PR #169 と PR #171 のフォローアップ最終回。残り 16 pattern を分割し、dispatcher の legacy fallback を撤去、docs を確定形に更新する。

これで 32/32 pattern が framework 別 4 ファイル形式に統一され、DemoSection.astro (legacy) はリポジトリから完全に消える。

変更内容

種別 件数
新規 DemoSection.{react,vue,svelte,web-component}.astro 64 (16 × 4)
削除 legacy DemoSection.astro 16
pages dispatcher 簡略化 (en/ja) 2
全 framework 別ファイルから framework?: Framework prop 削除 128 (sed 一括)
docs 確定化 (CLAUDE.md / .internal × 3 / CONTRIBUTING.md) 5

合計: 160 ファイル変更、+3742 / -2991

移行 pattern (16)

  • (alias): button / link / meter / spinbutton / switch / toggle-button / tooltip
  • : alert-dialog / breadcrumb / carousel / feed / landmarks / window-splitter
  • : data-grid / dialog / grid

固有処理 (plan の carry-over checklist 通り)

  • dialog: hydration directive (React/Vue client:only, Svelte client:load + contentHtml prop) を各 framework ファイルで legacy と完全一致
  • feed: locale === 'ja'FeedDemoJa / FeedDemo を切り替え (Astro.url.pathname 判定から locale prop へ統一)
  • carousel: import.meta.env.BASE_URL を 4 file 全てに残す (data ファイルには逃さない)
  • grid / data-grid: renderCell 関数は web-component.astro のみ
  • breadcrumb: 共通 data (basicItems / longPathItems) は短いので各 file にインラインで持つ (*-demo-data.ts は作らない)

dispatcher 簡略化

```ts
// Before
const newDemoLoader = frameworkDemoModules[framework][newPath];
const legacyDemoLoader = demoModules[`/src/patterns/${pattern}/DemoSection.astro`];
const DemoSection = newDemoLoader
? ((await newDemoLoader()).default as any)
: ((await legacyDemoLoader?.())?.default as any);

// After
const demoLoaderPath = `/src/patterns/${pattern}/DemoSection.${frameworkDemoKey[framework]}.astro`;
const demoLoader = frameworkDemoModules[framework][demoLoaderPath];
if (!demoLoader) {
throw new Error(`DemoSection not found: ${demoLoaderPath}`);
}
const DemoSection = (await demoLoader()).default as any;
```

getStaticPaths が valid な (pattern, framework) のみ生成するので、loader 欠落は実装ミスを示す build-time invariant となる。

検証

```bash

全数 probe: 32 pattern × 4 framework × 2 locale = 256 ページ

bad=0; ok=0
for d in src/patterns/*/; do
p=$(basename "$d")
for fw in react vue svelte astro; do
for prefix in "" "ja/"; do
c=$(curl -s -o /dev/null -w '%{http_code}' "http://localhost:4336/apg-patterns-examples/${prefix}patterns/$p/$fw/")
[ "$c" != "200" ] && { echo "BAD ${prefix}$p/$fw=$c"; bad=$((bad+1)); } || ok=$((ok+1))
done
done
done
echo "OK=$ok BAD=$bad / total=$((ok+bad))"
```

結果:
```
BAD alert/vue=500, ja/alert/vue=500, checkbox/vue=500, ja/checkbox/vue=500,
BAD combobox/vue=500, ja/combobox/vue=500, disclosure/vue=500, ja/disclosure/vue=500,
BAD menu-button/vue=500, ja/menu-button/vue=500, menubar/vue=500, ja/menubar/vue=500,
BAD slider-multithumb/vue=500, ja/slider-multithumb/vue=500, slider/vue=500, ja/slider/vue=500,
BAD toolbar/vue=500, ja/toolbar/vue=500
OK=238 BAD=18 / total=256
```

BAD 18 はすべて Issue #170 関連の既知 Vue ページ regression (9 pattern × 2 locale)。新規回帰 0 件

  • npm run lint: 0 errors / 0 warnings / 27 hints (PR-A から不変)
  • npm run build: success (553 pages built)
  • git ls-files 'src/patterns/*/DemoSection.astro' | wc -l: 0 (legacy 完全撤去)
  • find src/patterns -name '*-demo-data.ts' | wc -l: 7 (PR-A 由来、PR-B では追加なし)

関連

Test plan

🤖 Generated with Claude Code

masuP9 and others added 5 commits May 11, 2026 20:04
…fic files

Migrate the alias-style patterns (button, link, meter, spinbutton, switch,
toggle-button, tooltip) — those whose framework branches are mostly just
component invocations with little ceremony — to the framework-split format.
No shared demo data is extracted; each pattern's per-framework file just
calls its respective component.

Verified: 7 patterns × 4 frameworks = 28 pages return 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… files

Migrate alert-dialog, breadcrumb, carousel, feed, landmarks, and
window-splitter to the framework-split format. Per-pattern notes:

- breadcrumb: \`basicItems\` / \`longPathItems\` (~10 line each) are
  duplicated across the four files. Below the 8-line threshold for
  data extraction in spirit but moreover the items are short literal
  arrays that read cleanly inline; no \`*-demo-data.ts\` is added.
- carousel: \`import.meta.env.BASE_URL\` reference is kept in all four
  files (not extracted to a data module, per the plan).
- feed: each framework file picks \`FeedDemoJa\` / \`FeedDemo\` from the
  \`locale\` prop, replacing the prior \`Astro.url.pathname\` check.
- alert-dialog: React/Vue/Svelte each delegate to their wrapper Demo
  component with \`client:only\`; only the Astro Web Component file
  contains the inline AlertDialog markup.
- landmarks / window-splitter: straightforward delegation to wrapper Demo
  components.

Verified: 6 patterns × 4 frameworks × 2 locales = 48 pages return 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…) into framework files

- data-grid: React/Vue/Svelte each delegate to their wrapper DataGridDemo
  component with \`client:load\`; the Astro Web Component file contains
  the inline columns/rows data and full \`<DataGrid>\` invocation. Data
  is not extracted to a \`*-demo-data.ts\` because only the Astro variant
  uses it (per the migration rules for renderCell-bearing patterns).
- dialog: hydration directives are preserved per framework — React/Vue
  use \`client:only\`, Svelte uses \`client:load\` with \`contentHtml\` prop
  (slots cannot cross islands), Astro renders the dialog SSR. Each
  per-framework file holds the directive verbatim.
- grid: same shape as data-grid — Astro Web Component file owns columns,
  rows, and \`renderCell\` function; the React/Vue/Svelte files delegate.

Verified: 3 patterns × 4 frameworks × 2 locales = 24 pages return 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After all 32 patterns are migrated to the framework-split format, the
legacy unified \`DemoSection.astro\` is gone from the repo. Remove the
dispatcher's fallback path:

- Drop the \`demoModules\` glob for \`/src/patterns/*/DemoSection.astro\`
- Replace the new-then-legacy ternary with a single lookup that throws
  if the framework-specific file is missing (build-time invariant: the
  \`getStaticPaths\` only produces valid (pattern, framework) pairs, so
  a missing loader means an implementation mistake)
- Remove the now-unused \`framework\` prop from all per-framework
  DemoSection files (Astro.props receives only \`locale\`)
- Simplify the page invocation from
  \`{DemoSection && <DemoSection framework={framework} locale={locale} />}\`
  to \`<DemoSection locale={locale} />\`

Applied with a bulk sed across the 128 \`DemoSection.{react,vue,svelte,
web-component}.astro\` files for the prop removal.

Verified:
- 238/256 pages return 200 in dev (the 18 BAD are all Issue #170 known-
  failing Vue pages; no new regressions)
- npm run lint: 0 errors
- npm run build: success (553 pages)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After PR-B completes the migration of all 32 patterns, the legacy unified
\`DemoSection.astro\` is gone. Update CLAUDE.md, CONTRIBUTING.md, and the
.internal docs to describe the new convention as the canonical format
rather than as a transitional state:

- Directory listing examples show 4 framework-specific files and the
  optional \`{pattern}-demo-data.ts\`
- Architecture description drops the legacy fallback note
- Pattern planning checklist enumerates the 4 DemoSection files
- New file detection command (\`ls -la DemoSection.{react,vue,svelte,
  web-component}.astro\`) replaces the single \`DemoSection.astro\` check

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 11, 2026

Deploying apg-patterns-examples with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8223e47
Status: ✅  Deploy successful!
Preview URL: https://b0a4a850.apg-patterns-examples.pages.dev
Branch Preview URL: https://refactor-demo-section-split-2kyd.apg-patterns-examples.pages.dev

View logs

The sed-based bulk removal of the \`framework\` prop in the previous commit
left some files in shapes prettier wanted reformatted (line wrapping
around the now-leaner Props interface, blank lines, etc.). Run
\`npm run format:prettier --write\` to normalize them.

No semantic changes. CI's \`format\` job now passes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@masuP9 masuP9 merged commit c9edef7 into main May 11, 2026
17 checks passed
@masuP9 masuP9 deleted the refactor/demo-section-split-remaining branch May 11, 2026 17:10
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