-
Notifications
You must be signed in to change notification settings - Fork 1
Description
We have a decision to make about how to handle CSS and basic UI components, now that we have a Haskell frontend. There are at least the following options:
Raw CSS stylesheets
Pros
- Very well supported in browser tooling.
- Full control — anything CSS can do, we can do.
- Great interactive dev experience — just edit the stylesheet and reload (possibly not even required).
- No need to shoehorn tooling designed for the Node/JavaScript ecosystem into our build system.
Cons
- Big learning curve.
- Editing raw CSS is not very nice.
- Dealing with browser idiosyncrasies/supported features is on us.
- Dealing with responsive design is on us.
- Lots of reinventing the wheel.
Use Clay to generate CSS stylesheets
Using Clay as it's intended to be used — that is, to generate CSS stylesheets — is probably preferable to raw CSS stylesheets in every way except for the interactive dev experience, though we could surely find a "watch" tool that triggers a Clay build every time the source files are edited.
Pros
- Full control — anything CSS can do, we can do.
- Infinitely more composable/modular than raw CSS stylesheets.
- At least some degree of type checking.
- No need to shoehorn tooling designed for the Node/JavaScript ecosystem into our build system.
Cons
- Big learning curve — we're still writing CSS.
- Dealing with browser idiosyncrasies/supported features is on us.
- Dealing with responsive design is on us.
- Lots of reinventing the wheel.
- Concerns about Clay's level of maintenance — it doesn't appear to be particularly actively developed.
Per-component CSS styling with Miso.CSS
As I understand it, Miso now supports per-Component styling, and it seems to have fairly good coverage of CSS via its Miso.CSS DSL. We plan to use Miso's Components, so if we wanted to go with the in vogue Tailwind-like approach of local styling instead of an app-wide stylesheet, we could do it this way without actually using Tailwind. As all of the controls in the app would be Components anyway, there shouldn't be any DRY concerns.
Pros
- Full control — anything CSS can do, we can do.
- Infinitely more composable/modular than raw CSS stylesheets.
- At least some degree of type checking.
- No need to shoehorn tooling designed for the Node/JavaScript ecosystem into our build system.
- All the advantages of the Tailwind-like local styling approach.
Cons
- Big learning curve — we're still writing CSS.
- Dealing with browser idiosyncrasies/supported features is on us.
- Dealing with responsive design is on us.
- Lots of reinventing the wheel.
- All the disadvantages of the Tailwind-like local styling approach.
Shoehorn Tailwind into our build system
As I understand it, Tailwind is basically just some baked-out CSS stylesheets and maybe a bit of runtime JavaScript. Though Tailwind's tooling effectively requires that you use npm and write a bit of JavaScript to configure it, there are some non-JavaScript web development environments that make use of it (e.g., Trunk and Leptos for Rust).
Following the Leptos example, it should be possible to add Tailwind's tooling to our development environment, configure it as you would in a JavaScript project, and then configure Tailwind to search for its classes in .hs files.
Ref:
- https://old.reddit.com/r/rust/comments/14nxygv/psa_rust_web_frontend_with_tailwind_is_easy/
- Leptos is becoming best rust web framwork and How to set up leptos-rs/leptos#125
- Beginner tutorial for setting up tailwind v 4 using the standalone CLI (no node.js) tailwindlabs/tailwindcss#15855
Pros
- All the advantages of the Tailwind-like local styling approach.
Cons
- Still some reinventing the wheel, since Tailwind doesn't deliver components, only styling.
- All the disadvantages of the Tailwind-like local styling approach.
- Using Tailwind in a way it really wasn't designed for — it's unknown how fragile this approach would be.
Use Basecoat
Basecoat is a robust component library that uses Tailwind for styling. It differs from all of the other options I've listed here in that it doesn't just provide styling for components, but actual working components like buttons and drop-downs. As it doesn't require React, we could in theory use it with Primer — just link to 2 pre-compiled blobs (one for CSS, and one for a bit of self-contained JavaScript for the interactive components) and start using its components.
However, based on my experimentation with Basecoat over the past few days, I think we'd still need to install Tailwind's tooling (and possibly Basecoat's own tooling) to take full advantage of it. If Primer were just a run-of-the-mill CRUD app, I think the static Basecoat blobs would be sufficient, but I think vanilla Basecoat is a bit too opinionated for our needs, and therefore we're likely to need its support for Tailwind themes, at the very least; and at that point, we're basically using the full Tailscale CLI again, with all the drawbacks as described earlier.
We do still need custom UI components that neither Basecoat nor any other component library provides (e.g., tree rendering), but if we choose the Basecoat option, we shouldn't need to reinvent (m)any wheels, even if we completely replace its styling choices.
Pros
- All the advantages of the Tailwind-like local styling approach.
- Should provide all of our basic UI component needs.
Cons
- All the disadvantages of the Tailwind-like local styling approach.
- Using Tailwind in a way it really wasn't designed for — it's unknown how fragile this approach would be.