zachdaniel

zachdaniel

Creator of Ash

Tails - Tailwind & Tailwind Component Utilities

Making components take tailwind classes is a dicey proposition at best. You can’t just put a set of tailwind classes after another set and expect them to do the right thing, because later classes in the class string don’t override earlier ones, its all based on how “specific” the CSS that class applies. In looking for an example, I found a similar package for js that illustrates the need for it: https://www.npmjs.com/package/tailwind-merge.

I’m (slowly) building a set of utilities to help make more “tailwind-y” components, and also to be able to leverage tailwind in other ways. This library isn’t published to hex yet because it will need some more love, specifically it needs a lot more merge logic. It currently only handles some basic things.

Eventually, I could also see it supporting other kinds of directives to help overriding what a component does. For example, if a component sets something like bg-blue-500 hover:bg-blue-600, but you want it to use bg-red-500 always we could support something like <Component class="all_directives:bg-red-500" />. Or if you wanted to remove a class that the component adds, you could do so with <Component class="remove_class:bg-blue-500" />.

The ideas above are dubious, not sure if they are a good idea, but the point is that the potential for them is there :slight_smile: The part I am sure of is that having a class merger will allow us to write better components that can take tailwind classes and use them as overrides for their own classes.

It also handles merging a list, as well as conditional classes and nested lists, so in the end you might have something like this:

class={classes([
  "inline-flex items-center justify-center gap-2 text-sm font-medium font-sans transition-colors duration-300 disabled:cursor-not-allowed flex-grow-0",
  handle_button_hierarchy(@hierarchy), 
  handle_button_size(@size, @show_label),
  [
    "flex-row-reverse": slot_position == "trailing",
    "w-full": @expanded
  ],
  @class
])}

The other thing it currently does is defines functions that map to your tailwind colors, if configured with a tailwind.colors.json file to use. For those trying out LiveViewNative, this means you can reuse any custom tailwind colors, i.e <text color={primary_light_600()}>{@text}</text>. We could perhaps find other ways to make tailwind the “source of truth” that can be shared between web and LiveViewNative?

Curious to hear your thoughts! If we can get a few more people interested to help build out the class merging rules, and especially if we can make it more integrated with the tailwind config, that kind of thing.

Most Liked

trisolaran

trisolaran

Sounds definitely like something that could be useful. By the way, some of your ideas reminded me of this library: GitHub - cblavier/phx_component_helpers: Extensible Phoenix liveview components, without boilerplate
which comes with utilities to manipulate CSS classes. Don’t know how similar they are to what you have in mind.

zachdaniel

zachdaniel

Creator of Ash

That does look very similar! My only qualm that I can see is that its just doing “prefix replacements”, which won’t work for things like block and hidden, and other tailwind specific things. But I do wonder if perhaps tails should just live inside of a tool like that :slight_smile: So they could say extend_class(..., tailwind: true)?

tcoopman

tcoopman

No that doesn’t work. See Content Configuration - Tailwind CSS

Sebb

Sebb

stupid question: how does this work at all? Doesn’t the tailwind compiler just deliver the CSS for the classes it sees at buildtime? So when the only tailwind class in my templates is text-sm and I dynamically add text-xl how can the tailwind compiler know about that…?

Sebb

Sebb

So it does not parse the HTML and looks in @class but just looks for the classes as text in all files?

What about

size = "xl"
class = "text-#{size}"

can’t work, right?

Where Next?

Popular in Libraries Top

josevalim
Hi everyone, We would like to announce that Plataformatec is working on a new MySQL driver called MyXQL. Our goal is to eventually integ...
New
mhanberg
I just released the first version of Temple: an HTML DSL for Elixir and Phoenix! You can read this blog post or the docs for more info...
New
tmbb
I’ve been working on two packages (not on hex.pm yet) to build admin interfaces for phoenix apps: bureaucrat - which contains a bunch ...
New
OvermindDL1
Been making an MLElixir thing (not released yet…) for fun in spare time in the past day. I’m just trying to see how much I can get an ML...
132 13487 106
New
archan937
It is a well-know topic within the Elixir community: “To mock or not to mock? :)” Every alchemist probably has his / her own opinion con...
New
Crowdhailer
I have been updating a library that allows you to pipe between functions that use the erlang result tuple convention. Assuming you have...
New
josevalim
Yes, yet another parser combinator library! Most of the parser combinators in the ecosystem are either compile-time, often using AST tra...
159 18262 141
New
wmnnd
Hi there, for my project DBLSQD, I needed a file storage solution that is a bit more flexible than Arc. Because I thought others might f...
New
OvermindDL1
I created a new library (rather I pulled out a couple files from my big project), it manages an operating system PID file for the BEAM. ...
New
Qqwy
While not as prevalent as in imperative languages, arrays (collections with efficient random element access) are still very useful in Eli...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
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
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
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 42633 214
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

Sub Categories:

We're in Beta

About us Mission Statement