Marsh demo: video embed with reactive+hypermedia interplay
- ~video-player defisland persists across SPA navigations (morph-safe) - Clicking "reactive" cycles colour (signal) + fetches random YouTube video (sx-get) - sx-trigger="fetch-video" + dom-first-child check: video keeps playing on repeat clicks - Close button (x) clears video via /api/clear-video hypermedia endpoint - Autoplay+mute removes YouTube's red play button overlay - Header restructured: logo in anchor, tagline outside (no accidental navigation) - Flex centering on video container Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,18 +21,18 @@
|
||||
(shade (signal 500))
|
||||
(current-family (computed (fn ()
|
||||
(nth families (mod (deref idx) (len families)))))))
|
||||
(a :href "/"
|
||||
:sx-get "/" :sx-target "#main-panel" :sx-select "#main-panel"
|
||||
:sx-swap "outerHTML" :sx-push-url "true"
|
||||
:style (str (display "block") (max-w (get cssx-max-widths "3xl"))
|
||||
(mx-auto) (px 4) (pt 8) (pb 4) (align "center")
|
||||
(decoration "none"))
|
||||
;; Lake: server can update the logo text
|
||||
(lake :id "logo"
|
||||
(span :style (str (display "block") (mb 2)
|
||||
(cssx (:text (colour "violet" 699) (size "4xl") (weight "bold") (family "mono"))))
|
||||
"(<sx>)"))
|
||||
;; Reactive: colour-cycling "reactive" word (signal-bound, NOT in a lake)
|
||||
(div :style (str (display "block") (max-w (get cssx-max-widths "3xl"))
|
||||
(mx-auto) (px 4) (pt 8) (pb 4) (align "center"))
|
||||
;; Logo — only this navigates home
|
||||
(a :href "/"
|
||||
:sx-get "/" :sx-target "#main-panel" :sx-select "#main-panel"
|
||||
:sx-swap "outerHTML" :sx-push-url "true"
|
||||
:style (str (display "block") (decoration "none"))
|
||||
(lake :id "logo"
|
||||
(span :style (str (display "block") (mb 2)
|
||||
(cssx (:text (colour "violet" 699) (size "4xl") (weight "bold") (family "mono"))))
|
||||
"(<sx>)")))
|
||||
;; Tagline — NOT in anchor. Clicking "reactive" cycles colour + fetches video.
|
||||
(p :style (str (mb 1) (cssx (:text (colour "stone" 500) (size "lg"))))
|
||||
"Framework free "
|
||||
(span
|
||||
@@ -42,12 +42,18 @@
|
||||
:on-click (fn (e)
|
||||
(batch (fn ()
|
||||
(swap! idx inc)
|
||||
(reset! shade (+ 400 (* (mod (* (deref idx) 137) 5) 50))))))
|
||||
(reset! shade (+ 400 (* (mod (* (deref idx) 137) 5) 50)))))
|
||||
;; Only fetch video if none loaded (marsh: reactive + conditional hypermedia)
|
||||
(let ((embed (dom-query-by-id "video-embed")))
|
||||
(when (not (dom-first-child embed))
|
||||
(dom-dispatch (get e "currentTarget") "fetch-video" (dict)))))
|
||||
:sx-get "/api/random-video"
|
||||
:sx-target "#video-embed"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-trigger "fetch-video"
|
||||
"reactive")
|
||||
" hypermedia")
|
||||
;; Lake: server morphs this on every navigation — the path updates
|
||||
;; while the reactive colour above persists. Visible proof that
|
||||
;; server content flows through the island without disturbing signals.
|
||||
;; Lake: server morphs copyright on navigation without disturbing signals.
|
||||
(lake :id "copyright"
|
||||
(p :style (cssx (:text (colour "stone" 400) (size "xs")))
|
||||
"© Giles Bradshaw 2026"
|
||||
@@ -56,6 +62,14 @@
|
||||
"margin-left:0.5em;")
|
||||
(str "· " path))))))))
|
||||
|
||||
;; Video player island — defisland so the morph algorithm preserves it across
|
||||
;; navigations. Content swapped in via sx-get from the reactive word click.
|
||||
;; Empty initially (zero height). Iframe provides height when loaded.
|
||||
(defisland ~video-player ()
|
||||
(div :style "display:flex;justify-content:center;"
|
||||
(div :id "video-embed"
|
||||
:style "position:relative;width:66%;max-width:20rem;")))
|
||||
|
||||
;; @css grid grid-cols-3
|
||||
|
||||
;; Current section with prev/next siblings.
|
||||
@@ -134,6 +148,10 @@
|
||||
:style (str "opacity:" (+ (* (/ 1 depth) 0.75) 0.25) ";"
|
||||
"transition:opacity 0.3s;")
|
||||
(~sx-header :path (or path "/")))
|
||||
;; Video island — preserved across navigation morphs (like ~sx-header).
|
||||
;; Outside logo-opacity so it doesn't fade.
|
||||
;; Marsh demo: reactive click triggers hypermedia fetch, result lands here.
|
||||
(~video-player)
|
||||
;; Sibling arrows for EVERY level in the trail
|
||||
;; Trail row i is level (i+2) of depth — opacity = (i+2)/depth
|
||||
;; Last row (leaf) gets is-leaf for larger current page title
|
||||
|
||||
Reference in New Issue
Block a user