Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better styling #1316

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open

Better styling #1316

wants to merge 38 commits into from

Conversation

georgefst
Copy link
Contributor

@georgefst georgefst commented Jan 9, 2025

In a break from tradition, I would strongly recommend not attempting to review this one-commit-at-a-time. At this early stage of the frontend project, it's natural for there to be big sweeping changes, and it's the final state of this PR that's important, with the intermediate states best left as historical curiosities...

Given that we've said styling isn't the most important thing right now, I may have gotten a bit carried away here! But as well as taking us away from messy string concatenation for styles, this work has prompted several more general refactors, leaving the app in great shape for future work. Plus, some of the styling improvements are really about basic usability. For example, when I was working on a proof-of-concept for applying actions a few weeks ago, it was hard to debug without the current selection being indicated. Similarly, the recently-added definition panel buttons were previously way too small and annoying to click on, while simply making them bigger without adding scrollbars would have taken up too much screen space.

I believe I've developed a sensible set of principles for managing CSS, as expressed in 918eb41 (in summary: inline styles with Clay for component functionality, and style.css for pure aesthetics). This has so far been very pleasant to work with, but we may evolve our approach as we scale:

  • We've discussed using Clay for what it's actually designed for, i.e. generating stylesheets.
    • Right now, style.css is quite a long way from being interesting or repetitive enough for this to be of much benefit. This might start to change when, for example, we wish to implement the beginner and intermediate mode styles from primer-app.
    • This would require changes to our build script, in order to run the Haskell code which imports Clay. This could be a single-file "cabal script", but I don't know how well these play with Haskell.Nix.
    • We could develop a way to statically ensure that class names and IDs match between Miso and Clay, rather than just making sure we use the same strings. This would require some common local library which both the main app and the Clay script would depend on.
    • Optionally, we could ditch relying on the CSS cascade at all, as we currently do for e.g. node colours, in favour of Haskell abstraction.
  • We might choose to embrace Tailwind-style "utility classes".
    • Tailwind itself would probably be annoying to use, given that Miso and Haskell obviously lack the tight integration Tailwind has for React and JS build tools. Anyway, personally, I've become quite fond of CSS as a language and wary of stuff like Tailwind. For one thing, it's really quite nice to ditch all the heavyweight tooling and have something native that's well-supported by editors, browser dev tools, documentation etc.
    • I suspect the Tailwind style may be more useful for ad-hoc styling of basic UI components, whereas so far we've been focussed largely on program trees, which are more bespoke.
  • We may wish to move away from a single monolithic stylesheet. CSS has some support for namespaces and scoping, but I don't know much about it.

Finally, note that we aren't yet attempting to perfectly match primer-app. For the trees, we're very close, and better in some ways, but for the definitions panel what we have here is basically the simplest thing that looks somewhat decent. Similarly, using scrollbars rather than a pan-and-zoom-able canvas isn't the best UX, but it's simple.

This should be easier to work with than using inline styles for everything. It is also necessary for some functionality, e.g. changing styles on hover, which relies on a pseudo-selector and thus can't be used inline.

Signed-off-by: George Thomas <[email protected]>
Note that we use an `isSelected` parameter for `viewTreeExpr` etc. instead of seemingly simpler approaches like passing a `Maybe ID` because we have to make everything work when the metadata type is `()`.

Signed-off-by: George Thomas <[email protected]>
As well as simplifying the code, this gets rid of an unnecessary `div` layer.

Signed-off-by: George Thomas <[email protected]>
We also remove click handlers from such nodes, which just triggered `NoOp "clicked non-interactive node"` anyway.

Signed-off-by: George Thomas <[email protected]>
We now use a partially-transparent ring for nodes which are only hovered but not selected.

Signed-off-by: George Thomas <[email protected]>
The code is a lot more flexible now that we pass around `NodeViewData` rather than always immediately passing it to `viewNode`. This will ultimately allow for things like better edge styling.

Signed-off-by: George Thomas <[email protected]>
The major change here is making edges actual children of their source node in the DOM, allowing the colour to be inherited. The separate "node-contents" is necessary for this, but adds more flexibility which could be useful in future anyway, e.g. if we want labels on nodes like we had in the JS version.

This commit also unintentionally solves in passing an issue where pattern edges were invisible due to bad z-indices.

Signed-off-by: George Thomas <[email protected]>
We instead use CSS to center edges within the parent node.

Signed-off-by: George Thomas <[email protected]>
This approach is more robust against future changes.

Signed-off-by: George Thomas <[email protected]>
We now place trees within tight bounding boxes. This will make styling easier, including by  removing an unnecessary `div` layer.

Signed-off-by: George Thomas <[email protected]>
@georgefst georgefst requested a review from dhess January 9, 2025 19:35
@georgefst
Copy link
Contributor Author

Oh, whoops, I've accidentally formatted the README. Just a sec...

These are taken from `primer-app`, our old JavaScript frontend.

We also copy licenses, and the section from the README about third-party code (including the part about vendoring, which isn't actually relevant to changes in this commit, but is appropriate due to the layout algorithm from diagrams).

Note that we don't yet use the "branding" font, but we might as well copy all the fonts over together.

Signed-off-by: George Thomas <[email protected]>
We can almost get away with stripping the inner `div` and moving `overflow` etc. up a level, but we'd have to remove the flexbox, which makes centering the text vertically difficult (and would require further special-casing pattern boxes, though that's not a major issue).

Signed-off-by: George Thomas <[email protected]>
It's a bit pointless right now, and removing it allows us to simplify things. When we layout the UI properly with components in grids we'll likely want to do things differently anyway.

For now we apply some padding in to the whole canvas instead, via the stylesheet. Which at least means that hover rings don't overflow the screen.

Signed-off-by: George Thomas <[email protected]>
They're no longer used as much as they once were, so the code is simpler without them.

Signed-off-by: George Thomas <[email protected]>
Signed-off-by: George Thomas <[email protected]>
The offset is not obvious without setting `nodePadding` and `boxPadding` to 0. For some reason, the used/computed width for the element is otherwise less than the specified width. Changing to `min-height` as well is seemingly unnecessary but harmless, and it feels weird not to be consistent.

Signed-off-by: George Thomas <[email protected]>
The plan was initially to go the other way, removing remaining `style_` tags, and working with computed values in the stylesheet somehow.

Instead, we note that uses of CSS properties mostly fall cleanly in to two categories, and use the stylesheet solely for the latter:
- Functionality: properties which are essential for the app to work.
- Aesthetics: properties which could in theory be overridden by a user-specific "theme". We can remove these entirely and have an app which is still functional, if ugly.

Another way to think about this is that if we were to separate out functionality in to React-style components, the former would be hardcoded to ensure reasonable encapsulation, and the latter configurable. This is a common pattern in libraries such as ReactFlow.

In some cases, it might make sense for something to be overridden even when it is necessary that it has _some_ value. For example, without setting `border-style: solid` on edges they can't be seen at all, but a theme could still override with `border-style: dotted !important`. See also the flexbox properties for `node-contents`. In these cases, we use inline styles to preserve the principle that the stylesheet-less app still works.

Signed-off-by: George Thomas <[email protected]>
One of our recent changes must have made this possible where it wasn't before, e.g. by removing intermediate `div`s.

Signed-off-by: George Thomas <[email protected]>
It's not really designed for this (see comment on `clayToMiso`) but it actually works really nicely for avoiding manually constructing style strings and adding a degree of type safety.

Signed-off-by: George Thomas <[email protected]>
This makes no functional difference, but is good practice due to indicating the semantics as well as providing a theoretical performance improvement.

Signed-off-by: George Thomas <[email protected]>
@georgefst georgefst force-pushed the georgefst/stylesheet branch from 119eae7 to a5a6d45 Compare January 9, 2025 20:13
@dhess
Copy link
Member

dhess commented Jan 14, 2025

Recent Wasm builds on x86_64-linux have been OOM'ing. I'll fix this shortly.

edit: fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants