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:
10
web/boot.sx
10
web/boot.sx
@@ -433,7 +433,15 @@
|
||||
(run-post-render-hooks)
|
||||
(flush-collected-styles)
|
||||
(set-timeout (fn () (process-elements nil)) 0)
|
||||
(dom-listen (dom-window) "popstate" (fn (e) (handle-popstate 0)))
|
||||
(dom-listen
|
||||
(dom-window)
|
||||
"popstate"
|
||||
(fn
|
||||
(e)
|
||||
(let
|
||||
((state (host-get e "state"))
|
||||
(scrollY (if state (or (dict-get state "scrollY") 0) 0)))
|
||||
(handle-popstate scrollY))))
|
||||
(dom-set-attr
|
||||
(host-get (dom-document) "documentElement")
|
||||
"data-sx-ready"
|
||||
|
||||
@@ -719,7 +719,9 @@
|
||||
hdr-replace
|
||||
(browser-replace-state hdr-replace)
|
||||
(and push-url (not (= push-url "false")))
|
||||
(browser-push-state (if (= push-url "true") url push-url))
|
||||
(do
|
||||
(save-scroll-position)
|
||||
(browser-push-state (if (= push-url "true") url push-url)))
|
||||
(and replace-url (not (= replace-url "false")))
|
||||
(browser-replace-state (if (= replace-url "true") url replace-url))))))
|
||||
|
||||
|
||||
@@ -501,7 +501,10 @@
|
||||
"#sx-content")))
|
||||
(if
|
||||
(try-client-route (url-pathname href) target-sel)
|
||||
(do (browser-push-state nil "" href) (browser-scroll-to 0 0))
|
||||
(do
|
||||
(save-scroll-position)
|
||||
(browser-push-state nil "" href)
|
||||
(browser-scroll-to 0 0))
|
||||
(do
|
||||
(log-info (str "sx:route server fetch " href))
|
||||
(dom-set-attr link "sx-get" href)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user