Skip to content

Components in Svelte 5's own syntax: runes, snippets, event attributes - #231

Merged
xuelink merged 1 commit into
mainfrom
claude/svelte-5-runes
Sep 24, 2026
Merged

xuelink merged 1 commit into
mainfrom
claude/svelte-5-runes

Conversation

@xuelink

@xuelink xuelink commented Sep 24, 2026

Copy link
Copy Markdown
Member

Step 2 of the Svelte 5 move, after #230. Svelte's migrate() (what npx sv migrate svelte-5 runs) rewrote 76 of the 142 components; the other 66 had no props or reactivity to convert. The rest is what it could not do or got wrong:

  • Button: the external-link test landed before $props() (a ReferenceError at prerender) and clicks went through createBubbler. Props come first, the test is $derived, and onclick travels with the rest props; the one on:click on a Button became onclick.
  • AppPicker: the chosen app is $state.raw. Deep state returns a proxy that equals none of the apps, so the chosen chip lost its highlight. Guess-the-language rounds are raw too.
  • run() stopgaps replaced: SpeakButton and the say page use effects; the meaning quiz starts with one answer slot per round, so the server renders the same track as before.
  • Globe/mark container types, the onenter event type of the inview action, intended one-time reads of props marked, $app/state on the error page, and the unused NewsletterForm removed.

Blog posts and legal pages stay in the old syntax, which is what mdsvex writes; Svelte 5 runs both.

Checked

  • CI replayed in a clean copy under Node 22: 0 errors, 1371 pages.
  • Against the build of Svelte 5, with the Vite 8 toolchain it needs (supersedes #226) #230: every page has the same element tree, visible text and head; computed styles match on 16 page types at 1280 and 390 px.
  • In the browser: the compare picker (?vs=, clicks, chip highlight), FAQ, meaning quiz, guess the language, vocabulary test, word game, word list search and paging, say pages across client-side navigation, globe and mark. No console errors.

🤖 Generated with Claude Code

The follow-up to the Svelte 5 upgrade. Svelte's migrate() rewrote 76 of the
142 components (the other 66 had no props or reactivity to convert); the rest
of this commit is what it could not do, or got wrong:

- Button: migrate() put the external-link test before $props() — a
  ReferenceError at prerender — and forwarded clicks through createBubbler.
  Props are declared first now, the link test is $derived, and onclick
  arrives with the rest of the props; the one on:click on a Button became
  onclick.
- AppPicker: the chosen app is $state.raw. Deep state wraps the object in a
  proxy, which equals none of the apps the chips compare it with, and the
  chosen chip lost its ink. The guess-the-language rounds are raw too, being
  only ever replaced.
- run() stopgaps replaced: SpeakButton's audio check and the say page's
  sprite swap are effects; the meaning quiz starts with one slot per round,
  so the server renders the same track as before, and resets before render.
  The say page's sprite is a plain variable, as nothing renders from it.
- The globe and mark containers are typed as possibly unset, asserted where
  onMount uses them; the inview action's event is typed as onenter.
- Values taken once from props, as Svelte 4 did too, are marked as meant.
- The error page reads $app/state instead of the $app/stores store.
- NewsletterForm goes: nothing imported it.

The blog posts and legal pages stay in the old syntax; that is what mdsvex
writes, and Svelte 5 runs both.

Checked against the build of the upgrade commit: all 1371 pages have the same
element tree, text and head; computed styles match on 16 page types; in the
browser the compare picker, FAQ, quizzes, vocabulary test, word game, word
list search and paging, say pages across client navigation and the globe
all work, with no console errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@xuelink
xuelink merged commit 4f1cebf into main Sep 24, 2026
1 check passed
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