Sure, semantic is good, but that selector doesn’t do the same thing. :invalid is the default for any input type where empty is invalid. You also get quite a lot of flickering for certain types (which can be fine, it depends on the goals)
Next sibling selector tend to be quite volatile in my experience since it locks visuals to markup order.
There are plenty of ways of doing this, the core of it is to avoid variables to make diffs smaller for LV.
You can use :user-invalid then. Doesn’t really matter, I was talking about idea rather than particular implementation there. Main thing here is that it forces you to use aria-invalid attribute instead of custom class, which will help with a11y, and will leave classes and stuff for sensible data.
Because there are many components about +90 components and it needs huge time and efforts to convert all of them to Pure Css!! and we are just 2 persons that are working on the them
At the risk of being off-topic, I’d be curious to know what your setup looks like using Rsbuild. On a personal note, I was trying to fork the esbuild package to turn it into something that could run/manage rsbuild installations. Would this be something you would find valuable?
Having an esbuild package, is a way to fix the version…
In the past sass broke a Phoenix version. Nothing to do with Phoenix, nor Webpack… it was sass and because of this a lot of time has been spent for nothing
I am not sure a rsbuild package is required, I usually do npm i -D and use the current version of the dev dependencies
I wrote this code ages ago and it remains by far the most utility I have ever managed to extract from one stupid hack. It’s literally just a mediocre CSS parser/generator (which I desperately need to rewrite from scratch) and a macro/compiler that hijacks the HEEx and rewrites it with a stupid regex because I was too lazy to parse the HTML.
And yet, despite that, it’s been essentially the perfect solution. Here is what some of the components look like. I use nothing but vanilla CSS (with a shorthand $variable syntax because I am not writing var(--variable) 10,000 times). I can always use the latest CSS features and never have to worry about framework churn.
But I also inherit all of the best parts of Tailwind. Styles are co-located and scoped to their components. Dead styles are easily eliminated due to the co-location. Composability is not an issue due to scoping. There is no jumping around, and no worrying about name collisions.
The final advantage of Tailwind, perhaps the biggest, is that you get an extensible design system out of the box. So I built that too! The defaults are here, but I designed it to expand the design system recursively. Here’s my default. It even has themes! I then have app configs which in turn extend that one.
I’m used to things having tradeoffs but to be totally honest, for me, this remains the uncontested perfect solution. I have run into no meaningful problems with this approach.
I think I will clean this up and turn it into a real library (yes this is like the 10th time I’ve said this) once macro components ship as they will make it much less hacky. I’ll probably extract the CSS parser/generator to a separate library and maybe try to make it composable (like PostCSS or something, so people can minify etc if they want).
I use vanilla CSS with CSS variables. I agree with the points above on Tailwind and think it’s an unnecessary abstraction. I hadn’t considered the Would be great to see Phoenix move to scoped CSS and make tailwind an opt-in.
Sounds like a great lib. I’d happily be a user. I wonder if Hologram could take advantage as well.
The thing about Tailwind is that it’s a legitimate solution to these problems and so from that perspective I want to defend it.
But on the other hand the implementation is just totally hideous and degenerate, and scoped CSS is so much better in this regard. I really cannot advocate for that approach enough.
Noted!
Actually there is a good argument for the design system parts working across frameworks here, since a design system is often shared across an org rather than just an app. Even in my case I am reaching the end of the research phase for my JS frontend framework (if you remember my posts on that) and I’m going to start the implementation shortly. I will definitely be finding a way to bring corp_style along for the ride (the joys of controlling your own abstractions) as I don’t think I could live without it at this point!
Interop would be nice as I intend to keep using LiveView for some things even though I’ve really been feeling the limitations lately on the app side.
It’s too much of a digression to get into here. I’ll be posting about my apps very soon (for real this time unironically, the database has been slayed) and I can discuss it there with specific examples.
But tldr nothing I haven’t posted about before, specifically with regard to component composability. The only difference is I now know how to properly design a reactive framework (literally React-ive) and I can see where the problems actually lie in LV’s engine. These are things that could be fixed but it would be nontrivial. The (heroic) work by Jose and Steffen to diff :key properly was a big step in the right direction.
We’re using SCSS. The setup is based on Barker, with variations. Design tokens are defined with Style Dictionary, which supports different output formats and also allows to define custom output formats. This allows us to separate the canonical design token definition from the actual implementation. You might need the same tokens in a different format for a native app, for example.
Barker includes a couple of SASS functions for accessing the exported design tokens / variables (although you can also use the exported SASS variables directly; SASS variables and functions map to CSS custom properties, not values, making it theme-able), and generates a couple of utility classes based on them for one-off styles. Most styles are defined on a component level, though. Styles are separated between components (what is the thing, e.g. a card) and layouts (how is the thing arranged, e.g. a card grid) as much as possible. We also use some of the layouts as described in the already mentioned Every Layout.
As for why I don’t like Tailwind: I don’t think it solves the problems it claims to solve. It introduces new problems. It drags you away from standard CSS. Vendor lock-in (ever tried removing Tailwind from an existing project?). There are plenty of articles pointing out the issues in more detail, for example:
This PR was the bulk of it, I think. There was some other related activity if you look for PRs around that time.
The first version of the :key optimization (which is itself a very important addition) essentially expected global keys (because LiveComponents use global keys) which is a massive footgun. Somebody (me) complained that it wasn’t composable and apparently created multiple weeks of work for poor Jose and Steffen (sorry). They pulled it off, though!
Reading through that PR and the new engine code is on my todo list because I still don’t actually know what dark magic they invoked to get it to work
What have you experienced in this regard? I have not used Tailwind on a massive project before, but one thing I like better about Tailwind is that I find it much easier to determined what is actually being used. In my experience, projects using vanilla CSS have a tendency to accumulate pointless rules that no one is 100% if they are required or not.