diff --git a/sx/sx/nav-data.sx b/sx/sx/nav-data.sx index 7bfbfe5..a6d2f5f 100644 --- a/sx/sx/nav-data.sx +++ b/sx/sx/nav-data.sx @@ -253,18 +253,14 @@ :summary "SX as its own compiler. OCaml as substrate (closest to CEK), Koka as alternative (compile-time linearity), ultimately self-hosting. One language, every target."))) (define reactive-islands-nav-items (list - (dict :label "Overview" :href "/sx/(geography.(reactive))" - :summary "Architecture, four levels (L0-L3), and current implementation status.") - (dict :label "Demo" :href "/sx/(geography.(reactive.demo))" - :summary "Live demonstration of signals, computed, effects, batch, and defisland — all transpiled from spec.") + (dict :label "Examples" :href "/sx/(geography.(reactive.examples))" + :summary "Live interactive islands — counter, temperature, stopwatch, lists, input binding, portals, error boundaries, stores, event bridge.") (dict :label "Event Bridge" :href "/sx/(geography.(reactive.event-bridge))" :summary "DOM events for htmx lake → island communication. Server-rendered buttons dispatch custom events that island effects listen for.") (dict :label "Named Stores" :href "/sx/(geography.(reactive.named-stores))" :summary "Page-level signal containers via def-store/use-store — persist across island destruction/recreation.") - (dict :label "Plan" :href "/sx/(geography.(reactive.plan))" - :summary "The full design document — rendering boundary, state flow, signal primitives, island lifecycle.") - (dict :label "Phase 2" :href "/sx/(geography.(reactive.phase2))" - :summary "Input binding, keyed lists, reactive class/style, refs, portals, error boundaries, suspense, transitions."))) + (dict :label "Marshes" :href "/sx/(geography.(reactive.marshes))" + :summary "Where reactivity and hypermedia interpenetrate — server writes to signals, reactive transforms, client state modifies hypermedia."))) (define bootstrappers-nav-items (list (dict :label "Overview" :href "/sx/(language.(bootstrapper))") diff --git a/sx/sx/reactive-islands/demo.sx b/sx/sx/reactive-islands/demo.sx index c92d8ea..b52abc2 100644 --- a/sx/sx/reactive-islands/demo.sx +++ b/sx/sx/reactive-islands/demo.sx @@ -1,13 +1,13 @@ ;; --------------------------------------------------------------------------- -;; Demo page — shows what's been implemented +;; Examples page — live interactive islands, one per section ;; --------------------------------------------------------------------------- (defcomp ~reactive-islands/demo/reactive-islands-demo-content () - (~docs/page :title "Reactive Islands Demo" + (~docs/page :title "Reactive Islands — Examples" - (~docs/section :title "What this demonstrates" :id "what" - (p (strong "These are live interactive islands") " — not static code snippets. Click the buttons. The signal runtime is defined in " (code "signals.sx") " (374 lines of s-expressions), then bootstrapped to JavaScript by " (code "bootstrap_js.py") ". No hand-written signal logic in JavaScript.") - (p "The transpiled " (code "sx-browser.js") " registers " (code "signal") ", " (code "deref") ", " (code "reset!") ", " (code "swap!") ", " (code "computed") ", " (code "effect") ", and " (code "batch") " as SX primitives — callable from " (code "defisland") " bodies defined in " (code ".sx") " files.")) + (~docs/section :title "Live interactive islands" :id "intro" + (p (strong "Every example below is a live interactive island") " — not a static code snippet. Click the buttons, type in the inputs. The signal runtime is defined in " (code "signals.sx") ", bootstrapped to JavaScript. No hand-written signal logic.") + (p "Each island uses " (code "defisland") " with signals (" (code "signal") ", " (code "deref") ", " (code "reset!") ", " (code "swap!") "), derived values (" (code "computed") "), side effects (" (code "effect") "), and batch updates (" (code "batch") ").")) (~docs/section :title "1. Signal + Computed + Effect" :id "demo-counter" (p "A signal holds a value. A computed derives from it. Click the buttons — the counter and doubled value update instantly, no server round-trip.") @@ -88,12 +88,18 @@ (~docs/code :code (highlight ";; Island A — creates/writes the store\n(defisland ~reactive-islands/demo/store-writer ()\n (let ((store (def-store \"theme\" (fn ()\n (dict \"color\" (signal \"violet\")\n \"dark\" (signal false))))))\n (select :bind (get store \"color\")\n (option :value \"violet\" \"Violet\")\n (option :value \"blue\" \"Blue\"))\n (input :type \"checkbox\" :bind (get store \"dark\"))))\n\n;; Island B — reads the same store, different island\n(defisland ~reactive-islands/demo/store-reader ()\n (let ((store (use-store \"theme\")))\n (div :class (str \"bg-\" (deref (get store \"color\")) \"-100\")\n \"Styled by signals from Island A\")))" "lisp")) (p "React equivalent: " (code "createContext") " + " (code "useContext") " or Redux/Zustand. Stores are simpler — just named dicts of signals at page scope. " (code "def-store") " creates once, " (code "use-store") " retrieves. Stores survive island disposal but clear on full page navigation.")) - (~docs/section :title "14. How defisland Works" :id "how-defisland" + (~docs/section :title "14. Event Bridge" :id "demo-event-bridge" + (p "Server-rendered content inside an island (an htmx \"lake\") can communicate with island signals via DOM custom events. Buttons with " (code "data-sx-emit") " dispatch events that island effects catch.") + (~reactive-islands/index/demo-event-bridge) + (~docs/code :code (highlight ";; Island listens for custom events from server-rendered content\n(defisland ~reactive-islands/demo/event-bridge ()\n (let ((messages (signal (list))))\n ;; Bridge: auto-listen for \"inbox:message\" events\n (bridge-event container \"inbox:message\" messages\n (fn (detail) (append (deref messages) (get detail \"text\"))))\n (div\n ;; Lake content (server-rendered) has data-sx-emit buttons\n (div :id \"lake\"\n :sx-get \"/my-content\"\n :sx-swap \"innerHTML\"\n :sx-trigger \"load\")\n ;; Island reads the signal reactively\n (ul (map (fn (msg) (li msg)) (deref messages))))))" "lisp")) + (p "The " (code "data-sx-emit") " attribute is processed by the client engine — it adds a click handler that dispatches a CustomEvent with the JSON from " (code "data-sx-emit-detail") ". The event bubbles up to the island container where " (code "bridge-event") " catches it.")) + + (~docs/section :title "15. How defisland Works" :id "how-defisland" (p (code "defisland") " creates a reactive component. Same calling convention as " (code "defcomp") " — keyword args, rest children — but with a reactive boundary. Inside an island, " (code "deref") " subscribes DOM nodes to signals.") (~docs/code :code (highlight ";; Definition — same syntax as defcomp\n(defisland ~reactive-islands/demo/counter (&key initial)\n (let ((count (signal (or initial 0))))\n (div\n (span (deref count)) ;; reactive text node\n (button :on-click (fn (e) (swap! count inc)) ;; event handler\n \"+\"))))\n\n;; Usage — same as any component\n(~reactive-islands/demo/counter :initial 42)\n\n;; Server-side rendering:\n;;