SX docs: configurable shell, SX-native event handlers, nav fixes
- Configurable page shell (~sx-page-shell kwargs + SX_SHELL app config) so each app controls its own assets — sx docs loads only sx-browser.js - SX-evaluated sx-on:* handlers (eval-expr instead of new Function) with DOM primitives registered in PRIMITIVES table - data-init boot mode for pure SX initialization scripts - Jiggle animation on links while fetching - Nav: 3-column grid for centered alignment, is-leaf sizing, fix map-indexed param order (index, item), guard mod-by-zero - Async route eval failure now falls back to server fetch instead of silently rendering nothing - Remove duplicate h1 title from ~doc-page - Re-bootstrap sx-ref.js + sx-browser.js Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
(defcomp ~sx-home-content ()
|
||||
(div :id "main-content" :class "max-w-3xl mx-auto px-4 py-6"
|
||||
(highlight "(defcomp ~sx-header ()
|
||||
(~doc-code :code (highlight "(defcomp ~sx-header ()
|
||||
(a :href \"/\"
|
||||
:sx-get \"/\" :sx-target \"#main-panel\"
|
||||
:sx-select \"#main-panel\"
|
||||
@@ -13,7 +13,7 @@
|
||||
(p :class \"text-lg text-stone-500 mb-1\"
|
||||
\"Framework free reactive hypermedia\")
|
||||
(p :class \"text-xs text-stone-400\"
|
||||
\"© Giles Bradshaw 2026\")))" "lisp")))
|
||||
\"© Giles Bradshaw 2026\")))" "lisp"))))
|
||||
|
||||
(defcomp ~docs-introduction-content ()
|
||||
(~doc-page :title "Introduction"
|
||||
|
||||
@@ -21,35 +21,41 @@
|
||||
(p :class "text-xs text-stone-400"
|
||||
"© Giles Bradshaw 2026")))
|
||||
|
||||
;; Current section with annotated prev/next siblings.
|
||||
;; Desktop: prev ← Current → next (horizontal)
|
||||
;; Mobile: stacked vertically
|
||||
(defcomp ~nav-sibling-row (&key node siblings)
|
||||
(let* ((idx (find-nav-index siblings node))
|
||||
(count (len siblings))
|
||||
(prev-idx (mod (+ (- idx 1) count) count))
|
||||
(next-idx (mod (+ idx 1) count))
|
||||
(prev-node (nth siblings prev-idx))
|
||||
(next-node (nth siblings next-idx)))
|
||||
(div :class "max-w-3xl mx-auto px-4 py-2 flex items-center justify-center gap-4"
|
||||
(a :href (get prev-node "href")
|
||||
:sx-get (get prev-node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class "text-sm text-stone-500 hover:text-violet-600"
|
||||
(str "← " (get prev-node "label")))
|
||||
(a :href (get node "href")
|
||||
:sx-get (get node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class "text-lg font-semibold text-violet-700 px-4"
|
||||
(get node "label"))
|
||||
(a :href (get next-node "href")
|
||||
:sx-get (get next-node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class "text-sm text-stone-500 hover:text-violet-600"
|
||||
(str (get next-node "label") " →")))))
|
||||
;; @css grid grid-cols-3
|
||||
|
||||
;; Current section with prev/next siblings.
|
||||
;; 3-column grid: prev is right-aligned, current centered, next left-aligned.
|
||||
;; Current page is larger in the leaf (bottom) row.
|
||||
(defcomp ~nav-sibling-row (&key node siblings is-leaf)
|
||||
(let* ((sibs (or siblings (list)))
|
||||
(count (len sibs)))
|
||||
(when (> count 0)
|
||||
(let* ((idx (find-nav-index sibs node))
|
||||
(prev-idx (mod (+ (- idx 1) count) count))
|
||||
(next-idx (mod (+ idx 1) count))
|
||||
(prev-node (nth sibs prev-idx))
|
||||
(next-node (nth sibs next-idx)))
|
||||
(div :class "max-w-3xl mx-auto px-4 py-2 grid grid-cols-3 items-center"
|
||||
(a :href (get prev-node "href")
|
||||
:sx-get (get prev-node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class "text-sm text-stone-500 hover:text-violet-600 text-right"
|
||||
(str "← " (get prev-node "label")))
|
||||
(a :href (get node "href")
|
||||
:sx-get (get node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class (if is-leaf
|
||||
"text-2xl font-bold text-violet-700 text-center px-4"
|
||||
"text-lg font-semibold text-violet-700 text-center px-4")
|
||||
(get node "label"))
|
||||
(a :href (get next-node "href")
|
||||
:sx-get (get next-node "href") :sx-target "#main-panel"
|
||||
:sx-select "#main-panel" :sx-swap "outerHTML"
|
||||
:sx-push-url "true"
|
||||
:class "text-sm text-stone-500 hover:text-violet-600 text-left"
|
||||
(str (get next-node "label") " →")))))))
|
||||
|
||||
;; Children links — shown as clearly clickable buttons.
|
||||
(defcomp ~nav-children (&key items)
|
||||
@@ -70,16 +76,20 @@
|
||||
;; ---------------------------------------------------------------------------
|
||||
|
||||
(defcomp ~sx-doc (&key path &rest children) :affinity :server
|
||||
(let ((nav-state (resolve-nav-path sx-nav-tree (or path "/"))))
|
||||
(let* ((nav-state (resolve-nav-path sx-nav-tree (or path "/")))
|
||||
(trail (or (get nav-state "trail") (list)))
|
||||
(trail-len (len trail)))
|
||||
(<>
|
||||
(div :id "sx-nav" :class "mb-6"
|
||||
(~sx-header)
|
||||
;; Sibling arrows for EVERY level in the trail
|
||||
(map (fn (crumb)
|
||||
;; Last row (leaf) gets is-leaf for larger current page title
|
||||
(map-indexed (fn (i crumb)
|
||||
(~nav-sibling-row
|
||||
:node (get crumb "node")
|
||||
:siblings (get crumb "siblings")))
|
||||
(get nav-state "trail"))
|
||||
:siblings (get crumb "siblings")
|
||||
:is-leaf (= i (- trail-len 1))))
|
||||
trail)
|
||||
;; Children as button links
|
||||
(when (get nav-state "children")
|
||||
(~nav-children :items (get nav-state "children"))))
|
||||
|
||||
Reference in New Issue
Block a user