Event buffering during hydration gap

Clicks on island elements before hydration completes are captured
and replayed after boot finishes:

- shell.sx: inline script (capture phase) buffers clicks on
  [data-sx-island] elements that aren't hydrated yet into window._sxQ
- boot.sx: after hydration + process-elements, replays buffered clicks
  by calling target.click() on elements still connected to the DOM

This makes SSR islands feel interactive immediately — the user can
click a button while the SX kernel is still loading/hydrating, and
the action fires as soon as the handler is wired up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 14:45:04 +00:00
parent 759309c5c4
commit 1a3ee40e0d
3 changed files with 36 additions and 2 deletions

View File

@@ -492,7 +492,23 @@
(process-elements nil)
;; Wire up popstate for back/forward navigation
(dom-listen (dom-window) "popstate"
(fn (e) (handle-popstate 0))))))
(fn (e) (handle-popstate 0)))
;; Replay buffered clicks from hydration gap
(let ((queued (host-get (dom-window) "_sxQ")))
(when queued
(let ((arr (host-call (host-global "Array") "from" queued)))
(let ((n (host-get arr "length")))
(when (> n 0)
(log-info (str "replaying " n " buffered click(s)"))
(let loop ((i 0))
(when (< i n)
(let ((entry (host-call arr "at" i)))
(when entry
(let ((target (host-get entry "t")))
(when (and target (host-get target "isConnected"))
(host-call target "click")))))
(loop (+ i 1)))))))
(host-set! (dom-window) "_sxQ" nil))))))
;; --------------------------------------------------------------------------