The :hoplon: ClojureScript Web Framework - http://hoplon.io/

Some random thoughts: start off by optimizing ease of use/access. Don't think too much about it until something becomes annoying and then step back and think if you could benefity from changing the granularity. That's the nice thing about hoplon, you can pretty easily adjust granularity


For example if you have a flat sequence of stuff that you will want to visually sequentually like in the todo app, it makes a lot of sense to just put it all in one cell

micha 2020-03-25T00:45:57.006500Z

i think of it like input cells are database tables, and formula cells are views

micha 2020-03-25T00:46:10.007Z

there is a lot of flexibility there to design the data model you want

micha 2020-03-25T00:46:45.008Z

the UI is then sort of like a chart hooked up to the tables and views

micha 2020-03-25T00:47:21.008900Z

as the underlying data in the input cells change the data flows through the formulas and updates the UI

micha 2020-03-25T00:48:01.009400Z

like in a database you normally wouldn't make a view for each row in a source table

phronmophobic 2020-03-25T00:49:11.009800Z

ok, i’m probably doing something wrong

micha 2020-03-25T00:49:55.010400Z

i just mean that if you have a cell containing a sequence of todo items, for example, the sequence itself embodies important information

micha 2020-03-25T00:50:06.010700Z

like the order of the items for example

micha 2020-03-25T00:50:30.011400Z

so it's natural to put the collection in a cell

phronmophobic 2020-03-25T00:50:31.011500Z

(defn checkbox [& {:keys [checked?]}]
  (let [checked? (or checked? (cell false))
        $checked? checked?]
      (fn [_]
        (swap! $checked? not)
      (ui/checkbox checked?)))))

(let [test-checkbox (checkbox (cell false))]
  (ui/run #(deref test-checkbox)))

(defn todo-item [& {:keys [todo]}]
  (let [todo (or todo (cell {:description ""
                             :complete? false}))
        $todo todo
     (checkbox :checked? (path-cell $todo [:complete?]))
     (textarea-view :text (path-cell $todo [:description]))

(let [item (todo-item)]
  (ui/run #(deref item)))

phronmophobic 2020-03-25T00:51:36.012100Z

so my thinking was that “components” could receive cells as arguments

micha 2020-03-25T00:51:47.012500Z

yes that's key

phronmophobic 2020-03-25T00:51:49.012700Z

so they get auto updated when their cells change

phronmophobic 2020-03-25T00:52:07.013100Z

and that basically works until you get to collections

phronmophobic 2020-03-25T00:53:42.014Z

my workflow so far has been , you make complex components out of simpler components

phronmophobic 2020-03-25T00:54:04.014600Z

many of the hoplon examples don’t have very many defelem components

micha 2020-03-25T00:55:16.015400Z

yeah i mean it's a hard problem to engineer the foundation of your composable world

phronmophobic 2020-03-25T00:55:38.016100Z

my code is currently a little clunky, but I think it could be cleaned with some syntatic sugar macros

micha 2020-03-25T00:55:44.016300Z

but you can do the usual lisp approach of doing the best you can with special cases where needed

micha 2020-03-25T00:56:16.016800Z

i think lisp provides the best possible platform for making an imperfect world more sane

micha 2020-03-25T00:56:56.017500Z

but it's really hard to make a truly orthogonal, composable UI kit in the browser

phronmophobic 2020-03-25T00:57:55.018Z

well, let’s you weren’t targeting the browser, what would you do differently?

micha 2020-03-25T00:58:48.018500Z

what i mean is like in the browser you always need some weird extra div for padding or margins, things like that

micha 2020-03-25T00:59:06.018800Z

that kind of thing interferes with composition

micha 2020-03-25T00:59:38.019200Z

i don't have much experience with other models

micha 2020-03-25T00:59:59.019700Z

javafx seems like it might be more regular, but i haven't used it enough to really know all of its secret faults

micha 2020-03-25T01:01:25.020800Z

i think maybe webcomponents could be a big improvement in the browser, with shadow dom and css isolation

micha 2020-03-25T01:01:54.021300Z

but it's still vaporware

micha 2020-03-25T01:02:54.023200Z

@smith.adriane have you heard of the amethyst and garnet projects in the 80s?

micha 2020-03-25T01:03:02.023600Z

lisp machine kind of stuff

phronmophobic 2020-03-25T01:03:08.023900Z

I have, but I haven’t revisited them in a while

micha 2020-03-25T01:03:23.024300Z

those seemed like an ideal platform to me when i saw it


i started messing with hoplon/ui (https://github.com/jumblerg/ui) again pretty deep recently, and i think he really nailed a ui model there (though it's ever changing and takes some work just to get running

micha 2020-03-25T01:04:18.025500Z

yeah that is an example of an attempt for a full top-down solution to the composition problem


it's the best i've felt about making uis without being bogged down

micha 2020-03-25T01:06:15.027300Z

he's put a massive amount of time into the design

phronmophobic 2020-03-25T01:06:28.027800Z

it looks like it’s focused on layout. does it have a story around events and state management?

flyboarder 2020-03-25T01:06:47.028200Z

for the visual side of things we went with UIKit (http://getuikit.com)

flyboarder 2020-03-25T01:06:58.028500Z

this lets us build components like this…

micha 2020-03-25T01:08:08.029100Z

do you use the uikit js too?

flyboarder 2020-03-25T01:08:19.029300Z

(modal/modal :stack true :container true
          (modal/title "Patient Information"))
        (modal/body :text/left true ::util/overflow-auto true ::section/muted true
          (grid/grid :small true :grid {:masonry true}
            ::width/width-1-1 true
            ::width/child-width-1-2 true
              (patient-basic-info patient))
              (patient-address-info patient))
              (patient-account-info patient))
              (patient-insurance-info patient))))
        (modal/footer ::text/right true
          (button/button ::modal/close true :primary true

flyboarder 2020-03-25T01:08:34.029600Z

@micha yes it fits in nicely with hoplon

flyboarder 2020-03-25T01:08:53.030100Z


micha 2020-03-25T01:08:55.030300Z

nice, this is what i was hoping would come from webcomponents too

micha 2020-03-25T01:09:12.030500Z

haha i'm making a webapp right now

micha 2020-03-25T01:09:24.030800Z

do you recommend i use ^^?

flyboarder 2020-03-25T01:09:38.031200Z

we are building some enterprise medical apps with it right now

micha 2020-03-25T01:09:58.031700Z

awesome i'll give it a shot

flyboarder 2020-03-25T01:10:33.031900Z

micha 2020-03-25T01:10:48.032400Z

very nice

micha 2020-03-25T01:10:55.032800Z

i was almost going the craigslist route

phronmophobic 2020-03-25T01:11:16.033Z

looks really spiffy

micha 2020-03-25T01:11:29.033300Z

yeah i'm sold

flyboarder 2020-03-25T01:11:58.033900Z

we took the theme from the uikit documentation website, the default style without a theme is pretty bare bones

flyboarder 2020-03-25T01:12:24.034500Z

but working with elements like cards and things is so easy

micha 2020-03-25T01:12:37.034900Z

i just need something that doesn't look like a ransom note

micha 2020-03-25T01:12:42.035100Z


flyboarder 2020-03-25T01:12:43.035300Z


micha 2020-03-25T01:12:54.035600Z

instill just a little trust in the user

micha 2020-03-25T01:13:12.036200Z

but i'm in a hurry lol

flyboarder 2020-03-25T01:13:16.036500Z

yeah our goal was to not have a designer at all, and let the devs just build

micha 2020-03-25T01:13:28.036800Z

this seems pretty awesome, thanks for putting it out there

flyboarder 2020-03-25T01:14:03.037400Z

a nice spiffy UI helps to sell the underlying tech, even tho it’s not at all related

flyboarder 2020-03-25T01:14:54.038400Z

our users are doctors who are used to like windows 95 style apps, moving to the web is a challenge enough so it had to look appealing and simple

micha 2020-03-25T01:14:58.038600Z

omfg the source is in clojure

micha 2020-03-25T01:15:06.038800Z

you are a king among men

micha 2020-03-25T01:15:37.039400Z

like the little source tabs in the demo site

micha 2020-03-25T01:15:43.039700Z


flyboarder 2020-03-25T01:15:56.040200Z

yeah I want to build out full docs but I dont have the time right now

phronmophobic 2020-03-25T01:16:10.040500Z

so for

(forms/form (patient-basic-info patient))
what is patient? is that a cell or POD?

flyboarder 2020-03-25T01:16:53.040900Z

yeah patient is a cell in that example

flyboarder 2020-03-25T01:18:21.041400Z

the uikit-hl docs really need refresh, but the source is solid and in production

phronmophobic 2020-03-25T01:18:41.041800Z

yea, looking through it. looks great

flyboarder 2020-03-25T01:18:58.042300Z

itself is a small hoplon app

phronmophobic 2020-03-25T01:19:28.042800Z

I read in the hoplon docs about on! stuff, but I don’t think I grokked it till I just saw the examples like

(defmethod uk-progress! ::progress
  [elem _ v]
  (h/do! elem :class {:uk-progress v}))

(h/defelem progress [attr kids]
  (h/progress attr ::progress true kids))

micha 2020-03-25T01:21:50.043400Z

this has made my day 🚀

micha 2020-03-25T01:27:29.045200Z

back to s3 buckets and cloudfront distributions and api gateways and things

flyboarder 2020-03-25T01:27:50.045600Z

hahah the less fun parts of app dev

micha 2020-03-25T01:27:54.045700Z

it's fun to make webapps again

micha 2020-03-25T01:28:02.045900Z

been a few years lol

micha 2020-03-25T01:28:31.046200Z

got cognito working with facebook login, that's pretty cool

micha 2020-03-25T01:29:22.046600Z

lol i tried to login to my facebook account

micha 2020-03-25T01:30:03.047300Z

somehow chrome remembered my password from more than 10 years ago before i disabled my facebook account

micha 2020-03-25T01:30:23.047700Z

well sort of remembered, i guess it didn't remember very well

micha 2020-03-25T05:10:46.048300Z

hm i can't get the hoplon helloworld to build

flyboarder 2020-03-25T17:56:50.048600Z

@micha whats wrong with the build?

micha 2020-03-25T19:11:53.049100Z

haha well for one thing i was trying to do :refer :all in cljs

micha 2020-03-25T19:12:06.049500Z

because i'm an idiot

micha 2020-03-25T19:12:37.050Z

it ended up being easier to downgrade java to 1.8

micha 2020-03-25T19:12:47.050300Z

so that's all good now

phronmophobic 2020-03-25T22:57:56.051700Z

this is the cleanest I could come up with 😕

(defelem todo-item [& {:keys [todo]
                       :or {todo {:description ""
                                  :complete? false}}}]
   (checkbox :checked? (path-cell $todo [:complete?]))
   (textarea :text (path-cell $todo [:description]))))

(defn test-todo-item []
  (let [item (todo-item :todo (cell {:description ""
                                     :complete? false}))]
    (ui/run #(do item))))

(defelem todo-list [& {:keys [todos]
                       :or {todos [{:description "first"
                                    :complete? false}
                                   {:description "second"
                                    :complete? true}]}}]
  (let [todo-count (cell= (count todos))
        new-todo-text (cell "")]
       (ui/button "add todo"
                  (fn []
                    (swap! $todos conj
                           {:description @new-todo-text
                            :complete? false})
                    (reset! new-todo-text nil)
       (textarea :text new-todo-text))
      (apply vlayout
             (for [i (range todo-count)]
               (todo-item :todo (path-cell todos [i]))))))))

(defn test-todo []
  (let [todos (cell [{:description "first"
                      :complete? false}
                     {:description "second"
                      :complete? true}
                     {:description "third"
                      :complete? true}])
        tlist (todo-list :todos todos)]
    (ui/run #(do tlist))))

phronmophobic 2020-03-25T22:59:17.052800Z

it does seem like javelin really wants to have a mutable DOM-like structure under the hood.

flyboarder 2020-03-25T23:50:01.053600Z

Well there is always some mutable layer under the hood, javelin doesn’t prescribe that part tho