Skip to content

Commit d407967

Browse files
Merge pull request #46 from ClojureCivitas/sandwich
finalizing the sandwich
2 parents a518913 + 1265eae commit d407967

File tree

4 files changed

+125
-35
lines changed

4 files changed

+125
-35
lines changed

src/scicloj/clay/uncompiled.cljs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
(ns scicloj.clay.uncompiled
2-
(:require [reagent.core :as r]
3-
[reagent.dom :as rdom]))
2+
(:require [reagent.dom :as rdom]))
43

54
(rdom/render
6-
[:div "hello from Scittle"]
5+
[:div "Hello from a ClojureScript file (uncompiled.cljs)"]
76
(js/document.getElementById "app"))

src/scicloj/clay/uncompiled.jpg

93.1 KB
Loading

src/scicloj/clay/uncompiled2.cljs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
(ns scicloj.clay.uncompiled2
2+
(:require [reagent.core :as r]
3+
[reagent.dom :as rdom]))
4+
5+
(defonce app-state
6+
(r/atom {:style "scrambled"
7+
:eggs 2}))
8+
9+
(defn cycle-style []
10+
(swap! app-state update :style
11+
{"scrambled" "fried"
12+
"fried" "poached"
13+
"poached" "scrambled"}))
14+
15+
(defn add-egg []
16+
(swap! app-state update :eggs inc))
17+
18+
(defn remove-egg []
19+
(swap! app-state update :eggs #(max 1 (dec %))))
20+
21+
(defn breakfast-order []
22+
[:div.card.border-primary.mb-3 {:style {:max-width "30rem"}}
23+
[:div.card-header "Breakfast Order"]
24+
[:div.card-body
25+
[:div.mb-3
26+
[:label.form-label "Style: "
27+
[:strong (:style @app-state)]]
28+
[:div.d-grid.gap-2
29+
[:button.btn.btn-primary
30+
{:onClick cycle-style}
31+
"Change Style"]]]
32+
[:div.mb-3
33+
[:div
34+
[:label.form-label "Eggs:"]
35+
[:div.d-block.mb-2 (:eggs @app-state)]]
36+
[:div.btn-group
37+
[:button.btn.btn-secondary
38+
{:onClick remove-egg
39+
:disabled (= 1 (:eggs @app-state))}
40+
""]
41+
[:button.btn.btn-secondary
42+
{:onClick add-egg}
43+
"+"]]]
44+
[:div.text-muted
45+
(case (:style @app-state)
46+
"poached" "Water added for poaching..."
47+
"fried" "Turn n burn!"
48+
"scrambled" "Whisking away...")]]])
49+
50+
(rdom/render
51+
[breakfast-order]
52+
(js/document.getElementById "app2"))

src/scicloj/clay/uncompiled_clojurescript.clj

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
:quarto {:author :timothypratley
44
:description "A lightweight way to cook with Clay and Scittle"
55
:type :post
6-
:draft true
76
:date "2025-08-13"
87
:category :clay
98
:tags [:clay :workflow :scittle :reagent]}}}
@@ -33,9 +32,9 @@
3332
;; Clay lets us interleave plain Hiccup with Reagent/Scittle components:
3433

3534
(kind/hiccup
36-
[:div [:strong "Hello from Hiccup"]
35+
[:div [:strong "Hello from Hiccup (Clojure)"]
3736
['(fn []
38-
[:em "Hello from Scittle/Reagent"])]])
37+
[:em "Hello from Scittle/Reagent (ClojureScript)"])]])
3938

4039
;; But because Clay serves HTML, re-evaluating this namespace normally reloads the whole page.
4140
;; Wouldn’t it be great to get a Figwheel/shadow-cljs style experience where code updates in place?
@@ -96,12 +95,13 @@
9695
;; ## A Taste Test
9796

9897
;; Let's walk through a small example to see hot reload in action.
99-
;; I recommend copying these snippets into the `uncompiled.cljs` and saving as you go.
98+
;; I recommend copying these snippets into `uncompiled2.cljs` and saving as you go.
10099
;; First, we'll set up our ingredients (app state):
101100

102101
;; ```clojure
103-
;; (ns my-app.core
104-
;; (:require [reagent.core :as r]))
102+
;; (ns scicloj.clay.uncompiled2
103+
;; (:require [reagent.core :as r]
104+
;; [reagent.dom :as rdom]))
105105
;;
106106
;; (defonce app-state ; <- defonce preserves state during reload
107107
;; (r/atom {:style "scrambled"
@@ -116,64 +116,103 @@
116116
;; [:h3 "Breakfast Order"]
117117
;; [:p "Style: " (:style @app-state)]
118118
;; [:p "Eggs: " (:eggs @app-state)]])
119+
;;
120+
;; (rdom/render
121+
;; [breakfast-order]
122+
;; (js/document.getElementById "app2"))
119123
;; ```
120124

121-
;; We can mount our new component on the `app` div.
125+
;; We want to be able to change cooking styles.
122126

123127
;; ```clojure
124-
;; (rdom/render
125-
;; [breakfast-order]
126-
;; (js/document.getElementById "app"))
128+
;; (defn cycle-style []
129+
;; (swap! app-state update :style
130+
;; {"scrambled" "fried"
131+
;; "fried" "poached"
132+
;; "poached" "scrambled"}))
133+
;; ```
134+
135+
;; And while we're at it, let's add controls for the number of eggs:
136+
137+
;; ```clojure
138+
;; (defn add-egg []
139+
;; (swap! app-state update :eggs inc))
140+
141+
;; (defn remove-egg []
142+
;; (swap! app-state update :eggs #(max 1 (dec %))))
127143
;; ```
128144

129-
;; Just like our opening story, imagine the order changes mid-cook.
130-
;; We can update our component without losing the current state:
145+
;; Now we can update our component to use these functions.
131146

132147
;; ```clojure
133148
;; (defn breakfast-order []
134149
;; [:div
135150
;; [:h3 "Breakfast Order"]
136-
;; [:p "Style: " [:em (:style @app-state)]] ; <- added emphasis
137-
;; [:p "Eggs: " (:eggs @app-state)]
138-
;; [:small "Water added for poaching..."]]) ; <- new status line
151+
;; [:div
152+
;; [:p "Style: " [:strong (:style @app-state)]]
153+
;; [:button {:onClick cycle-style} "Change Style"]]
154+
;; [:div
155+
;; [:p "Eggs: " (:eggs @app-state)]
156+
;; [:button {:onClick remove-egg
157+
;; :disabled (= 1 (:eggs @app-state))} "−"]
158+
;; [:button {:onClick add-egg} "+"]]
159+
;; [:div
160+
;; (case (:style @app-state)
161+
;; "poached" "Water added for poaching..."
162+
;; "fried" "Turn n burn!"
163+
;; "scrambled" "Whisking away...")]])
139164
;; ```
140165

141-
;; Save the file, and voilà! The display updates while preserving the
142-
;; existing order details in app-state. No need to start over or lose
143-
;; your place in the cooking process.
166+
;; If you are running this locally,
167+
;; notice how we keep the same state while adding new features.
168+
;; Each time we save the ClojureScript file,
169+
;; our app updates but keeps its current state.
170+
171+
;; Here's the final result of our cooking:
172+
173+
(kind/hiccup
174+
[:div#app2
175+
[:script {:type "application/x-scittle"
176+
:src "uncompiled2.cljs"}]])
177+
178+
;; We replaced functions on the fly while our state lives on.
179+
;; The new code creates a fresh experience without losing where we were.
180+
;; Just like adding water to the pan.
144181

145182
;; ## Why Go Light?
146183

147184
;; A Michelin-star kitchen is a marvel of efficiency.
148185
;; Sous chefs prepping ingredients,
149186
;; line cooks at their stations, everything precisely mise en place.
150-
;; That's your typical ClojureScript setup: build tools, asset compilation,
151-
;; development servers, and careful configuration.
187+
;; That's your typical ClojureScript setup.
188+
;; Build tools, asset compilation, development servers, and careful configuration.
152189
;;
153190
;; But sometimes you just want to slap some cold cuts and cheese in a sandwich and start munching.
154-
;; That's Scittle: quick, simple, and satisfying.
191+
;; That's Scittle. Quick, simple, and satisfying.
155192
;; No waiting for the kitchen to warm up, no cleanup afterward.
156-
;; Just write some code and see it work.
193+
;; Write some code and see it work.
194+
195+
;; ![Sandwich creation workspace](uncompiled.jpg)
157196

158197
;; ## Chef's Notes
159198

160199
;; Clay blends the traditional with the experimental.
161200
;; Write a namespace, get a webpage.
162201
;; Add some Scittle, get interactive components.
163202

164-
;; The magic happens in how Clay handles changes:
203+
;; Magic happens when Clay handles changes:
165204

166-
;; - For your narrative and page structure in Clojure live reload refreshes the whole view
167-
;; - For your Scittle components hot reload updates just the code, keeping state alive
205+
;; - For your narrative and page structure in Clojure, live reload refreshes the whole page
206+
;; - For your Scittle components, hot reload updates only the code, keeping state alive
207+
208+
;; This is especially sweet when you're cooking up mini-games with MatterJS.
209+
;; Tweak physics parameters or game logic, and watch them take effect as soon as you save.
168210

169-
;; This is especially sweet when you're cooking up interactive elements like mini-games
170-
;; with matter.js. Tweak physics parameters or game logic, and watch them take effect
171-
;; instantly. Your game state, scores, and position all preserved.
172-
;;
173211
;; Remember how we started with those poached eggs?
174212
;; Maybe they were destined for a sandwich all along.
175-
;; That's the beauty of this approach: start simple,
176-
;; stay flexible, and build exactly what you need.
177-
;; Clay lets you shape your story with markdown, spice it up with interactive widgets,
213+
;; That's the beauty of this approach.
214+
;; Start simple, stay flexible, and build what you need.
215+
;; Clay lets you shape your story with markdown,
216+
;; spice it up with interactive widgets,
178217
;; and adjust the ingredients.
179218
;; That's the kind of flow that keeps creative coding delicious.

0 commit comments

Comments
 (0)