Sebb

Sebb

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 

Showing Posts 1 to 10

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?

tcoopman

tcoopman

Have a look at: Detecting classes in source files - Core concepts - Tailwind CSS

If you really need to have some classes, you can safelist them (see further on that page).

Basically, tailwind creates minimal css files by only including the class you’ve used. It can’t guess what classes you need.

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.

D4no0

D4no0

This is a great resource, but the reality is that the most likely case is the one I stumbled across, where you have to invest a lot of time to understand what is happening.

It would be great if the tailwind elixir library could somehow detect and warn the user that class string interpolation can impact directly tailwind classes when used in conjunction with phoenix.

sodapopcan

sodapopcan

I think having it more prominently documented would go a long way. As it stands, as linked by @tcoopman, the Tailwind documentation mentions it three sections in and a good scroll-length down the page. For Phoenix users, phx_new could maybe add a comment about it to app.css and/or tailwind.config since so many people run into this (I did too).

Warning via a macro would probably be really tricky as interpolating non-tailwind classes is perfectly valid. It would be hard to reliably judge what is and isn’t a Tailwind class.

EDIT: I guess you could warn on interpolation so long as there is way to turn it off since this is one of those things that once you know, you know.

D4no0

D4no0

I think this is totally doable, especially with the tools elixir has at disposal. Think of it the following way:

  1. Magic for finding dynamic class content;
  2. Magic for finding interpolated strings in dynamic classes;
  3. Use a opt-out approach where you always warn the user about the potential problem, then offer him a way out, for example by using a ~dont_care sigil;
  4. Make it globally configurable if you don’t care at all.

I think this is very important, especially for beginners that have a lot of complexity without this small implementation detail that is extremely hard to trace down.

sodapopcan

sodapopcan

I wasn’t saying that any of that was hard. What’s potentially hard is determining what is an isn’t a Tailwind class, especially since TW class names are highly configurable. But ya, so long as you could turn it off it should be fine. And obviously not fire if you’ve used --no-tailwind.

sodapopcan

sodapopcan

Plus this is perfectly valid:

color =
  case assigns.color do
    :green -> "bg-green-500 text-green-50"
    # ...
   end

assigns = assign(assigns, :color, color)

~H"""
<p class={"font-bold #{@color}"}>foo</p>
"""

But yes, so long as there is a way to turn it off it would be good.

D4no0

D4no0

Indeed, this is very similar to the example I posted above.

What I want to focus on is not the commodity on how to approach this, but how to avoid having this almost impossible to trace bug.

This is the first time in my 5 years of elixir development when I literally had no idea what was going on, because after checking out on another branch (that was most probably when the cache was invalidated) the project was no longer working as expected, without any warnings, traces or ways to reproduce what happened.

sodapopcan

sodapopcan

Cool, I clearly misunderstood your intent.

I agree it’s a problem.

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 92995 915
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
GES233
I’m posting this in response to Jose’s recent tweet (Cr. link) : People are sleeping on Elixir for a coding harness: Hot-code swappi...
New
_mfierro
Hello, I wrote Stop My Hand, a Scattergories-like web application using Phoenix/LiveView as my learning project for Elixir (after readin...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews