Fork me on GitHub
#reagent
<
2016-03-28
>
adamkowalski17:03:24

is there a good way to create a higher order component? meaning it would take in a reagent component, modify it in some way, and then render the modified component instead? I am trying to make a component which can alter the styles of the element if you are hovering over it, so I was planning on having an ratom which is initially false, when the mouse enters the component I change it to true, and when it leaves set it to false again. Then I could have both base, and hover styles which could be merged or left as just the base depending on the state of the atom. however, rather than writing that piece of logic for every component which needs to react to hovering, I want to abstract it away and allow any new component to have that logic added it it.

rafd19:03:59

@adamkowalski: do you need to do the styling changes inline? this sounds like something that css solves on its own

rafd19:03:08

but... to your question, you can pass a component to a component

rafd19:03:39

or.... just pass and parse the "hiccup" data structures to a component

adamkowalski19:03:04

thanks for the response. yeah I know that css can do what I described above, but I prefer to write my styles as clojure maps [:div {:style {:color “green”}} “hello world”] that way I can use arbitrary functions to generate them and be able to have all of the abstractions programming languages provide

adamkowalski19:03:42

the drawback is that now things that were once trivial, like psudo selectors and media queries become more difficult

rafd19:03:57

i've used garden to do [:style (garden/css [ .... ] ) ]

rafd19:03:37

which lets you keep the benefits your describe

adamkowalski19:03:44

you just blew my mind, I didn’t know you could do that

adamkowalski19:03:09

do the psuedo selectors from garden work with styles inline?

rafd19:03:41

b/c it is a <style> block

rafd19:03:44

not an inline style

rafd19:03:59

errr, sorry, i meant.... the code i showed above adds a style block to your page

rafd19:03:07

i don't think the pseudo-selectors work with inline styles

rafd19:03:33

fyi, in practise, you should use dangerously-set-inner-html b/c re-agent escapes strings

rafd19:03:36

[:style {:type "text/css"
                :dangerouslySetInnerHTML {:__html (garden/css [:body ...}}]

gadfly36119:03:07

Fyi, a quick way to try out garden: lein new reagent-figwheel myapp +garden

adamkowalski19:03:24

yeah garden seems really interesting to me, except I have two reservations

adamkowalski19:03:37

1) how do you generate styles at runtime using functions?

adamkowalski19:03:54

ie: I have a component whose hue changes based on passing time

adamkowalski19:03:33

2) when you reload styles using figwheel and garden, it doesn’t seem to remove old styles, just mounts new styles on top. How do I clear all old styles before remounting styles

rafd19:03:54

re: 1) you can still use inline styles w/o garden, or use (garden/style ...) for it to generate a string that is compatible with inline-styles

rafd19:03:34

re: 2, i have it set-up to generate the css on the cljs side, and don't see that problem (my way may have some performance issues maybe?, but not that i've experienced)

adamkowalski19:03:13

yeah i think for #2 the issue was I used goog.style/installStyles and not [:style …]

adamkowalski19:03:43

but yeah for number one I would still have to solve the problem of having hover, focus, click styles

rafd19:03:03

do you need to have hover, focus, click dynamic?

rafd19:03:17

in theory, you can just create a dynamic <script> block

adamkowalski19:03:17

so you think that I could parse the child element passed in, extract the style map from the attribute map and merge in my styles

adamkowalski19:03:51

well my idea is this, I would like to be able to create a set of completely reusable components that can be shared between projects and other people

adamkowalski19:03:35

these components should be completely self contained, meaning they do not manipulate the css in any way and can instead be safely imported into your project without having to worry about style changes

adamkowalski19:03:25

also, i think it is a bad idea to have logic inside of a style language, so I would ideally move all of that out into the programming language level so that I can do more interesting dynamic changes to my components

adamkowalski19:03:49

in react I used radium and es7 decorates or react mixins which was perfect

rafd19:03:26

you could use gensym + garden + style tag in each of your components... ex.

(def wrapper [child]
  (let [id (gensym "id_")]
    (fn []
       [:div {:id id :key id}
         [:style (garden/css [(keyword id) {:color "red"} [:&:hover {:color "green"}]])]
          [child]])))

adamkowalski19:03:37

great idea, except how would I apply those styles to the child instead of the outer div

adamkowalski19:03:50

while also keeping any styles the child already has

adamkowalski19:03:43

lets say the hypothetical api looks like this

[hover-styles {:color “green”}
  [:div {:style {:color “blue”}} “I will change from blue to green when you hover over me”]]

rafd19:03:50

do [(str "#" id " *") {:color "blue"}] (note the star *)

adamkowalski19:03:42

so you generate the gensym in the child component then pass it up to the wrapper so they both talk about the same thing?

rafd19:03:43

generate the gensym in the parent, create the parent div with the gensym, and add the child underneath... add a style block that defines styles for the parent's descendants (ex. #id_1234 * )

rafd19:03:53

(star being: any children of #id_1234)

rafd19:03:13

and rely on css specificity to override children styles

adamkowalski19:03:09

interesting idea, I will think about it some more and see if I can codify it into something

adamkowalski19:03:21

because I might also have like

[clicked-styles {:color “red”}
  [hover-styles {:color “blue”}
    [:div {:style {:color “green”}} “hello”]]]

adamkowalski19:03:12

but that is quickly becoming unwieldy so maybe I can have something like this instead

[psuedo {:clicked {:color “red”}
         :hover {:color “blue”}}
  [:div {:style {:color “green”}} “hello”]]

rafd19:03:07

nvm, only supported by firefox atm

adamkowalski19:03:20

yeah polymer tries to do something similar

adamkowalski19:03:53

thats actually exactly what I am going for, essentially trying to make reagent work like web components

adamkowalski19:03:26

scoped styles, js, html -> reagent components, inline styles