Jarzka / stylefy

Clojure(Script) library for styling user interface components with ease.
MIT License
315 stars 10 forks source link

Convenience functions #10

Open tatut opened 6 years ago

tatut commented 6 years ago

Currently combining style information with other attributes seems quite verbose, like:

[:a (merge (stylefy/use-style some-style-ns/link-style)
                  {:on-click #(...)})
  "click me"]

A more convenient shorthand would be nice (though I don't yet know what would be the best).

Perhaps defining a pre-styled element, like:

;; define pre-styled constructor
(def my-link (stylefy/with-style :a some-style-ns/link-style))

(defn my-component []
 ;; use it like any reagent component
  [my-link {:on-click #(...)} "click me"])

This can obviously be done separately without adding it to stylefy, but I think a recommended way would be nice.

Jarzka commented 6 years ago

Neat, this idea is worth testing!

Jarzka commented 6 years ago

I think this problem got a bit less painful after use-style started accepting HTML attributes as the second parameter.

nijk commented 6 years ago

Agreed, and further convenience wrappers can be provided by wrapping the component in an HOC that does a lot of the hard work for you, e.g.

[with-style [:a {...} "click me"]]

(defn- normalise
  [attrs-and-children]
  (if (and (not (second attrs-and-children))
           (sequential? (first attrs-and-children))
           (coll? (ffirst attrs-and-children)))
    (first attrs-and-children)
    attrs-and-children))

;; Merge new attrs map into Attrs & Children sequence
(defn merge-attrs
  [default-attrs [attrs & children :as attrs-and-children]]
  (if (map? attrs)
    (cons (merge default-attrs attrs) children)
    (cons default-attrs attrs-and-children)))

;; Gernerate Hiccup with Stylefy styles and variadic args
(defn with-style
  [style-map style [element & attrs-and-children]]
  (let [style (get (get style-map @theme) style)
        [attrs & children] (->> (normalise attrs-and-children)
                                (merge-attrs {}))
        attrs' (or (use-style style attrs) attrs)]
    (into [element] (cons attrs' children))))

Disclaimer: This is untested code and has no guarantees associated with it. It is intended here to spark debate about the possible ways to solve the original poster's question and help close the issue.