#+TITLE: Intro to Hiccup


* Introduction

hiccup is a html DSL, used extensively in the clojure's eco-system, there are others as well but hiccup is the most widely used.

In hiccup everything is a list, this means you can easily compose html using standard language constructs.
To render the hiccup to html elements we call the (html) function from the hiccup library for server side with reagent or client side code this will likely be a different function like (render).

There are a few variant's the main ones being https://github.com/weavejester/hiccup and https://github.com/lambdaisland/hiccup , the lambdaisland one is particular helpful if you want to share html between the frontend and backend as its closer to reagents builtin hiccup.


#+BEGIN_SRC edn :results silent :export none :tangle deps.edn
{:paths ["src" "resources"]
 :deps
 {org.clojure/clojure {:mvn/version "1.10.0"}
  org.clojure/clojurescript {:mvn/version "1.11.60"}}}
#+END_SRC


#+BEGIN_SRC text :results silent :export none :tangle readme.org
#+TITLE: Getting started
#+END_SRC


** Simple examples
If using reagent you don't need to pass into h/html but this is server side reagent also has some helpers to work with react nicer.
#+BEGIN_SRC clojure :tangle src/core.clj
[:span "bar"]
#+END_SRC

*** Styles classes and ID's
Attributes are added as a map of values styles are also a map
#+BEGIN_SRC clojure :tangle src/core.clj
[:span {:class "class1 class2" :title "my title" :style {:color "red"}} "bar"]
#+END_SRC

You can use shorthand to add id's and classes
#+BEGIN_SRC clojure :results output :tangle src/core.clj
[:span#id.class1.class2 "bar"]
#+END_SRC

** Example of manipulating hiccup with clojure functions

You can use clojure core language to manipulate these vectors.

place parts inside another containing element
#+BEGIN_SRC clojure :results output :tangle src/core.clj
(into [:div.container]
      [[:span "span 1"]
       [:span "span 2"]])
#+END_SRC

You could also use merge, in this example the spans are merged inside the div vector.
#+BEGIN_SRC clojure :results output :tangle src/core.clj
(merge [:div] [:span "span 1"] [:span "span 2"] [:span "span 3"])
#+END_SRC

We can take advantage of lazyness if we like
#+BEGIN_SRC clojure :results output :tangle src/core.clj
(defn navbar-link [{:keys [href title text] :or {text href title nil} :as link}]
  [:a.link.dim.white.dib.mr3 {:key href :href href :title title} text])

[:div (into [:nav.f6.fw6.ttu.tracked]  (vec (take 2 (mapv navbar-link
                  [{:key "link1" :href "link1" :title "title here"}
                   {:key "link2" :href "link2" :title nil}
                   {:key "link3" :href "link3" :text "link text"}
                   {:key "link4" :href "link4"}]))))]

#+END_SRC

** Compossible components
The main advantage comes from the ability to compose the parts together, so we can break our html apart and recombine using all the function at our disposal.
In this example our navigation is defined as a hash map, the data is separated out from the html, we can then pass the data to our component to render it.
In this example we have a link component and a nav component the link component take the values as key, value pairs and uses de structuring while also setting default if values are not set.

#+BEGIN_SRC clojure :results output :tangle src/core.clj
(defn navbar-link [{:keys [href title text] :or {text href title nil} :as link}]
  [:a.link.dim.white.dib.mr3 {:key href :href href :title title} text])

(defn navbar [links]
  [:header.bg-black-90.w-100.ph3.pv3.pv4-ns.ph4-m.ph5-l
   (into [:nav.f6.fw6.ttu.tracked]
         (mapv navbar-link links))])

[navbar [{:href "link1" :title "title here"}
         {:href "link2" :title nil}
         {:href "link3" :text "link text"}
         {:href "link4"}]]
#+END_SRC

In this example we create some simple top trump style cards using a map with a vector of nested maps for the stats.
We use map and into to convert the stats value

#+BEGIN_SRC clojure :results output :tangle src/core.clj
(defn playing-card
  [{:keys [title image stats]}]
  [:article
   [:div.border-solid.border-2.border-sky-500.m-4.w-64.rounded-lg
    [:div.dt.w-full
     [:div.m-4 [:h1.f5.f4-ns.mv0 title]]
     [:img.db.w-full.h-100.br2.br--top {:src image}]]
    (into [:ul.m-4]
          (mapv (fn build-stats [[stat value]]
                  [:li [:div stat [:div.float-right (str value)]]])
                stats))
    [:p.f6.lh-copy.measure.mt-2.mid-gray ""]]])

[:div.flex.flex-wrap
 [playing-card
  {:title "Bee"
   :image "https://loremflickr.com/300/300/bee"
   :stats {:strength "6"
           :lifespan "3" ;; 6 weeks
           :danger "5"
           :mobility "9"}}]
 [playing-card
  {:title "Spider"
   :image "https://loremflickr.com/300/300/spider"
   :stats {:strength "4"
           :lifespan "5" ;; 1 year
           :danger "8"
           :mobility "5"}}]
 [playing-card
  {:title "Ant"
   :image "https://loremflickr.com/300/300/ant"
   :stats {:strength "8"
           :lifespan "8" ;; 7 years
           :danger "4"
           :mobility "3"}}]
 [playing-card
  {:title "Dragonfly"
   :image "https://loremflickr.com/300/300/dragonfly"
   :stats {:strength "2"
           :lifespan "1" ;;2 weeks
           :danger "1"
           :mobility "9"}}]]
#+END_SRC



