refactor(web): Svelte 5 event-idiom modernization (on:/createEventDispatcher → event attrs + callback props)#90
Conversation
…attrs + callback props)
…preventDefault inlined)
…nt attrs + callback props
…> event attrs + callback props
… (created payload)
…wnModal to runes)
…d uidist (event idiom done)
📝 WalkthroughWalkthroughThe Svelte UI replaces deprecated event directives and dispatcher-based modal events with Svelte 5 event attributes and callback props. Validation now treats event-directive deprecations as errors, documentation records the migration, and the embedded UI bundle reference is refreshed. ChangesSvelte 5 event idiom migration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant VMDetail
participant SnapshotModal
User->>VMDetail: open snapshot modal
VMDetail->>SnapshotModal: pass oncreated and onclose callbacks
SnapshotModal->>VMDetail: return stopAfter payload after creation
VMDetail->>VMDetail: stop polling and navigate when stopAfter is set
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
docs/superpowers/specs/2026-07-19-svelte5-event-idiom-design.md (1)
26-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd a blank line before the table.
Markdown tables should be preceded by a blank line to ensure they render correctly across all Markdown parsers.
♻️ Proposed fix
#### 모달 ↔ 부모 매핑 (결합 단위) + | 모달 | 부모 | 콜백 props | |---|---|---|🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/superpowers/specs/2026-07-19-svelte5-event-idiom-design.md` around lines 26 - 28, Insert a blank line between the “모달 ↔ 부모 매핑 (결합 단위)” heading and the table that follows it, leaving the table content unchanged.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/superpowers/plans/2026-07-19-svelte5-event-idiom.md`:
- Around line 1-11: Translate the entire Markdown document into Korean,
including headings, explanatory text, goals, architecture, constraints, and task
instructions. Preserve all code identifiers, API paths, environment variables,
commands, file names, Svelte syntax, and checkbox formatting exactly as written.
---
Nitpick comments:
In `@docs/superpowers/specs/2026-07-19-svelte5-event-idiom-design.md`:
- Around line 26-28: Insert a blank line between the “모달 ↔ 부모 매핑 (결합 단위)”
heading and the table that follows it, leaving the table content unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3c69710e-90c5-4feb-8990-0acec486695c
📒 Files selected for processing (30)
cmd/goose-daemon/uidist/assets/index-CMV4roMS.jscmd/goose-daemon/uidist/assets/index-NUOirKmO.jscmd/goose-daemon/uidist/index.htmldocs/superpowers/plans/2026-07-19-svelte5-event-idiom.mddocs/superpowers/specs/2026-07-19-svelte5-event-idiom-design.mdweb/package.jsonweb/src/App.svelteweb/src/components/ActivityFeed.svelteweb/src/components/AddAgentModal.svelteweb/src/components/AuditLog.svelteweb/src/components/BroadcastModal.svelteweb/src/components/BuiltinsModal.svelteweb/src/components/ChangeRoleModal.svelteweb/src/components/CreateFlockModal.svelteweb/src/components/FlockDetail.svelteweb/src/components/Flocks.svelteweb/src/components/Login.svelteweb/src/components/ModelPicker.svelteweb/src/components/ProfileModal.svelteweb/src/components/RestoreModal.svelteweb/src/components/SendTaskModal.svelteweb/src/components/Settings.svelteweb/src/components/SnapshotModal.svelteweb/src/components/Snapshots.svelteweb/src/components/SpawnModal.svelteweb/src/components/System.svelteweb/src/components/SystemPromptModal.svelteweb/src/components/TaskPanel.svelteweb/src/components/VMDetail.svelteweb/src/components/VMList.svelte
| # Svelte 5 event-idiom modernization Implementation Plan | ||
|
|
||
| > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. | ||
|
|
||
| **Goal:** Replace the deprecated Svelte 4 event idiom across `web/src` — `on:event`→event attributes, event modifiers inlined, `createEventDispatcher`→callback props — bringing `event_directive_deprecated` warnings to zero, behavior-preserving. | ||
|
|
||
| **Architecture:** Hand-migrate, each file touched once. Two independent transform classes are per-file mechanical (DOM `on:`→`on`; inline the 17 removed event modifiers). The third (custom events→callback props) couples each modal with its parent, so tasks are grouped by parent-cluster. The existing `svelte-check` gate catches signature errors; a final task promotes `event_directive_deprecated` to a failing error and greps to prove `createEventDispatcher` is gone. | ||
|
|
||
| **Tech Stack:** Svelte 5.56.4, Vite 8, `svelte-check` (gate already present from #87). node_modules already installed. | ||
|
|
||
| ## Global Constraints |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Write documentation in Korean.
As per coding guidelines, all Markdown files (**/*.md) must be written in Korean while preserving code identifiers, API paths, environment variables, commands, and file names in their original form. This document is currently written entirely in English. Please translate the contents of this file into Korean.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/superpowers/plans/2026-07-19-svelte5-event-idiom.md` around lines 1 -
11, Translate the entire Markdown document into Korean, including headings,
explanatory text, goals, architecture, constraints, and task instructions.
Preserve all code identifiers, API paths, environment variables, commands, file
names, Svelte syntax, and checkbox formatting exactly as written.
Source: Coding guidelines
Summary
Completes the Svelte 5 migration started in #87 (core runes) by modernizing the event idioms that #87 scoped out. Removes all deprecated Svelte-4 event syntax so the
svelte-checkgate can enforce the new idiom going forward. Behavior-preserving — no functional change.Three transform classes across 24
.sveltecomponents:on:xxx→onxxxevent attributes (handler bodies byte-identical).on:click|self={h}→onclick={(e) => e.target === e.currentTarget && h()}on:submit|preventDefault={submit}→onsubmit={(e) => { e.preventDefault(); submit() }}createEventDispatcher→ callback props (11 modals + their parents): childdispatch('close')→let { onclose } = $props(); onclose?.(); parent<Modal on:close={h}>→<Modal onclose={h}>.Notable specifics:
{ stopAfter }payload: the one detail-carrying event.oncreated?.({ stopAfter })passes the object as the first positional arg;VMDetail.onSnapshotCreated(payload)now readspayload.stopAfter(the oldCustomEvent.detailwrapper is gone).$props()for its callbacks flips it to runes mode, so its reactive locals (profiles,selected,busy,result) became$state().Gate
web/package.json'scheckscript now promotesevent_directive_deprecatedto an error (alongside the existingnon_reactive_update:error), so any regression to the oldon:idiom fails the build.createEventDispatcheremits no svelte-check warning, so its removal is enforced by grep-assert (0 occurrences tree-wide).Verification
npm run check(tightened gate): 0 errors, 10 benignstate_referenced_locallywarnings (pre-existing from refactor(web): migrate operator UI to Svelte 5 runes (core, behavior-preserving) #87).npx vite build+go build ./cmd/goose-daemon: pass.uidistrebuilt + committed (//go:embed).on:directives, 0createEventDispatcher, 0dispatch(, 0.detail; exactly 16 stricte.target === e.currentTargetbackdrops.preventDefault(no reload), backdrop|self(child-click no-close / self-click close), Escape, Cancel, callback-prop end-to-end unmount,$staterender — all pass; 0 Svelte runtime errors.Domain-callback success round-trips (actual spawn/snapshot/flock actions, incl. the
{stopAfter}VM-destroy branch) require a live daemon and were not exercised end-to-end this session; they're covered by the tightened static gate + the proven callback-firing mechanism + code review of the payload path. A live-daemon click-through at next test-host deploy is recommended as belt-and-suspenders.Method
Hand-migrated (consistent with #87), executed via subagent-driven development: fresh implementer + task-scoped review per component cluster, then a whole-branch review. All per-task reviews and the final holistic review came back clean.
Summary by CodeRabbit
Improvements
Documentation