datahike 2026-09-12

Started playing around with Spindel last night. It's very cool! I find the API much more intuitive than #CL85MBPEF.

One bit of feedback: the DOM stuff is not well documented at all. It's only mentioned in passing in the readme, and it wasn't until I was poking around the examples that I realized there even was a DOM library piece. Almost feels like it should be its own library, i.e. Missionary is to Electric as Spindel is to Spindel DOM. Just my 2c.

👍 1

I tried to add a simple toolbar to the tiptap example:

(defn make-app-spin [content-signal toolbar-signal]
  (spin
    ;; Track the content signal for reactive updates
    (let [content (iv/get-new (track content-signal))
          ;; Truncate for display if too long
          display-html (if (> (count content) 500)
                         (str (subs content 0 500) "...")
                         content)
          toolbar-state (iv/get-new (track toolbar-signal))]

      (el/div {:class "tiptap-demo"}
        ,,, ;; Header

        ;; Editor container using foreign-node
        (el/div {:class "editor-section"}
          (el/h2 "Editor")
          (foreign-node
            {:class "tiptap-editor"
             :on-mount (fn [el]
                         (create-editor! el content-signal))
             :on-unmount (fn [_]
                           (destroy-editor!))
             ;; updates toolbar-state so the toolbar follows the cursor...
             :on-mouseup on-mouseup
             }))

        ;; Live preview of content - now reactively updated via signal
        (el/div {:class "preview-section"}
          (el/h2 "Content (HTML)")
          (el/pre {:class "content-preview"}
            (el/code display-html))

          (el/h2 "Toolbar state")
          (el/pre {:class "content-preview"}
            (el/code (pr-str (into {} toolbar-state))))) ;; <---------------------- ???

        (el/div {:class "toolbar"
                 :style (:style toolbar-state)}
          (el/button {:on-click #(js/console.log "i")} "I")
          (el/button {:on-click #(js/console.log "b")} "B")
          (el/button {:on-click #(js/console.log "u")} "U"))

        ,))))
Reactivity on toolbar-state is working nicely. However, for the content preview, doing (pr-str toolbar-state) just renders the #object[...] repr, not very useful. So the into is just a way to show a readable form. Works, but not sure if this is idiomatic or if there's a "sanctioned" way to do this? 🙂 Thanks!

I will take a look. We could maybe introduce a custom render protocol.