To stop bikeshedding, quickly gleam add glaze_oat, then make it work!
make it work, then make it beautifulSeems like popular and good advice on Gleam discord (from Joe Armstrong at some point? idk the exact source). In general yeah it's true. However when writing application pages I just can't bring myself to stop bikeshedding how pages look. It really slows me down because I'm not good at CSS so it takes me hours to get it looking right (which ofc is all wasted when I later throw the whole thing away to do something else), but I'm also unable to just say ok well it works I'll make it beautiful later. It's also very demotivating for pages to look ugly. This is especially true when looking for validation for non software people (ie my wife) who care much more how it looks than, idk, if the API to get a patient returns typesafe error variants. Finally the "first make it work" approach is definitely true for algorithms and such, but maybe for UIs figuring out figuring out what to do is figuring out what looks good. So I've wasted a lot of time messing around with CSS...
glaze_oat cuts down that time by a lot by providing Lustre components from Oat UI, which are elements like button, dialog, table, etc. that come with nice premade styling and behavior.
Ofc one way is to ask chatgpt to spit out some CSS or tailwind or whatever. Honestly this tempts me, I don't really love CSS or care to understand it. That said for PotatoEMR I want to keep "no AI written code in the application itself" a simple rule (maybe not totally simple because the FHIR library's code generator is total slop, but my goal is for the generated FHIR code be nice and readable for humans even though the generator itself is not).
At first I tried classless css stylesheets, hoping I could just slap those on and write HTML, and swapping between various classless stylesheets would be easy in CSS zen garden kind of way. But they ended up needing a lot of fiddling with specific things and didn't provide a sidebar. Also none of them seemed designed for phones. I would like to just write HTML but classless CSS feels much more for blogs and stuff than applications, oh well.
Another alternative is glaze_basecoat which binds to Combobox, Oat instead has a TagInput with autocomplete using native datalist, idk will probably see eventually if I'm missing something important with Oat but for now it seems good. I also felt like basecoat docs eg Sidebar felt a bit AI generated:
Sidebar uses a native <aside> next to your page content. Basecoat owns the fixed positioning, overlay behavior, active states, nested lists, and details submenu styling. Your app still owns the navigation data and current route.
It's not terrible, there's definitely worse AI text and idk what even puts me on edge about it, maybe the use of "owns". But between that and Basecoat having AGENTS.md whereas Oat feels 100% human, it's a point in Oat's favor. Not to malign Basecoat too much though, it's not slop and there's a real guy behind it/owning it so it could totally be a good choice.
Ideally you can just slap Oat on it and not have to mess around with custom styling. But maybe you do want some particular style, ok just put standard Lustre attributes. The one exception I was not happy with is hover styling, for some reason CSS can't do hover as inline style, so I have this garbage:
table.container([], [
h.style(
[],
// can't do hover style inline
// oat puts hover on row, but for calendar we want it on individual cell, and not first hour cell
"
.highlight-one-cell tbody tr {
&:hover {
background-color: transparent;
}
}
.highlight-one-cell tbody td:not(:first-child) {
transition: background-color var(--transition-fast);
&:hover {
background-color: rgb(from var(--muted) r g b / .5)
}
}
",
),
...
In general I like Oat's default of hover higlighting table row, which makes sense for patient lookup, but for selecting individual calendar cell obviously need to change that, which is all fine, I just wish you could use inline style from Lustre attribute directly on the element instead of some class. Just my rant but I can never reason about what CSS class is applied from where; tracking Gleam function composition feels much (for me).