Add Specs section, Reflexive Web essay, fix highlight and dev caching
- Fix highlight() returning SxExpr so syntax-highlighted code renders as DOM elements instead of leaking SX source text into the page - Add Specs section that reads and displays canonical SX spec files from shared/sx/ref/ with syntax highlighting - Add "The Reflexive Web" essay on SX becoming a complete LISP with AI as native participant - Change logo from (<x>) to (<sx>) everywhere - Unify all backgrounds to bg-stone-100, center code blocks - Skip component/style cookie cache in dev mode so .sx edits are visible immediately on refresh without clearing localStorage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,24 +2,24 @@
|
||||
|
||||
(defcomp ~example-card (&key title description &rest children)
|
||||
(div :class "border border-stone-200 rounded-lg overflow-hidden"
|
||||
(div :class "bg-stone-50 px-4 py-3 border-b border-stone-200"
|
||||
(div :class "bg-stone-100 px-4 py-3 border-b border-stone-200"
|
||||
(h3 :class "font-semibold text-stone-800" title)
|
||||
(when description
|
||||
(p :class "text-sm text-stone-500 mt-1" description)))
|
||||
(div :class "p-4" children)))
|
||||
|
||||
(defcomp ~example-demo (&key &rest children)
|
||||
(div :class "border border-dashed border-stone-300 rounded p-4 bg-white" children))
|
||||
(div :class "border border-dashed border-stone-300 rounded p-4 bg-stone-100" children))
|
||||
|
||||
(defcomp ~example-source (&key code)
|
||||
(div :class "bg-stone-50 border border-stone-200 rounded p-4 mt-3 overflow-x-auto"
|
||||
(pre :class "text-sm" (code code))))
|
||||
(div :class "bg-stone-100 rounded p-5 mt-3 mx-auto max-w-3xl"
|
||||
(pre :class "text-sm leading-relaxed whitespace-pre-wrap break-words" (code code))))
|
||||
|
||||
;; --- Click to load demo ---
|
||||
|
||||
(defcomp ~click-to-load-demo ()
|
||||
(div :class "space-y-4"
|
||||
(div :id "click-result" :class "p-4 rounded bg-stone-50 text-stone-500 text-center"
|
||||
(div :id "click-result" :class "p-4 rounded bg-stone-100 text-stone-500 text-center"
|
||||
"Click the button to load content.")
|
||||
(button
|
||||
:sx-get "/examples/api/click"
|
||||
@@ -50,7 +50,7 @@
|
||||
(button :type "submit"
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Submit"))
|
||||
(div :id "form-result" :class "p-3 rounded bg-stone-50 text-stone-500 text-sm text-center"
|
||||
(div :id "form-result" :class "p-3 rounded bg-stone-100 text-stone-500 text-sm text-center"
|
||||
"Submit the form to see the result.")))
|
||||
|
||||
(defcomp ~form-result (&key name)
|
||||
@@ -66,7 +66,7 @@
|
||||
:sx-get "/examples/api/poll"
|
||||
:sx-trigger "load, every 2s"
|
||||
:sx-swap "innerHTML"
|
||||
:class "p-4 rounded border border-stone-200 bg-white text-center font-mono"
|
||||
:class "p-4 rounded border border-stone-200 bg-stone-100 text-center font-mono"
|
||||
"Loading...")))
|
||||
|
||||
(defcomp ~poll-result (&key time count)
|
||||
@@ -145,10 +145,10 @@
|
||||
(defcomp ~oob-demo ()
|
||||
(div :class "space-y-4"
|
||||
(div :class "grid grid-cols-2 gap-4"
|
||||
(div :id "oob-box-a" :class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
(div :id "oob-box-a" :class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-500" "Box A")
|
||||
(p :class "text-sm text-stone-400" "Waiting..."))
|
||||
(div :id "oob-box-b" :class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
(div :id "oob-box-b" :class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-500" "Box B")
|
||||
(p :class "text-sm text-stone-400" "Waiting...")))
|
||||
(button
|
||||
@@ -167,7 +167,7 @@
|
||||
:sx-get "/examples/api/lazy"
|
||||
:sx-trigger "load"
|
||||
:sx-swap "innerHTML"
|
||||
:class "p-6 rounded border border-stone-200 bg-stone-50 text-center"
|
||||
:class "p-6 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(div :class "animate-pulse space-y-2"
|
||||
(div :class "h-4 bg-stone-200 rounded w-3/4 mx-auto")
|
||||
(div :class "h-4 bg-stone-200 rounded w-1/2 mx-auto")))))
|
||||
@@ -328,7 +328,7 @@
|
||||
(p :class "text-sm text-stone-400" "Messages will appear here."))))
|
||||
|
||||
(defcomp ~reset-message (&key message time)
|
||||
(div :class "px-3 py-2 bg-stone-50 rounded text-sm text-stone-700"
|
||||
(div :class "px-3 py-2 bg-stone-100 rounded text-sm text-stone-700"
|
||||
(str "[" time "] " message)))
|
||||
|
||||
;; --- Edit row demo ---
|
||||
@@ -488,7 +488,7 @@
|
||||
:sx-swap "innerHTML"
|
||||
:class "px-3 py-1.5 bg-stone-600 text-white rounded text-sm hover:bg-stone-700"
|
||||
"Full Dashboard"))
|
||||
(div :id "filter-target" :class "border border-stone-200 rounded p-4 bg-white"
|
||||
(div :id "filter-target" :class "border border-stone-200 rounded p-4 bg-stone-100"
|
||||
(p :class "text-sm text-stone-400" "Click a button to load content."))))
|
||||
|
||||
;; --- Tabs demo ---
|
||||
@@ -525,7 +525,7 @@
|
||||
:sx-swap "innerHTML"
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Load with animation")
|
||||
(div :id "anim-target" :class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
(div :id "anim-target" :class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-400" "Content will fade in here."))))
|
||||
|
||||
(defcomp ~anim-result (&key color time)
|
||||
@@ -552,7 +552,7 @@
|
||||
:sx-get "/examples/api/dialog/close"
|
||||
:sx-target "#dialog-container"
|
||||
:sx-swap "innerHTML")
|
||||
(div :class "relative bg-white rounded-lg shadow-xl p-6 max-w-md w-full mx-4 space-y-4"
|
||||
(div :class "relative bg-stone-100 rounded-lg shadow-xl p-6 max-w-md w-full mx-4 space-y-4"
|
||||
(h3 :class "text-lg font-semibold text-stone-800" title)
|
||||
(p :class "text-stone-600" message)
|
||||
(div :class "flex justify-end gap-2"
|
||||
@@ -573,23 +573,23 @@
|
||||
|
||||
(defcomp ~keyboard-shortcuts-demo ()
|
||||
(div :class "space-y-4"
|
||||
(div :class "p-4 rounded border border-stone-200 bg-stone-50"
|
||||
(div :class "p-4 rounded border border-stone-200 bg-stone-100"
|
||||
(p :class "text-sm text-stone-600 font-medium mb-2" "Keyboard shortcuts:")
|
||||
(div :class "flex gap-4"
|
||||
(div :class "flex items-center gap-1"
|
||||
(kbd :class "px-2 py-0.5 bg-white border border-stone-300 rounded text-xs font-mono" "s")
|
||||
(kbd :class "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono" "s")
|
||||
(span :class "text-sm text-stone-500" "Search"))
|
||||
(div :class "flex items-center gap-1"
|
||||
(kbd :class "px-2 py-0.5 bg-white border border-stone-300 rounded text-xs font-mono" "n")
|
||||
(kbd :class "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono" "n")
|
||||
(span :class "text-sm text-stone-500" "New item"))
|
||||
(div :class "flex items-center gap-1"
|
||||
(kbd :class "px-2 py-0.5 bg-white border border-stone-300 rounded text-xs font-mono" "h")
|
||||
(kbd :class "px-2 py-0.5 bg-stone-100 border border-stone-300 rounded text-xs font-mono" "h")
|
||||
(span :class "text-sm text-stone-500" "Help"))))
|
||||
(div :id "kbd-target"
|
||||
:sx-get "/examples/api/keyboard?key=s"
|
||||
:sx-trigger "keyup[key=='s'&&!event.target.matches('input,textarea')] from:body"
|
||||
:sx-swap "innerHTML"
|
||||
:class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
:class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-400 text-sm" "Press a shortcut key..."))
|
||||
(div :sx-get "/examples/api/keyboard?key=n"
|
||||
:sx-trigger "keyup[key=='n'&&!event.target.matches('input,textarea')] from:body"
|
||||
@@ -675,7 +675,7 @@
|
||||
(button :type "submit"
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Submit as JSON"))
|
||||
(div :id "json-result" :class "p-3 rounded bg-stone-50 text-stone-500 text-sm"
|
||||
(div :id "json-result" :class "p-3 rounded bg-stone-100 text-stone-500 text-sm"
|
||||
"Submit the form to see the server echo the parsed JSON.")))
|
||||
|
||||
(defcomp ~json-result (&key body content-type)
|
||||
@@ -697,7 +697,7 @@
|
||||
:sx-vals "{\"source\": \"button\", \"version\": \"2.0\"}"
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Send with vals")
|
||||
(div :id "vals-result" :class "p-3 rounded bg-stone-50 text-sm text-stone-400"
|
||||
(div :id "vals-result" :class "p-3 rounded bg-stone-100 text-sm text-stone-400"
|
||||
"Click to see server-received values."))
|
||||
(div :class "space-y-2"
|
||||
(h4 :class "text-sm font-semibold text-stone-700" "sx-headers — send custom headers")
|
||||
@@ -708,7 +708,7 @@
|
||||
:sx-headers {:X-Custom-Token "abc123" :X-Request-Source "demo"}
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Send with headers")
|
||||
(div :id "headers-result" :class "p-3 rounded bg-stone-50 text-sm text-stone-400"
|
||||
(div :id "headers-result" :class "p-3 rounded bg-stone-100 text-sm text-stone-400"
|
||||
"Click to see server-received headers."))))
|
||||
|
||||
(defcomp ~echo-result (&key label items)
|
||||
@@ -729,7 +729,7 @@
|
||||
:class "sx-loading-btn px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm flex items-center gap-2"
|
||||
(span :class "sx-spinner w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin")
|
||||
(span "Load slow endpoint"))
|
||||
(div :id "loading-result" :class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
(div :id "loading-result" :class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-400 text-sm" "Click the button — it takes 2 seconds."))))
|
||||
|
||||
(defcomp ~loading-result (&key time)
|
||||
@@ -749,7 +749,7 @@
|
||||
:sx-sync "replace"
|
||||
:placeholder "Type to search (random delay 0.5-2s)..."
|
||||
:class "w-full px-3 py-2 border border-stone-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-violet-500")
|
||||
(div :id "sync-result" :class "p-4 rounded border border-stone-200 bg-white"
|
||||
(div :id "sync-result" :class "p-4 rounded border border-stone-200 bg-stone-100"
|
||||
(p :class "text-sm text-stone-400" "Type to trigger requests — stale ones get aborted."))))
|
||||
|
||||
(defcomp ~sync-result (&key query delay)
|
||||
@@ -768,7 +768,7 @@
|
||||
:sx-retry "exponential:1000:8000"
|
||||
:class "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700 transition-colors text-sm"
|
||||
"Call flaky endpoint")
|
||||
(div :id "retry-result" :class "p-4 rounded border border-stone-200 bg-white text-center"
|
||||
(div :id "retry-result" :class "p-4 rounded border border-stone-200 bg-stone-100 text-center"
|
||||
(p :class "text-stone-400 text-sm" "Endpoint fails twice, succeeds on 3rd attempt."))))
|
||||
|
||||
(defcomp ~retry-result (&key attempt message)
|
||||
|
||||
Reference in New Issue
Block a user