Clay – UI Layout Library
Just a funny note—there’s a button at the end to switch between HTML and Canvas. I think it is neat how little difference it makes… normally.
But with iOS Safari + Dark Reader, at least on my side, the HTML page is turned into dark mode with Dark Reader, while the canvas page is not. So, it basically ruins the wow factor, haha.
But it still looks nice.
Looks very nice, I just watch a great YT video from the developer here https://www.youtube.com/watch?v=DYWTw19_8r4
Just wanted to drop a note - everything following the animation cannot be selected - seems focus is stolen somehow - whenever I try to select text, it immediately deselects it.
This is a delightful take on a style of UI I really love. Separating the UI logic from drawing with a set of draw commands is an excellent and very versatile idea - I first saw it in microui, and the separation allowed me to easily use the library in the browser using WASM and Canvas2D. (https://rxi.github.io/microui_v2_an_implementation_overview....)
Also, doing layout in WASM and rendering to HTML is a great idea that I can't believe I never thought of before.
Excellent. If these compiled data structures were the web standard instead of HTML, www would be ridiculously fast.
My question may be to obvious but, how can you incorporate js to mutate your layout based on user interaction and api calls? Do you have a dynamic website example?
Okey i was going to complain about what's the point of doing it in C, when it could be done more safely in Haskell/OCaml
But 2000 lines of C, and no dependencies is pretty cool!
It's a good first draft. I do find it a shame that the HTML output is only div elements. I think a little accessibility would go a long way. I also can't select text in many places before some re-render de-selects before I can hit control-c.
There is also taffy (Rust) which has WIP C bindings.
Right and middle click on links behaves like a left click on the website.
Serious question: am I the only one who finds writing a webpage like this to be a little too much (even if the concept is cool):
void LandingPageDesktop() { CLAY(CLAY_ID("LandingPage1Desktop"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIT({ .min = windowHeight - 70 }) }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = { .x = 50 } })) { CLAY(CLAY_ID("LandingPage1"), CLAY_LAYOUT({ .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .childAlignment = {.y = CLAY_ALIGN_Y_CENTER}, .padding = { 32, 32 }, .childGap = 32 }), CLAY_BORDER({ .left = { 2, COLOR_RED }, .right = { 2, COLOR_RED } })) { CLAY(CLAY_ID("LeftText"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_PERCENT(0.55f) }, .layoutDirection = CLAY_TOP_TO_BOTTOM, .childGap = 8 })) { CLAY_TEXT(CLAY_STRING("Clay is a flex-box style UI auto layout library in C, with declarative syntax and microsecond performance."), CLAY_TEXT_CONFIG({ .fontSize = 56, .fontId = FONT_ID_TITLE_56, .textColor = COLOR_RED })); CLAY(CLAY_ID("LandingPageSpacer"), CLAY_LAYOUT({ .sizing = { .width = CLAY_SIZING_GROW(), .height = CLAY_SIZING_FIXED(32) } })) {} CLAY_TEXT(CLAY_STRING("Clay is laying out this webpage right now!"), CLAY_TEXT_CONFIG({ .fontSize = 36, .fontId = FONT_ID_TITLE_36, .textColor = COLOR_ORANGE })); } CLAY(CLAY_ID("HeroImageOuter"), CLAY_LAYOUT({ .layoutDirection = CLAY_TOP_TO_BOTTOM, .sizing = { .width = CLAY_SIZING_PERCENT(0.45f) }, .childAlignment = { CLAY_ALIGN_X_CENTER }, .childGap = 16 })) { LandingPageBlob(1, 32, COLOR_BLOB_BORDER_5, CLAY_STRING("High performance"), CLAY_STRING("/clay/images/check_5.png")); LandingPageBlob(2, 32, COLOR_BLOB_BORDER_4, CLAY_STRING("Flexbox-style responsive layout"), CLAY_STRING("/clay/images/check_4.png")); LandingPageBlob(3, 32, COLOR_BLOB_BORDER_3, CLAY_STRING("Declarative syntax"), CLAY_STRING("/clay/images/check_3.png")); LandingPageBlob(4, 32, COLOR_BLOB_BORDER_2, CLAY_STRING("Single .h file for C/C++"), CLAY_STRING("/clay/images/check_2.png")); LandingPageBlob(5, 32, COLOR_BLOB_BORDER_1, CLAY_STRING("Compile to 15kb .wasm"), CLAY_STRING("/clay/images/check_1.png")); } } } }
Source: https://github.com/nicbarker/clay/blob/35d72e5fba6872be48d15...
cool stuff! selectable text is a MUST in the browser for me. In clients and apps that do not need that or can provide it themselves, this seems to be a very nice and tiny solution.
So cool! For some reason navigating to Github/Discord by clicking the links is slow on my phone (old galaxy s20fe). The click highlight of the button is normal, just going to the sites is slow.
I'm not a frontend person. Can anyone explain why this is better than using CSS directly or a CSS framework/library? Seems like added complexity when there are already hundreds of CSS frameworks available that seem like they do the same thing.
So cool. I wonder if it'd work for a Raspberry Pi Pico + https://pimoroni.com/picodisplay or similar devices.
Using CSS translations to place elements on the page is... cursed to say the least. It's probably why text selection works (assuming it qualifies as working) in such a weird way when the cursor goes between blocks.
This looks pretty cool, but from the page I can't tell if there's any interactivity supported...there's a button example but it seems to have no click handler?
Okay, from the examples there's something like this:
if (isMouseDown && !scrollbarData.mouseDown && Clay_PointerOver(Clay_GetElementId(CLAY_STRING("ScrollBar")))) {
Looks impressive! What are the connection/comparison with imgui though?
The canvas renderer tried on iPhone feels weird. The scroll is completely different from regular, also no scroll bounce. That alone is a deal breaker
Highlighting is degraded for me running on Firefox, it's wigging out every time I nudge my cursor
Getting an empty, cream-rose-colored page, followed by a warning that the script on the page is slowing the browser down with an offer to stop the script. Just FYI.
the inspector at the end was a neat surprise! I had some issues trying to build the examples on windows but I think it's an opportunity to contribute to the project
I'm not proficient in C. Does this "just work" or do you need to provide some sort of rendering environment like SDL?
Press "d" to debug didn't work for me. On Chrome in Mac.
This is basically what Flutter web is doing - its own canvas, rendering UI, and leveraging Wasm
Would be fun to combine this with the single-file Impeller header from the Flutter people.
The API approach could be implemented extremely cleanly in Clojure and Java, and then the whole thing would be runtime-dynamic, since Clojure generates new Java functions on the fly, and the JVM's JIT makes them fast.
If anyone wants a fun project over the holidays…
The d for debugging is so cool. Fantastic library. C is also such a good language. If I wasn't doing Rust, I would have gone back to C.
Oh sweet jesus, the preprocessor? Go away.
Cool, so if i look for 'clay', i'll find your lib?
why it's not written in rust?! now every cool kid writes in rust)) Jokes aside this is nice!
Nice! It's pretty cool what you can make in a few thousand lines. Though Flex isn't my favorite as I prefer full CSS Grid. So I ended up making a CSS Grid layout library that I'm proud of in pure Nim (1). Though I'll have to checkout Clay and compare some of the layout algorithms.
It's neat to see boxes resizing themselves using an algorithm you implemented. Wonder if I could expose a C interface?
The reason I like CSS Grid is that I could imitate the formatting like this:
1: https://github.com/elcritch/cssgrid