(defisland ~layouts/header (&key path) (let ((families (list "violet" "rose" "blue" "emerald" "amber" "cyan" "red" "teal" "pink" "indigo")) (store (if (client?) (def-store "header-color" (fn () {:idx (signal 0) :shade (signal 500)})) nil)) (idx (if store (get store "idx") (signal 0))) (shade (if store (get store "shade") (signal 500))) (current-family (computed (fn () (nth families (mod (deref idx) (len families))))))) (div (~tw :tokens "block max-w-3xl mx-auto px-4 pt-8 pb-4 text-center") (a :href "/sx/" :sx-get "/sx/" :sx-target "#sx-content" :sx-select "#sx-content" :sx-swap "innerHTML" :sx-push-url "true" (~tw :tokens "block no-underline") (lake :id "logo" (span (~tw :tokens "block mb-2 text-violet-699 text-4xl font-bold font-mono") "()"))) (p (~tw :tokens "mb-1 text-stone-500 text-lg") "The framework-free " (span (~tw :tokens "font-bold") :style (str "color:" (colour (deref current-family) (deref shade)) ";" "cursor:pointer;transition:color 0.3s,font-weight 0.3s;") :on-click (fn (e) (batch (fn () (swap! idx inc) (reset! shade (+ 400 (* (mod (* (deref idx) 137) 5) 50)))))) "reactive") " hypermedium") (lake :id "copyright" (p (~tw :tokens "text-stone-400 text-xs") "© Giles Bradshaw 2026" (when path (span (~tw :tokens "text-stone-300 text-xs") :style "margin-left:0.5em;" (str "· " path)))))))) (defcomp ~layouts/nav-sibling-row (&key node siblings is-leaf level depth) :affinity :server (let* ((sibs (or siblings (list))) (count (len sibs)) (row-opacity (if (and level depth (> depth 0)) (+ (* (/ level depth) 0.75) 0.25) 1))) (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 (~tw :tokens "w-full max-w-3xl mx-auto px-4 py-2 grid grid-cols-3 items-center") :style (str "opacity:" row-opacity ";transition:opacity 0.3s;") (a :href (get prev-node "href") :sx-get (get prev-node "href") :sx-target "#sx-content" :sx-select "#sx-content" :sx-swap "innerHTML" :sx-push-url "true" (~tw :tokens "text-right min-w-0 truncate") :style (tw "text-stone-500 text-sm") (str "← " (get prev-node "label"))) (a :href (get node "href") :sx-get (get node "href") :sx-target "#sx-content" :sx-select "#sx-content" :sx-swap "innerHTML" :sx-push-url "true" (~tw :tokens "text-center min-w-0 truncate px-1") :style (if is-leaf (tw "text-violet-700 text-2xl font-bold") (tw "text-violet-700 text-lg font-semibold")) (get node "label")) (a :href (get next-node "href") :sx-get (get next-node "href") :sx-target "#sx-content" :sx-select "#sx-content" :sx-swap "innerHTML" :sx-push-url "true" (~tw :tokens "text-left min-w-0 truncate") :style (tw "text-stone-500 text-sm") (str (get next-node "label") " →"))))))) (defcomp ~layouts/nav-children (&key items) :affinity :server (div (~tw :tokens "max-w-3xl mx-auto px-4 py-3") (div (~tw :tokens "flex flex-wrap justify-center gap-2") (map (fn (item) (a :href (get item "href") :sx-get (get item "href") :sx-target "#sx-content" :sx-select "#sx-content" :sx-swap "innerHTML" :sx-push-url "true" (~tw :tokens "px-3 py-1.5 rounded border transition-colors") :style (tw "text-violet-700 text-sm border-violet-200") (get item "label"))) items)))) (defcomp ~layouts/doc (&key path &rest children) :affinity :server (let* ((nav-state (resolve-nav-path sx-nav-tree (or path "/"))) (trail (or (get nav-state "trail") (list))) (trail-len (len trail)) (depth (+ trail-len 1))) (<> (div :id "sx-nav" (~tw :tokens "mb-6") :sx-swap-oob "innerHTML" (div :id "logo-opacity" :style (str "opacity:" (+ (* (/ 1 depth) 0.75) 0.25) ";" "transition:opacity 0.3s;") (~layouts/header :path (or path "/"))) (map-indexed (fn (i crumb) (~layouts/nav-sibling-row :node (get crumb "node") :siblings (get crumb "siblings") :is-leaf (= i (- trail-len 1)) :level (+ i 2) :depth depth)) trail) (when (get nav-state "children") (~layouts/nav-children :items (get nav-state "children")))) (div :id "sx-content" (error-boundary children) (~tw/flush))))) (defcomp ~layouts/docs-layout-full () nil) (defcomp ~layouts/docs-layout-oob () nil) (defcomp ~layouts/docs-layout-mobile () nil) (defcomp ~layouts/standalone-docs-layout-full () nil) (defcomp ~layouts/standalone-docs-layout-oob (&key content) (~shared:layout/oob-sx :content content)) (defcomp ~layouts/standalone-docs-layout-mobile () nil)