Sebb

Sebb

Can we solve the tailwind-interpolation-problem with a macro?

tailwind will go through your files and find classes using a RE.
So you can’t interpolate tailwind classes.

<div class={"w-#{@foo}"}> <!-- DOES NOT WORK -->

You have to

<div class={[
  @foo==1 && "w-1",
  @foo==2 && "w-2",
  ...
  @foo==96 && "w-96"]}>

(or use @style)

How about a heex macro tailwind (and an accompanying attr type which gives all possible values)

attr :foo, :tailwind, range: [1, 2, 3, 4, 10, 24, 96]
...
<div class={[tailwind("w-#{@foo}"), "other classes ..."]}>

or maybe sth like this using a sigil

<div class={[~t"w-#{@foo}", "other classes ..."]}>

all tailwind macros could compile to an extra file (which is listed in tailwind.config to get parsed by the tailwind preprocessor)

# tailwind.lst
w-1, w-2, w-3, w-4, w-10, w-24, w-96 

Most Liked

zachdaniel

zachdaniel

Creator of Ash

I think my tails library could be a good place to put this solution: Tails - Tailwind & Tailwind Component Utilities

We can make classes into a macro instead of a function, and support something like this:

classes(["foo-#{x}", ...], x: [1, 2, 3, 4, 10, 24, 96])

Then it would yell if you interpolate a variable in your classes but don’t provide a list of possible values. Then it would write the file that you’ve mentioned.

zachdaniel

zachdaniel

Creator of Ash

Yep! We shouldn’t scan source code, we should provide a macro or sigil that does the validation. The tails library solves for class merging and conditional classes. Class merging is necessary for allowing components to have their classes overridden by parents passing down classes(my preferred way of overriding components) and tails will do a semantic merge based on what classes “conflict” in tailwind.

I’m already working on a macro version of classes as well as a sigil. The macro version will, for now, warn on interpolation unless possible values for the interpolated expression is provided.

D4no0

D4no0

Oh my god, just banged my head for a few hours to understand that this is happening.

The thing is that this is not only not consistent, if you use same classes elsewhere, it will work (this also includes cached builds), but it also doesn’t show any kind of errors or warnings.

Actually as it currently stands, it seems that the limitation is that the string should be known at compile-time, things such as this work:

<div class={[@badge_type]}>
</div>
badge_type = get_badge(type)
assign(socket, badge_type: badge_type)
defp badge_type (type) do
    case type do
      :success -> "badge-success"
      :warning -> "badge-warning"
      :error -> "badge-error"
      :inactive -> "badge-ghost"
      :not_found -> "badge-info"
    end
  end

I have both the cases where a separate .heex file is used and when render/1 from an .ex file is used, and both seem to be working when the strings are known at compile-time. Looking at this now, it seems that the configuration watches in .ex files too:

content = [
  ...
  "../lib/*_web/**/*.*ex"
]

Have you found any solutions so somebody else would not stumble onto this bug?

Where Next?

Popular in Discussions Top

WolfDan
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
Jayshua
I recently came across the javascript library htmx. It reminded me a lot of liveview so I thought the community here might be interested....
New
sashaafm
I’m trying to evaluate the best combo/stack for a BEAM Web app. Right now I’m exploring Yaws a bit, after having dealt with Phoenix for a...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
arpan
Hello everyone :wave: Today I am very excited to announce a project that I have been working on for almost 3 months now. The project is...
New
tmbb
This is a post to discuss the new Phoenix LiveView functionality. From Chris’s talk, it appears that they generate all HTML on the serve...
342 18272 126
New
AlexMcConnell
The reason that Rails is as popular as it is is because it’s very easy for relatively inexperienced developers to get a lot of work done....
588 19675 166
New
New
Owens
Hello all, I am developing a new mobile app with Flutter frontend and Phoenix backend. The mobile app has real-time task management and c...
New
fireproofsocks
This is more of a general question, but I’m wondering how other people in the community think about the pattern matching in function sign...
New

Other popular topics Top

siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43806 214
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

We're in Beta

About us Mission Statement