Fork me on GitHub
#clojurescript
<
2024-02-28
>
lwhorton17:02:55

i'm looking for some suggestions on css libs/strategies for use in a cljs project. does anyone have tools they like? 1. isolation is super important to me; i should be able to define a function which renders a component, and that component's css shouldn't leak into any other component. perhaps something like this:

(defn my-component [args] [:div {:class (some-fully-isolated-css args)} [:h1.head ...] [:ol.list ...]])
(defn some-full-isolated-css [args] {:display 'flex :align-items 'center ... ".head" { ... } ".list" { ... } })
1. i really dont like tailwinds, or tailwinds-like implementations. i find it difficult to read/write semantic html: [:.stuff.is.buried.behind.ten.classes.and.oh.wait.reloading.gets.tricky.too.and.also.what.about.stripping.unused.css?] 2. if at all possible, id prefer something that spits out a compiled .css file at prod-build time. the ability to cache this file is great. also, not having to use extra render time for css-in-js-style dom manipulation is very nice. i conceptually really like the idea of cljss . its defstyled is a very simple, straightforward interface. its isolation through guid-based class generation is great. i'm not a fan of the macro-based implementation, though. trying to setup a reload-friendly workflow is immediately tricky and confusing, and the mixing of functions like remove-styles! with macros (which are in ... some other namespace?) is really confusing. anyways, i'd love some suggestions if anyone has a particular tool/lib they enjoy.

p-himik18:02:36

Just a small thing - things like :label.class1.class2.class3 become much more manageable if you extract all the classes:

(def cool-label-cls [:class1 :class2 :class3])

(def view []
  [:label {:class cool-label-cls}
   "hello"])

p-himik18:02:15

And regarding stripping unused CSS - there has been a recent announcement of https://www.npmjs.com/package/@multiplyco/tailwind-clj

👀 1
lwhorton18:02:44

i feel very dumb that i didnt think about pulling classes out into a separate block. that's essentially identical to defining a normal css block {:display ... :margin ...} , except you can use tailwind's language instead of css.

p-himik18:02:02

Yeah, the (unfortunate, IMO) proliferation of the :div.class syntax can sometimes make people forget about the ability to pass :class as an attribute. :) And it's very flexible - it accepts nil, keywords, strings, collections of those items, collections of collections. So you can have stuff like

[:div {:class [(when red? :red) (when stands-out? [:border :shadow]]} ...]

thheller20:02:01

https://github.com/thheller/shadow-css I'll leave that here, although you already basically disqualified it with your statements 😛

lwhorton20:02:16

this is actually really close to what i had in mind. i like the prod build step that spits out a real css file. i like the tiny api surface area. i wonder if i could edit it a bit to spit out inlined <style> tags at dev time, so i dont need to setup a watcher process and wait for css to compile on reload

lwhorton20:02:29

the sad thing is that i have already built a tool to do exactly what i want... but due to a series of unfortunate events including NDAs and private github repos, i have lost that tool.

p-himik20:02:13

> setup a watcher process It's built into shadow-cljs. Dunno about other tools. > wait for css to compile on reload <style> also requires a compiled CSS string, there's no way around compiling CSS. But if the compilation is just concatenation and generation, without any optimizaitons, it's fast. You won't notice it when compared to CLJS reloading times (which are also small under normal conditions).

thheller09:02:14

FWIW I switch the https://github.com/thheller/shadow-cljs/blob/3579024808eafdfcf42b93f5e0d3eb2d28abf6e4/src/dev/repl.clj#L18-L27 to just do a release build on every changes. takes about 50-100ms so not really required doing any kind of incremental update.

👍 1
lwhorton15:02:41

I've been reading through ornament from the lambdaisland folks, there's some neat ideas in there, too