fuzetsu / zaftig

~2kB css in js: z`display flex` // .zjsdkk43-1

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

helpers vs. inlinining the CSS directly into the templated string?

resolritter opened this issue · comments

when I was using this library for the first time, I thought the z.helper API was neat

however, can't the same be done by interpolating expressions directly into the string?

e.g., instead of

z.helper({
  bo: 'border'
})

z`
  bo 4 solid red
`

do

z`
  ${bo(4, 'solid', 'red')}
`

collateral benefit: also results in straightforward type-checking if you're using e.g. TypeScript

this could also be z.style in the "post-processing" phase for effects which depend on updated values (after a hook has triggered an update, for instance)


Is there some advantage I'm failing to see in there? My current impression is that those custom functions are more flexible and also would help in reducing the API.

Hi @resolritter, sorry for the late reply!

You're absolutely right about interpolation fulfilling a similar role to helpers.

Helpers are inherently global, which can be an upside/downside depending on how you look at it:

In a smaller application having easy access to a set of centrally defined helpers without needing to interpolate or import functions can be convenient, but in a larger more modular code base it might be much more desirable to stick to interpolated values so that code is more portable/reusable.

Of course you could also use z.new to create a dedicated instance of zaftig for a submodule of your application that has it's own dedicated set of helpers, but I digress.

Type checking is certainly a good argument for using interpolation if you're using TypeScript!

To answer your last question, there's one fairly minor advantage to using helpers vs interpolation, and that is that helpers have built in memoization. The helper method will only be executed if the style string changes, whereas an interpolated function unless you add your own memoization would be called each time.
I say this is a minor benefit because most helper functions are pretty low cost and not really a performance concern.

Overall I think that helpers are just a nice convenience feature of zaftig, but certainly not a core necessity. I could certainly see removing it as a feature as some point if I got the feeling that most people didn't use it or like it. As things are currently I do use helpers quite a bit in my code bases and I know at least one other user of Zaftig that does as well 🤔

@fuzetsu I apologize for the lateness as well. I'm only having room to come back to side projects on the weekends.

Overall I think that helpers are just a nice convenience feature of zaftig, but certainly not a core necessity

I've always worked with Sass, Less and other sorts of and pre-processors in the past. zaftig is the first library I've used with CSS-in-JS. I especially liked that it's not tied to a specific UI runtime and, for that reason, I presumed it was also more customizable.

Coming from that background, I associated the z.helpers with mixins and Sass helper functions (like darken, for instance). One of the first things I did was install the npm package color and try to generate helpersfor some methods available there.

That was about when I noticed it wasn't necessary, because I wasn't relying on pre-processors anymore. Code can be interpolated directly using native JS constructs (JS variables instead of Sass variables, JS functions instead of Sass functions, etc)... This is what "bugged" me: one of the advantages of CSS-in-JS is that you can write the style as any other JS code, but z.helper kind of pushes in a different direction - those are "functions" which are written and behave differently from JS functions; according to my expectations, the whole styling API should add as little "dialect" as possible on top of the host language.


As things are currently I do use helpers quite a bit in my code bases

I think use-cases are a good argument for keeping parts of the API, especially if it doesn't hold the library back. Although...

a set of centrally defined helpers without needing to interpolate or import functions can be convenient

That you can use them at any time, without setup, sounds like the biggest selling point to me. It got me thinking it'd be useful to advertise that a bit more in the README, as well as the memoization effect.

z.helpers are advertised as a shortcut brevity and code reuse, both of which are attractive... However, the same intent can be expressed with plain functions, which are much more universal. If you compare the two, z.helpers statements are macros which are tied to zaftig's semantics, while a plain function is a common first-class citizen in JS. The former's usage pattern is inherently less flexible than interpolating strings directly, which gives you all the freedom you want regardless of the argument's types.

From what I'm reading here

? helper(...(value ? value.split(' ') : []))

I'm imagining it'd be possible to pass an array to a helper if you removed spaces and called JSON.parse later, but it seems weird.


In summary, I'd be in favor of removing z.helpers because they're part of this library's grammar, when their same intent can be achieved using primitive constructs of the language. I dislike that I can't think of them the same as I would with JS functions.

If not removing, then it'd be very nice to highlight what sets them apart and why you would prefer one over the other.