SPA nav improvements: scroll restoration, popstate, history spec

- boot.sx: popstate handler extracts scrollY from history state
- engine.sx: pass scroll position to handle-popstate
- boot-helpers.sx: scroll position tracking in navigation
- orchestration.sx: scroll state management for back/forward nav
- history.spec.js: new Playwright spec for history navigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 15:36:24 +00:00
parent bea8779aea
commit b6e144a6fd
5 changed files with 217 additions and 8 deletions

View File

@@ -527,6 +527,7 @@
(if
client-routed
(do
(save-scroll-position)
(browser-push-state (get live-info "url"))
(browser-scroll-to 0 0))
(do
@@ -1553,11 +1554,23 @@
(dom-dispatch el event-name detail))))))))
els))))
(define
save-scroll-position
:effects (io)
(fn
()
(let
((scrollY (host-get (dom-window) "scrollY")))
(browser-replace-state
(dict "scrollY" scrollY)
""
(browser-location-href)))))
(define
handle-popstate
:effects (mutation io)
(fn
((scrollY :as number))
(scrollY)
(let
((url (browser-location-href))
(boost-el (dom-query "[sx-boost]"))
@@ -1566,9 +1579,8 @@
boost-el
(let
((attr (dom-get-attr boost-el "sx-boost")))
(if (and attr (not (= attr "true"))) attr nil))
nil))
(target-sel (or target-sel "#main-panel"))
(if (and attr (not (= attr "true"))) attr "#sx-content"))
"#sx-content"))
(target (dom-query target-sel))
(pathname (url-pathname url)))
(when
@@ -1577,7 +1589,7 @@
(try-client-route pathname target-sel)
(browser-scroll-to 0 scrollY)
(let
((headers (build-request-headers target (loaded-component-names) _css-hash)))
((headers (build-request-headers target "GET" url)))
(fetch-and-restore target url headers scrollY)))))))
(define