Color parameters in elm-tailwind-modules with Philipp Krüger

Philipp joins us to talk about color parameters in elm-tailwind-modules and how that brings the tool closer to an ideal expression of a design system in Elm.
March 13, 2023


Hello, Jeroen.
Hello, Dillon.
And, well, today we've got another friend of the show joining us, Philip Kruger.
Philip, thank you so much for coming back on the show.
Hi, thank you for having me again.
It's a pleasure.
I have been a very happy user of Elm Tailwind Modules and Elm Default Tailwind Modules.
So thank you for those tools and thanks for coming back on.
Thank you.
I'm glad you like them and, yeah, lots of complicated names in all of those tools.
Lots of very sensible names, but you got to remember which order they come in.
So what are we talking about today, Philip?
So Elm Tailwind Modules currently has a new alpha release and in that release there's
some nice features that we want to talk about.
Actually, Dillon and I both worked on this and I think they're coming up nicely.
It's not released yet, at least the NPM package.
You can try it out anyway.
So yeah, it's an alpha.
And so, okay, so there's the NPM package, Elm Tailwind Modules, and there's the Elm
package, Elm Default Tailwind Modules, which is basically the result of running the code
generation from the NPM package with the default configuration, right?
Yes, exactly.
So Elm Tailwind Modules is a code generation tool?
So Elm Tailwind Modules is a code gen tool you install from NPM.
You can run it on your NPM config.
So if, sorry, on your Tailwind config.
So if you have a project with Tailwind CSS installed and you want to use that Tailwind
CSS config that you're using in Elm together with Elm CSS, then you can use the NPM package
to turn your Tailwind config into Elm Modules that use Elm CSS to have the same effect that,
well, all of the CSS classes that Tailwind has have.
Is that the right sentence structure?
I don't even know.
Philip, we did have you on, I guess a couple of years ago now, to talk about the initial
release of Elm Tailwind Modules.
But why don't we give people a little bit of a refresher?
They can go back and listen to that full episode.
But like, what problem is Elm Tailwind Modules trying to solve to begin with?
And even what is Tailwind?
What is that thing that no one has heard about?
That's right.
Yes, yes.
So Tailwind CSS is a way to style your applications using CSS.
It is using, I think people call this atomic CSS classes nowadays.
Is that still true?
I think so.
Utilities, perhaps.
Yeah, utility classes is a term that is used a lot.
Oh yeah, utility classes.
Right, right, right.
So basically the idea is your CSS class definitions are like very, very narrowly scoped.
And so for example, to make an element have display flex set, you simply put a class called
flex on it.
If you want it to be full width, you say w-full as a class on it, if I remember that correctly.
And well, so all of these classes in Elm, you'd have to set as strings, right, in your
class function from Elm HTML.
Or, well, yeah.
And since you don't get any type checking with that, that means you might do a typo
and wonder why your button doesn't take the full width just because you messed up some
dash or something in the name.
And so for that, someone else already built a tool which basically takes all of the Tailwind
classes that exist and creates small definitions for them, but then relays that to use classes
So you need to install your or add your CSS file to your Elm application somehow that
was generated from Tailwind.
And you need to figure out how to do that class elimination, essentially, right?
So Tailwind CSS classes that weren't used need to be deleted somehow.
And I found that it would be better to just reuse the dead code elimination that Elm the
language itself has instead of having to rely on other tools that go through your JS file
and try to find certain strings to figure out which classes to remove and to keep.
So instead, I built something that was based on Elm CSS.
So Elm CSS is a way of describing CSS styles within Elm as code, essentially.
And then these automatically get put into your Elm app.
You don't have to add any CSS files, some kind of styles.
You don't need that.
That's all managed by Elm.
And similarly, if you just don't use a couple of CSS classes from some module, well, they
won't appear in your final code because Elm just eliminates them.
So in addition to that, you can, this is one of the kind of really amazing things from
this design is you can throw in Elm CSS styles next to Tailwind styles.
So if you need to do some really custom CSS, you can even compose them together.
You can even, you know, add a media query that's not built into the Tailwind configuration
for your breakpoints, you know, like prefers reduced motion or whatever media query you
need to add, you can compose that media query together with Tailwind classes because it's
just generating Elm CSS.
Yeah, exactly.
There were a couple of nice follow ups from that.
So if I get it right, usually when you use Tailwind, you just say, hey, I want to use,
I want to, usually when you use Tailwind, you say, I want this thing to have full width.
So you do W dash full, and then Tailwind sees it and inserts some CSS code, which is going
to have the nice properties to make the thing have the full width, right?
And what you're doing with your project is you don't have that real CSS generated by
Tailwind, you reimplement it using Elm and Elm CSS, right?
Okay, so there's no, Tailwind doesn't do anything except your defined configuration, and you
just piggyback on that one to generate your Elm code.
It's almost like that.
Yes, we still, we don't bypass Tailwind CSS completely.
So essentially, how it works on the inside is it will generate the whole CSS file from
Tailwind CSS, and then it will turn that using the Tailwind config, and then it will turn
that CSS file into a big Elm module that contains all classes, each with their own definition
exposed and then you use that.
Right, okay.
So you still use it to generate that original CSS file, and then you just generate Elm code
and scrap that CSS file.
Yes, exactly.
Because you don't need it anymore.
Okay, interesting.
It should all be in memory, so there is no file actually generated.
Yeah, so this composability you get with Elm CSS is really interesting.
And so when Tailwind v3 came out, there was an interesting challenge that came up because
Tailwind v3 introduced this just-in-time JIT compiler that their approach if you're using
a project like React, and you can add in these arbitrary colors and CSS properties within
Tailwind utility classes, because the JIT compiler would be running in a dev server
and automatically generating CSS utility classes for you as needed.
So if you use something with an arbitrary color notation that defines a color that's
not in your Tailwind configuration, suddenly a CSS utility class would come into existence
in this JIT interpreter, and now your CSS file in your dev server would have that.
Whereas that became one challenge to support with Elm Tailwind modules.
But in addition to that, they just started throwing a whole bunch of different style
options and permutations at it.
And so the configuration blew up with a huge number of options.
So as I recall, there were around like 100,000 generated utilities in the default configuration
with v3, which became essentially unusable with a lot of tooling with IntelliSense.
And the compiler handles it pretty well, but editor tooling does not like that.
Yeah, exactly.
I remember it being a problem in the early days of Elm Review, where someone was making
this at the same time when there was a 75,000 lines of code Elm file.
And like, yeah, that is starting to be quite a big file for any tool like editors and Elm
And somehow it stopped being a problem because people stopped using that anyway, or that
approach of building a huge file.
So I'm glad about that.
Yeah, I think part of that is trying to hide it from the tools, trying to hide it in something
So for example, people do like using, well, the Elm package, Elm default Tailwind modules.
So that is just running Elm Tailwind modules, the code generator on the default Tailwind
And so if that's like hidden behind a library, then people still can use it, but their tooling
won't have to parse the whole thing all the time while they're working on their project.
But yeah, I'm glad I provide stress testing test cases to deal with.
I definitely had my fair share of problems with huge Elm files generated from Elm Tailwind
modules too.
I mean, you really don't have to provide stress tests, honestly.
I'd be fine without them at this point.
I'm sorry.
So when I think about like just this whole Tailwind approach of these utility classes,
like in a way, if you really think about it, a single utility class is almost like a notation
for parameterizing things.
So if you say like, LG colon hover colon text large, or something like that, you're saying
on a large screen on hover, make the text large.
And really, those are almost like things that you're composing together conceptually.
But as far as Tailwind utility classes go, it's giving you an actual class for every
possible thing you could do.
Which means like, if you do, you know, instead of large, instead of LG, you do SM, you do
small, and then hover and then something else, it's generating a class for every single thing
you do, which means every permutation of every possible thing gets generated, which is why
you have to prune the generated Tailwind CSS file, which is why you can't just like include
I mean, you actually, I'm not sure if with v3 you can because it's so huge now.
Back in the day, sometimes people would do that.
And it was like a 10 megabyte file with every possible permutation.
And that's why you use this sort of, you know, regex scanner to find the classes that you
use and don't use.
So the Tailwind can prune down to just the ones you use.
Elm Tailwind modules addresses that, like the earlier release addressed that problem
partially by making things composable with Elm CSS.
And then you had things like breakpoints generated a function.
So you do like, so you would get a breakpoint.large function, and that takes a list of Elm CSS
styles, and you can pass it other Tailwind styles.
So you can compose it together.
So essentially, it takes these things that just generate a CSS class for every possible
permutation of everything you could possibly express.
And it turns that into what it really more conceptually is, which is like composing together
these different pieces.
And so sort of like a good tool for that, right?
Now, this latest alpha release and this latest non alpha release of Elm default Tailwind
modules, the Elm package, kind of goes a step further with the composability.
So not only do you have the breakpoints being a function that more conceptually matches
what it's doing, this composable thing, instead of a bajillion permutations of everything
you could possibly do.
So what's the new development in the latest version, Philip?
You want to?
Yeah, sure.
So basically, before, if you, let's say you wanted to make an elements background blue.
So there would be one Tailwind class for that, that would be bg-blue-100, for example.
And so that sets the background color to the blue 100 color.
The blue 100 color is something that is defined in your Tailwind config, or it is coming from
the default Tailwind colors that is in your default Tailwind config.
In the new version, you would actually compose a function together with a value.
So very simple, you'd have bg underscore color being a function and you apply to it a blue
underscore 100 color from the theme module, which is a new module now generated in Tailwind
modules in the new alpha.
And so that makes it, that reads nicely.
You can technically abstract it if you, let's say, wanted to create some kind of view function
that is abstract over a bunch of colors.
You could do that.
You could apply the color later if you have a bunch of themes.
There's fun things you can do with it.
Previously, it would be really, really hard to create these composable view functions,
for example, because you're actually not allowed to, let's say you don't use Elm Tailwind modules,
you don't use any other Elm tools, you only compose these strings together in normal Tailwind
But then you wouldn't actually be able to break apart the string and choose the color,
essentially, from some computation, from an if expression or something like that.
Because then once you break up the string, the regex matcher from Tailwind CSS wouldn't
be able to recognize that you're using this utility, the CSS utility.
So that's something that is not much nicer, I think.
That makes the Elm version of it kind of nicer to use, I would argue.
Yeah, I really like that point.
I think when you are able to use the same mental model you use for writing Elm code
and the way that dead code illumination happens with Elm code, that's huge.
Because as you say, you don't have to get superstitious with your code where you say,
wait a minute, am I allowed to concatenate strings together or will that break things
in mysterious ways?
That doesn't feel great to have to think about that with Elm code, which is what happens
if you use vanilla Tailwind with a class string in Elm.
You have to worry about those spooky side effects at a distance.
In addition to that, like you said, you can have a button helper function that takes an
on hover color and a regular color for the background.
And now those are Elm values that you can pass to Elm functions because these generated
Tailwind helper functions that Elm Tailwind modules now generates for you are functions
that take color parameters.
So this is really nice from a developer experience perspective.
It also, I will note, I have a GitHub issue where I sort of explored the, I did my best
to remember my combinatorics math stats class.
I was never great at stats class.
So the number of lines to beat is 75,000.
Oh, yes.
Oh, I think we did.
The number of lines to beat is 75,000 for Tailwind version two.
So with Tailwind version three, they added like so many more definitions.
Even if you just had a single line for every definition, you would have a thousand lines,
a hundred thousand lines of code.
Yes, exactly.
So for Tailwind version three, I showed my work.
So if anybody doubts my stats calculation abilities, which I would not blame you for,
you can see I showed my work at least in this GitHub issue.
But it goes from a grand total of 88,320 down to 23 when you parameterize the color and
opacity variance.
So 88,000 to 23?
That's not every possible style, but at least that number, like, that's a subset of the
total possible styles.
But it did reduce by that amount, to put it that way.
You can think of it this way.
You're like, you actually only have 23 different kinds of small utilities.
Like you can change the accent color, you can change the background color, the text
Those are the 23 different things, and then you multiply that with every main color that
Tailwind has, and every variation that Tailwind has for every main color.
Then with every opacity that is possible with each of those colors, then you multiply that
with breakpoints and more and more, and you will get like huge and huge amounts of combinations.
And previously, Tailwind modules would generate all of that for you, thinking, well, it can
be deleted later.
But of course, that causes issues.
At one point, I generated a basically full configuration kind of file with Tailwind modules
as a test.
Basically, that's always running as a test in the generator code.
And so that includes the typography plugin for Tailwind, and I think, yeah, also another
plugin, but that may be unrelated.
And it clocked out at like 2 million lines of codes or more for like a full configuration
as an Elm file.
And that's just, well, that's a lot.
Tooling won't handle that well at all.
So yeah, that needed to change.
It's only 33 times more than that file that was already way too big.
Yes, exactly.
We can do better.
I'm sure we'll wait a couple of Tailwind versions, and we'll roll back to the old Elm Tailwind
modules version, and we can generate some massive new files for you.
So this changes, is it only for colors or is it also for other things that are somewhat
This version actually only abstracts out colors.
There are other possible things to abstract out, like spacing, variables, but for now,
it's only colors.
Why would you or would you not want to do things like spacing?
Well, it is basically something else to figure out exactly how to do it.
And there's always like a conversation to be had about how configurable do you want
your styles to be, because there is some value in restricting the set of possibilities, essentially.
So you have fewer things to choose from when you're building a front end, and you usually
end up with more consistent styles.
And you could pretty quickly argue that, well, if you have this utility that is literally
W-3, W-4, W-5, why not just abstract that out?
And instead of using these numbers, just literally pass in the integers.
At some point, well, that could be argued, and there's more to be figured out exactly.
Is that something that you should do?
Is that something that will destroy some value of Tailwind CSS, or is it not?
So basically, there's more thoughts to be had about that.
So Tailwind already limits what you can do, because for instance, you have W-3 pixels
or something, which says that something is three pixels wide, and you say, think four
or four, then you have eight, then 16, that kind of thing.
It's actually more abstracted.
It's not pixels.
They sort of have the configuration gives you these increments, but they're not defined
as pixels and they're abstracted away from that.
But yeah.
There's one pixel, I think.
And then it's that abstract thing.
Is there one pixel one?
Oh, nice.
I think so.
Because that could, I guess, be useful.
But yeah, so you already have a pretty restricted set of width that you can set.
So one, two, four, eight, 16, something like that.
So I could imagine that you could also, just like colors, just say, well, these are the
different possible values that you can pass.
It's one, some variants, one, variant two, variant 16, variant 32.
And I was like, would that make sense as well for Tailwind to parameterize some of these
functions the same way?
Again, to reduce the size of Tailwind and the number of generated utilities that you
Yes, I think so.
I think that would make sense.
There's just some thinking to be had about exactly how, like, perhaps we can put that
into a theme.
And like, we literally have a to do in the repo, which is do the same that we did with
auto abstracting the colors, and just auto abstract the spacing as well.
I think the space that we save from doing that is actually a little less than with colors,
because colors were just the more extreme case with more and more combinations.
I can see that.
Yeah, I actually did a few calculations on that in this GitHub issue.
And what I wrote is that from the v3 output with a default configuration, using the older
release of Elm Tailwind modules, 98% of the output was related to or 98% of the generated
definitions had colors in the name.
2% did not.
So 1600 did not have colors in the name.
80,875 did have colors in the name.
So that was the biggest one.
Because what it is, is it's like, you know, with combinations, when you're like, order
independent combining things, every time you add something, you're multiplying the number
of possibilities, just like adding a nested for loop, you know, so you go from O of N
to O of N squared, to O of N or, you know, O of M times N, if you prefer, you know, however
you want to call that, but effectively O of N squared and cubed, these colors were getting
into these deeply nested loops where you're multiplying, multiplying, multiplying.
And because it was, you know, the accent plus left or right or x or y plus or no, that would
be for border has those options.
Plus you can have a color strength, plus you can have a color opacity.
So it blew up pretty quickly.
Yeah, exactly.
But now, now the that's, that's all gone.
And instead, if you look at, for example, the Tailwind module, the utilities module
that is generated from the default Tailwind configuration, that clocks in at around 50,000
lines of code.
So we're, we're down a little from the 70 to 75,000.
However, we also like have a lot more stuff in that module.
So there's way, way more things you can, way more colors and combinations and stuff that
you can use.
And you heavily relying on Elms live code inclusion slash dead code elimination to reduce
that in practice, right?
Yeah, absolutely.
And one of these, one of the things that this really makes me kind of step back and think
about is, you know, we, we talked about this a little at some point, Philip, like when
you think about what, what is the value at that point?
And what are we actually doing here with like this library?
It makes you think about like, what now you've just got a bunch of functions for basically
like saying, this is a text background color, and here's a color that I'm passing into it.
And at that point, it almost becomes Elm CSS and except with like a design system.
So it, it really makes you think like, how, how does this compare to our platonic ideal
of a way of writing kind of a design system in Elm?
Like if we just wrote that from scratch, what would that look like?
And how does that compare to what Elm tailwind modules is generating for us now?
Yeah, that's, that's an interesting question.
Elm tailwind modules is definitely still like, most or a lot of its reasons for existence
is the whole ecosystem around tailwind.
But they're like, if you take all of that away, you quickly start to think about, well,
it's probably mostly a bunch of smart folks who've identified a good way to create utilities
to style web pages.
So they figured out which utilities are useful, and how to, well, how do I say this, basically,
they found a good way to factor utilities for styling HTML.
And if you take away all of the tailwind CSS stuff, and you start to abstract out these
utilities, you could think of like creating a something similar to Elm UI that has similar
utilities for setting the background color, and other CSS web API things.
And yeah, I think it looks a lot similar, very similar to something like Elm UI.
Yeah, if I think about like, let's say, I'm like, maybe even like kind of new to web development,
and, you know, familiar with Elm, and I'm like, okay, does Elm give me like a really
easy way to like style things like I love the simplicity of Elm, and not having to think
about weird mutations and side effects and things happening?
Is there something that makes me feel that way with the way you style things in Elm,
And, you know, Elm UI is one answer to that question that abstracts away all these things
that you don't have to think about centering an element and things like that, which is
When I think about the things like that are going to be stressful when you're getting
into web development, or like just for me, who's not super strong styling person, it's
like, should I use font size in pixels or REM or EM?
It's like there's so many, there's like analysis paralysis, where there are so many choices.
And you have to sort of navigate those choices.
It's not like here are a bunch of reasonable choices that will give you good results for
your users, accessibility, maintainable code.
It's like, yeah, here are a bunch of choices.
But if you use inconsistent options, or the wrong options, you will end up with unmaintainable
code and inaccessible code and bad things will happen.
And that sucks.
So that's one thing like when you do when you use Tailwind, what you're getting is like,
they made that choice of whether to use font size in pixels or EM or REM, which I don't
even know.
And I don't really care.
And I don't have to care.
And for most people just using like the built in Tailwind, like text large text small is
And you don't ever really have to think about that because they're really good at those
And they've researched them a lot.
So that's like a huge part of the value of it.
Like another thing that I wouldn't want to have to think about with CSS coming into Elm
as a new web developer is like defining my CSS classes and thinking about the cascading,
Elm UI sort of like addressed that problem in its own way of you don't have to think
about cascading because that that is a very stressful part of CSS.
And Tailwind utility classes approaches that problem in a different way, but it still solves
that problem.
You don't have to think about cascading because it's all just adding utility classes.
Yes, exactly.
You've got like the amazing community, all of these thoughtful design decisions that
go into it that you get for free.
You have a design system that constrains, like gives you guardrails of well thought
out steps for your sizing and margins and padding and things like that.
And now you start to be able to compose them together with functions where you can pass
in color, you can define a breakpoint and pass in all the things and use them programmatically.
And you can think of it just like Elm code.
And then the only thing that's left that I'm thinking like as somebody who's like, okay,
Elm makes so much sense.
What if I rethought CSS from scratch?
And now I'm like, well, there still is like margin versus padding, which one should I
And there still is like all these quirks of like flex, and I need to define flex in the
right place for a parent and things like that.
So those are the things that come to mind that are left that are like, that's not quite
the platonic ideal, but a lot of the things start to get pretty close to that.
Yes, exactly.
There's a lot of things.
I mean, I think that there will I think that a pure Elm solution would look a lot like
something like Elm UI.
But I think there is real value in just because we're not there today in reusing this huge
ecosystem of well, Tailwind CSS is very opinionated.
But at the same time, it is also very expressive.
And there's a lot of people out there who are writing Tailwind CSS.
They kind of share the same opinionated configuration, essentially, because they're all using Tailwind
So when you see something, let's say you're on, I think it was right.
And you have these prebuilt components, you can take them.
And because it's just HTML and uses these utility classes, they're just right in there.
You can reuse that you can use that for your stuff.
This helps beginners who don't know CSS very well, just taking that into their projects
and starting something with it.
If you just had a CSS file and an HTML file, then these can get out of sync and weirdly
combine and not work exactly correctly.
If you have a different kind of HTML structure and stuff like that.
So there's, I think there's huge value in that ecosystem.
And it's nice bringing that into Elm.
I should say Tailwind UI is the the creators of Tailwind CSS created a sort of component
like showcase.
It's like a set of components and screens that basically just gives you like the HTML
and Tailwind CSS classes for these common screens, a sales page, a blog post selection,
testimonials page, and they look really good.
And you can copy paste them into and even get Elm Tailwind module style syntax.
And I think from that perhaps, like we can also learn something.
I mean, Tailwind CSS is pretty good.
And it's nice to be able to take that ecosystem into Elm.
But of course, it's not perfect, right?
We still have 50,000 lines of code of utilities that could be better composable, we could
have spacing abstracted out, we could not have both padding and margin, and you don't
know which one to use.
We could not have I don't know, nowadays, it's too many ways of centering stuff.
Do you use text center?
Do you use margin auto?
Do you use items, center and flexbox or whatever it is?
Because still like it's not perfect.
But for something like that to exist in the Elm ecosystem, I would imagine it to be, let's
say it uses Elm UI, and it provides a bunch of that the value of the big value I see is
people publishing pre built components that you can take and modify to your needs.
So somebody has a dashboard kind of structure that you can just copy, and you can adapt
for your project.
Or there's something built with Elm UI that gives you a sidebar or a login form, those
kinds of things.
But then also learning from tailwind CSS, we know that likely you want to have a configuration
for your theme.
So there's going to be your company's CI in there.
And actually, what did CI stand for?
Corporate identity, right?
Okay, sorry, exactly.
That's what I wanted to figure out.
So the company's corporate identity is what I meant.
So the color theme that the company uses or something like that, that would be in your
And so those kinds of things, right?
You would have that with Elm UI.
And then I think you get into like a very similar kind of situation, a nice ecosystem
where you help juniors who maybe not know how to style stuff very effectively, or anyone
who wants to start up something.
I think for that, it would be really helpful.
Now, when you say Elm UI, do you literally mean Elm UI?
Elm UI as it exists now, obviously is not composable with these things that Elm Tailwind
modules generates, which are Elm CSS properties.
Do you mean exactly Elm UI or something with a similar interface to Elm UI?
Yeah, basically, what I'm getting at is you could build something on top of Elm UI that
well, because Elm UI improves upon not having both padding and margin and these kinds of
things, but it does not have the configuration.
I think it would be valuable if you had something like these component libraries that others
are building, and but they would be configurable with some kind of configuration.
And you essentially build something like Tailwind CSS, but around Elm UI.
I can imagine something like that.
That's very interesting, although it does become difficult, because you talked about
like being able to tap into this giant community, and set of resources for Tailwind.
And so if you've got if you go to Tailwind, and you go copy paste some HTML from
there, and it uses margins and padding, yes, you definitely lose that ecosystem.
That is true.
Basically, I see this as a thought exercise, like what is the what is the perfect version
look like?
Having learned from what Tailwind CSS has done, right?
I mean, we should just compile every component to the equivalent to HTML binary or something.
And then you can, then you can compile that components that you found on the on the internet,
and just keep using your own configuration.
Oh, yeah, that would be interesting.
This was just a very random idea.
Or perhaps, perhaps you don't even need to do the copy pasting thing.
And at the end of the day, maybe that's the wrong flow.
And you can actually reasonably abstract stuff and just use a function from a package, perhaps,
perhaps not, I don't know, maybe the equivalent of Tailwind UI and Tailwind CSS would just
be packages and functions.
But yeah, nobody's built that yet.
Exactly the way I described, I think, I don't know.
So I feel like I missed something or unclear about something.
Is it possible in Tailwind to say, remove all the classes related to margin or to padding
or whatever?
No, sorry.
I don't know.
That's not possible.
Or perhaps I'm misunderstanding something.
Yeah, I mean, it is interesting, because there is this sort of quality in the Elm community.
There's a willingness to think things up from scratch.
And sometimes say, like, hey, here's this way of solving problems.
And it doesn't support every possible way of solving problems.
And that's the point.
And we don't give you escape hatches even for that.
So if you don't like it, then use another package that lets you do that or drop down
to a lower level thing.
Like that's kind of, that's an approach that's pretty common in Elm.
And it's one of the things we love about it, but it definitely has trade offs.
So I mean, it seems Elm Tailwind modules as it stands, is a pretty darn good balance of
like, you know, being able to use a well thought out design system and all these great things.
But it actually, it doesn't limit what you can do at all.
And also you can do semantic HTML and you can, you can use margin if you need to.
But at least like, it gives you these things that are easily within reach, where you usually
don't have to think about those weird corner cases most of the time.
So it's like, it's pretty close.
Yeah, I think so too.
I mean, yeah, there's still a bunch of things that aren't exactly perfect, but those go
deep down into the browser and the platform that we're building on, right?
Web API is in CSS.
And yeah, those will take a longer time to improve, I guess.
Is there anything on your radar that you are keen to explore next?
Or are you not thinking about that at this stage?
Well, one thing is I would like to, for Elm Tailwind modules, I would like to explore
a different way of generating the modules.
Essentially, what happens right now is that the Tailwind configuration is fed into Tailwind
And Tailwind CSS will generate a huge CSS file.
And that CSS file is processed by Elm Tailwind modules.
And that means that this process of creating all of the different variants, this explosion,
this combinatorial explosion, that does still happen, but it's in the background, kind of.
There's no files generated with it.
But it still needs to happen.
And we should, or it should actually, or Elm Tailwind modules should just connect to Tailwind
CSS at a different level, before Tailwind CSS actually generates all the combinations
of the way that utilities can be built.
But that's kind of inside Tailwind CSS.
So it's a little harder to get to.
But I believe that we could do that.
And we would get a lot of things for free.
So this would mostly be for performance, I'm guessing.
But is that a, I'm curious, is that a problem?
Because how long does it take for Tailwind to run?
And is it a problem for people who have JavaScript projects, which don't use Elm Tailwind modules?
So for regular Tailwind, they have optimizations in place to not do all of that work.
But we can't use them in Tailwind, Elm Tailwind modules, because basically, these optimizations
rely on regex matching, and going into your code where we actually use the Tailwind configurations
and figuring out exactly what you need.
Use of that.
Okay, so usually, the regular Tailwind, it looks at your code and then generates what
is necessary.
Whereas your approach is we generate everything.
And then Elm's data code elimination will remove what is unnecessary.
And we also in between have this abstraction step where all the combinations get compressed
down in just a smaller set of combinations.
And you can actually compose them using functions and values.
And that process takes like, on my machine, I think it's like 20 seconds.
So it can be pretty long.
And depending on what you do, that is fine.
So for example, if you have some Tailwind configuration, and you're just generating
it once, then well, 20 seconds isn't too bad.
But of course, if you're constantly tweaking your configuration, that will not be fun.
And also, we may be imprecise.
We don't we haven't tested every possible Tailwind configuration out there.
There may be bugs hidden in the code.
That's why it's still an alpha.
And I think, well, it's going to be hard to squash every possible bug out there.
I don't think that people will hit lots of them in practice.
But still, it would be a way more resilient kind of way of generating these Elm modules.
If they were generated from that part in Tailwind CSS that still knows about, like, these are
colors and they get combined with this kind of utility, instead of having to guess what
the combinations are afterwards.
Yeah, does Tailwind have a plugin system for this kind of thing?
I know it has a plugin system, but I don't know what those plugins can do and what they
can't do.
So basically, if you're, I'm not extremely familiar with Tailwind CSS internals.
They don't have a out of the box plugin system for something or that Elm Tailwind modules
could use their plugin system.
It's correct.
They have one, you can basically add things that generate more combinatorial stuff.
So let's say you wanted to, I don't know, there's a new web API, and suddenly you can
define the color of your cursor or something like that.
Maybe that even exists, who knows.
And then you could go in and add like a Tailwind plugin and say, okay, this Tailwind plugin
is some JavaScript function and it generates a CSS definition that says cursor color colon,
and then insert here every possible Tailwind configuration color from the theme.
And so hooking into that step before these combinations get executed, essentially, would
be nice for Elm Tailwind modules.
That should reduce the time, that should make it easy for abstracting out spacing to and
other things.
So yeah, that would be the hope.
That would be a next step, I think.
I actually wondered, like, if Tailwind adds a new feature, a new utility, do you need
to do anything in your project to make that work?
Or let's imagine we, Tailwind added that cursor color feature.
Would you need to do anything?
Luckily not, no.
I mean, the version 3 update was something bigger for Elm Tailwind modules to support,
but all of the minor updates so far seemed to go pretty smoothly.
Yeah, so basically, there's no manual work involved with that.
And I can't, I mean, basically what happens with new Tailwind versions is when they add
new utilities, they essentially just change the Tailwind configuration.
And I need to, or Elm Tailwind modules needs to support many different kinds of Tailwind
configurations out of the box anyway, and combinations of additional plugins that people
may want to install.
And so yeah, that should work out of the box.
So Tailwind v3, one of the curveballs that it threw at your library, among other things,
was this way of this arbitrary syntax.
So like there is a way now in Tailwind of expressing an arbitrary color.
Like an example they give is, you know, if you have your, I guess your CI colors, your
corporate identity colors that you use for your color palette in your Tailwind config,
you might have a link to Twitter and LinkedIn and whatever.
But those aren't part of your design system and you don't want them to be.
You just want to say like, I want to drop out of our design system for a moment and
just use Twitter blue.
And I don't want to pollute my design system with that because I don't want people making
buy now button that's Twitter blue because it's not part of our design system.
So there's a syntax for doing arbitrary colors in Tailwind CSS.
You want to talk a little bit about the like design decisions behind this and maybe the,
you've got the Elm Tailwind modules base Elm package, which just gives a couple of color
So there's, I mean, there's a little bit of a debate around that, I guess, or initially,
because well, one response to that Tailwind feature at the beginning could have been,
well, why not use inline styles for this if you'd need it sometimes.
You could do the same thing with Elm CSS and like add some inline styles, but the thing
is once you do that, you're out of Tailwind CSS land.
And there's a couple of things that Tailwind CSS does.
So everything fits together nicely.
Like for example, it passes down opacity into like sub elements, essentially.
It handles that nicely.
There's basically it does a bunch of additional things sometimes around basic styles, which
you would expect would be basic, but turn out have some nice hooks here and there.
Another example would be like font size is something that is like you can locally change
that and it should work nicely with Tailwind CSS.
And it would be nice to hook into that or into Tailwind CSS in a way that doesn't bypass
it completely.
And so that is possible with this, with these helpers.
So you can, instead of just using one of the predefined theme things, you can use your
own color if you need to.
And there's going to be like arbitrary RBGA, I think it's called in the base library that
every generated code depends on.
You can use that.
So basically, I thought, well, if they decide to do that, let's do this as well.
You won't see this in the very beginning.
So if you're only depending on default Tailwind modules, you will not see that there is an
arbitrary way to do this or to add colors because you should instead just have your
config and add colors that you need into your config.
But if you really want to or need to go outside of that, there is a way to do that, which
doesn't bypass any Tailwind CSS generated things.
So it's, it kind of seems like a, you do want to a certain extent to be able to say, okay,
we have this design system, so I don't have, and as Elm developers, we really want to be
able to say, what are the guarantees I can depend on?
And so like design system, it's constraints.
You say like, what guarantees do I get from those constraints?
Are they like full guarantees or are they like partial guarantees?
And, and then, so this arbitrary RGB and arbitrary RGBA, these functions that are provided for
the color type in this generated code is an escape patch in a sense.
I mean, it's something that now exists in Tailwind.
So you could argue it's just following the Tailwind semantics, but it also is an escape
patch from the Tailwind design system.
But I hear there's a tool that helps you do static analysis to give you additional guarantees
around this type of thing.
So I think this is the perfect use case for Elm Review to just have this be, if you want
to, a forbidden function or forbidden in certain contexts.
Oh, that's an interesting idea.
Yeah, yeah.
But that would be something to turn on per project, for example.
So yeah, I haven't actually thought about that.
I mean, I guess to some extent, you could just have an Elm Review rule that checks that
any class that you're using is a Tailwind class, is an existing Tailwind class.
Because the original problem of your project is if you make a typo in a Tailwind class,
then it's not going to take effect.
And you want to know about that.
So that's why we go with the type safe route of creating functions and creating variables
so that the compiler helps us.
But you could do it using Elm Review.
But then you do need restrictions, like you only want to report things that you know are
used as classes and not are just arbitrary strings, because we have the same syntax for
defining both, right?
Just string literals.
So you do need to know in which context you are.
Yeah, absolutely.
And also you re-inherit these problems that the original Tailwind CSS had as well, which
you can't break up the literal in the middle.
If you have bg-blue100, and you want to combine, instead, like do a string concat of bg- and
then color, and color is a variable.
And that's like a string passed in or something like that.
That won't work.
But yeah, you could do an Elm Review rule like that.
Yeah, and you lose the ability to get dead code elimination through the Elm compiler.
So Tailwind does have something to that effect.
I don't know how well it works in practice, if it works as well as the Elm compiler or
better or worse.
I don't know.
But yeah, then you would have to rely again on Tailwind's way of doing things and you
might get false.
It might not delete as much as you want.
But definitely an interesting approach as well, but different.
Very different.
It does make me think, so you're talking about the vanilla Tailwind CSS approach to using
Elm CSS classes that point to Tailwind CSS utilities.
And it makes me think, is there a reason for some users not to switch?
Or is it mostly at this point, it's a lot of work and I haven't done the upgrade yet?
For example,, slightly embarrassingly, I mean, it's three years old, so it predates
Elm Tailwind modules, but it uses vanilla Tailwind CSS utility classes.
But you kind of don't want to break anything in its CSS, so that's scary.
So it's a big upgrade job.
But I do have the site, which as we talked about, lets you convert Tailwind
classes to Elm Tailwind modules syntax.
And there's also the companion Elm Review rule that lets you take a debug.todo string
where the string has HTML and it will convert that string to HTML.
And it even uses the import context, we talked about this in the previous Elm Tailwind modules
But that Elm Review rule provides a fix that converts an HTML string to an Elm Tailwind
modules HTML snippet.
And now it's striking me that it would actually be really handy to just have an Elm Review
version of that rule for class attributes to go in and change those class attributes,
not the entire HTML snippet.
And I think I could do that.
And that would like, for example, for me resisting going in and upgrading from vanilla Tailwind
to Elm Tailwind modules in the Elm Radio site, that would...
This is like the tooling author's thought process, right?
I wouldn't want to manually do it, but what if I built a tool that did it for me?
I mean, luckily, this doesn't take extremely long anymore now that we have Elm Review,
like going through all of the Elm code or building like a parser or something that would
have been extremely hard.
But yes, it might actually save time in total.
That's the goal with tooling authors is that you're like, eventually it's going to pay
And in my life, I'll have spent less time building tools than I would have manually
building on these things.
I mean, I don't think it's a lie that even we believe in.
It's just like the way that I like to myself is like, oh, well, at least it's going to
be useful to other people.
Because I can't just lie and say, well, this is going to save me some time.
Like, no.
It's more fun anyway.
So yeah.
It's the arbitrary condiment passing utility from XKCD.
But yeah, it sounds good.
Sounds like exactly the thing we described before.
But except instead of checking, you just transform it into the Elm Table modules version.
Is there like a kind of there definitely is a fix all in Elm Review, right?
Oh, wow.
That would be quite amazing if you managed to just fix all and you turn any vanilla Tailwind
CSS Elm project into a Elm Table modules project.
That would be awesome, right?
Pretty amazing.
The really cool thing, like, so, you know, because Elm Review gives you access to all
these things, you can like look at imports and stuff, right?
So the rule I have for the string to HTML snippet one looks at your import context and
it uses all of your imports and exposed values.
So if you like do import HTML styled, is it?
Import HTML styled exposing dot dot, then it will use just div and span instead of HTML
dot style dot div.
So if you do import HTML dot styled as HTML, it will do HTML dot div, for example.
Yeah, it's super powerful.
I was going to ask you, Philip, if you had tips on how to switch from Elm HTML to Elm
CSS because to use your project, people need to switch to Elm CSS first.
But now I feel like the answer is just going to be, well, we can rise an Elm Review rule
for that.
So I mean, that would be amazing, right?
I mean, also like Elm CSS is basically a superset of Elm HTML anyway.
So I don't think it's going to be very hard anyway.
Just change the imports and that's mostly going to be it, I'm guessing.
I mean, yeah, I haven't done like an upgrade in that kind recently.
But yeah, as far as I know, it should be straightforward.
And it seemed to have worked really well for Elm Radio.
The other cool thing with like building these kind of Elm Review code mod tools is you can
have a folder in the repo with a review configuration.
So like, let's say it's Elm HTML to Elm CSS.
You can have a configuration that just is an Elm Review config folder that only has
that one rule.
And then you can run Elm Review with dash dash template and point it to that repo.
And you don't need to like, temporarily set up the rule in your config folder.
So you can give somebody a single command to run, and it'll just run the code mod.
So that's pretty cool, too.
Yeah, actually, it's dash dash config dash dash template is if you want to run a configuration
that is hosted on GitHub somewhere.
So you actually don't even need to have it on your machine, you can do it.
If the rule exists somewhere in GitHub, then that will also work.
Wait, but you do that.
Yeah, but I was talking about if you host it on GitHub.
So if you have on GitHub, just a folder that has your code mod review rule, then you can
give them a single command, they don't need to download anything or set up a temporary
configure anything.
Yeah, absolutely.
At this point, Elm Review, have you have you thought about a rename of Elm Review?
Because like code mod, that sounds, sounds like more than review.
And it's like Elm Review is underselling it.
I mean, to some extent, this is like a topic for us not really to tell when they're anymore.
But I mean, to some extent, like, I don't even know if a code mod is a term that is
used elsewhere than in the JavaScript community.
Maybe it is.
That's where I encountered it, at least.
But even just like linters, they do the same thing as Elm Review, they just usually do
it worse.
And even just a linter is a very bad name.
Yeah, I guess linters just have gotten meaning, because they existed and didn't really, I
personally didn't know what that would mean before.
Yeah, well, yeah, well, actually, lint are those, those tiny pieces of fabric that you
find in your clothes.
So linting is the process of accumulating those, not of cleaning them.
So linter is technically something that adds garbage to your code.
Yeah, I guess there are some people who feel like that.
Yeah, yeah.
Well, if you had all those disabled comments, then yes, I agree.
But so only for this reason, for this reason alone, I'm already pretty happy I didn't call
it Elm Lint.
Actually, that I renamed it.
But yeah.
So yeah, that's...
That's a side topic.
Always happy to talk about Elm Review.
It is a really good pairing.
And it could even be cool to, well, maybe it's overboard, but the Elm Tailwind modules
base package, I was thinking could even expose an Elm Review rule that helps you avoid the
arbitrary RGB.
Although at that point, like, there are packages that have forbidden functions and things like
that, so it's probably better to use a standard tool for that.
So are there any tips we should give people who, let's say somebody is upgrading from
the previous release of Elm Tailwind modules to the alpha?
First of all, how can they help you through the alpha process?
And secondly, what does the upgrade process look like for them?
So the upgrade process is upgrade your npm package, and you can do that with npm i dash
dash save Elm Tailwind modules at alpha.
So no need to remember the version or anything.
Once you do that, rerun it to get like all the new Tailwind modules.
And you'll basically have to replace bg underscore blue, etc. with bg color.
And then another import of the theme module, which is now new, and whatever color you were
using from that theme module.
I'm guessing you will get compiler errors for all the things that you should do.
And I mean, yeah, that's that's the power of it, right?
You can you can change the way it works, and you'll get compiler errors, and you just fix
them everywhere.
And it should definitely just work.
Remember to add your global styles to your style sheet.
I've had some people now hit with a new Tailwind.
The way the new Tailwind version works, they've had issues with suddenly it working less well
with the global style.
So there's like one global styles thing that is basically kind of a style reset that Tailwind
needs to work.
But apparently it worked okay without using this.
Previously, it doesn't do that as well anymore.
So it's not intended to be used that way.
So just just include it.
Yeah, that might be a feature, not a bug.
Yeah, it definitely was an unintended feature.
There's no way I mean, we should have an Elm review rule for that.
But yeah, do that.
And then just try out the alpha.
It should actually be very straightforward.
But if you do hit some issues, like contacting me, whatever way feels comfortable for you,
DM me on Slack, or write an issue up on the Elm Tailwind modules or Elm default Tailwind
modules, GitHub, Issue Tracker, and then yeah, that's the perfect way.
Eventually, I'll just announce the at least the alpha or even the finished, finished,
I guess, while the final new version on the Elm discourse.
And for people looking to try it out, like, do you have any guidance on you have this
Elm default Tailwind modules package, which as we talked about, it's an Elm package that
is basically a packaged up version of the default Tailwind config with the generated
code from Elm Tailwind modules.
So you don't need to install an npm package to use that one.
It's like much easier to get set up if you want to try it out.
Do you think that people should eventually outgrow that?
Or is it okay if certain people don't outgrow that, for example,
I mean, it's up to you.
I personally think there's like, I will have a lot of personal projects that I will just
do with Elm default Tailwind modules, because I don't feel like creating my own color scheme.
And basically, that's what you want to do with your custom config.
There's some other things like if you really want to have something very production ready,
you can add your custom plugins to Tailwind to for example, what is it auto prefixes one
of them, but I think that that is even auto installed with default Tailwind modules.
But plugins like that, which make it work on more devices, let's say, that add polyfills
for older CSS classes for newer CSS classes that didn't exist previously.
So these kinds of things, if you really want to have something polished, then graduate.
But honestly, I really like the flow personally of using just default Tailwind modules.
Yeah, I'm a big fan of being able to I use a lot.
It's a paid library of components and styles, but it's like so so worth it.
For me, it has been and if you use the default configuration, the things look like they look
on the site, and you copy paste the styles and they just work, you don't have to tweak
it to use your naming convention for your color, style system and stuff.
So I kind of like that, like, maybe I'll change indigo or whatever to whatever color I'm using.
But other than that, like, I can just drop things in.
So there's, it's kind of like the debate of like, how much customization do you do on
your system versus using the default keyboard shortcuts and keyboard layout so you can go
to someone else's machine and work with them.
I was going to say like, you probably don't need to upgrade from default Tailwind modules.
If you don't have a corporate identity.
So now you're saying that the Elm reader doesn't have a corporate identity.
Yes, I'm sorry.
I guess we do have an identity.
It's just not a corporation.
Makes sense, I guess.
I mean, you can you can build your identity on top of tailwind colors.
We've learned that version three has like a bazillion more colors than previously.
Or is it simpler to just build a corporation?
I mean, maybe at this point, you know.
Well, amazing stuff, Philip.
And thanks again for all your work on this awesome project.
And thanks for coming on the show.
Thank you for helping with it as well.
And thank you for having me.
It's a pleasure.
And Jeroen, until next time.
Until next time.