The developer is rediscovering the concept of a GUI library. The modern variant is the mouse-driven GUI developed by Xerox in the 1970s (and later commercialized by them as Xerox Star) which Jobs famously copied to create Apple’s Lisa, and Gates famously mimicked to create MS Windows. Since they determine the look and feel of a platform and their design determines the ease with which developers can create apps for the platform, GUI frameworks became pivotal to platform wars across all sorts of products, from OSs to browsers, graphics engines and anything else whose success was determined largely by the interface developer experience.
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:
test "compute others":
var gt: GridTemplate
parseGridTemplateColumns gt, ["first"] 40'ux \
["second", "line2"] 50'ux \
["line3"] auto \
["col4-start"] 50'ux \
["five"] 40'ux ["end"]
Cool! I also have a standalone implementation of CSS Grid [1]. Implemented in Rust in my case (and we also support Flexbox and Block layout). Looks like the licenses are both MIT (although you may want to add a LICENSE file to make that easier to find) so feel free to steal bits if you want. We aim to be fully web compatible, although we're not quite there yet.
One thing we have that you may be particularly interested is a reasonably substantial test suite. The tests are defined as HTML snippets that we run through Chrome using webdriver in order the scrape (hopefully) correct assertions, and then format into pure-code unit tests. If you wanted to you could write your own test generator and reuse our snippets. (this test infrastructure is also partially shared with Yoga [2], the C++ Flexbox implementation that powers React Native)
Correct CSS grid layout calculation is about solving system of equations and constraints. In simple cases, when there are no spanned cells (like in flexbox), it can be done relatively trivially.
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.
The HTML renderer is definitely faster in Chrome. Why is that, I wonder? The Canvas one is also reasonably fast, but noticable in that "High performance" animation and also when scrolling.
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.
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.
If you don't use some kind of layouting language (like XML/HTML), this is inevitably what you will always end up with. See: AWT[1], SWT[2], Swing[3], Qt[4]†, Fyne[5], etc., etc., etc.
The real issue is trying to represent graphical objects, and the relationship between those objects, with text. Graphical builders/RAD tools seem like such an obvious solution, but that approach has largely been abandoned.
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.
it's weird to watch it break text selection/copy-and-paste : feels like it might be fixable, though.
I'm a stuck record on this, but I really feel like the regressions in clipboard universality are one of most understated losses of UI shifts in the last few years (along with linkability and embedding)
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.
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")))) {
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.
This isn't really meant to replace such things an environment where you have a rendering engine that supports CSS— I think demoing it on the page is more for showing off how portable it is with WASM. Off the top of my head, a few uses for this:
- Mapping components or structured document data with something like MDX or slate on to Clay components to render in different contexts outside the browser reasonably closely to what shows up in a browser preview, for example content for HUDs, in-world display panels or documents in games, or batch rendering printed documents
- Layout for UI where something like Electron or React Native would be overkill, or isn't supported
The main goal is to enable nice UI without the requirement of a whole web browser in order to get CSS. The fact that it can be used to layout web pages is just showing off to get the attention of the billion web devs out there.
This UI library can be re-targeted to Raylib, Canvas, HTML from its markup ... Good luck doing that with just CSS.
Put another way, this library is a step into writing an agnostic UI layer for your application which it just invokes from its business logic. If you can decouple your UI from your application code ala MVC or MVP architecture, as a developer you can find the right tool for the components that compose the sum of your project.
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.
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.
Both use immediate mode rendering. Both have the “single header” design. There doesn’t appear to be any shared implementation.
The examples use Raylib as a renderer behind the layout engine. I suppose it would be possible to use Dear Imgui as a renderer, but you might have to write some glue code.
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?
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.
Yes, the repo offers a couple of example renderers.
The idea is that you already have a rendering pipeline (e.g. in your game engine), but want to lay out more complex UIs in it. Then you can use this library to make nice settings / chat / stats / whatever screens, or even render realistic content onto screens of in-game computers, pages of books, etc.
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
If Android had provided an defining UI API like this entirely in C without using Java, Android would have 100% monopolized the mobile OS market. So fast, efficient.
mega-tux|1 year ago
rubymamis|1 year ago
riazrizvi|1 year ago
elcritch|1 year ago
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/cssgridnicoburns|1 year ago
One thing we have that you may be particularly interested is a reasonably substantial test suite. The tests are defined as HTML snippets that we run through Chrome using webdriver in order the scrape (hopefully) correct assertions, and then format into pure-code unit tests. If you wanted to you could write your own test generator and reuse our snippets. (this test infrastructure is also partially shared with Yoga [2], the C++ Flexbox implementation that powers React Native)
1: https://github.com/DioxusLabs/taffy
2: https://github.com/facebook/yoga
c-smile|1 year ago
Otherwise solving that system is far from being trivial, you will need simplex solver or the like, for example https://constraints.cs.washington.edu/solvers/cassowary-toch...
bee_rider|1 year ago
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.
spiderfarmer|1 year ago
varispeed|1 year ago
> There's even an HTML renderer - you're looking at it right now!
Jokes on them, I already switched to Canvas renderer when I read it.
sgt|1 year ago
unknown|1 year ago
[deleted]
jasonjmcghee|1 year ago
Reubend|1 year ago
rmac|1 year ago
what's also interesting is how much worse Firefox is at rendering this page; example =>
https://imgur.com/a/DNYe2WN
bvisness|1 year ago
Also, doing layout in WASM and rendering to HTML is a great idea that I can't believe I never thought of before.
dgan|1 year ago
But 2000 lines of C, and no dependencies is pretty cool!
PittleyDunkin|1 year ago
virtualritz|1 year ago
https://crates.io/crates/taffy
wishinghand|1 year ago
ahmedfromtunis|1 year ago
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...
dvt|1 year ago
[1] https://docs.oracle.com/javase/7/docs/api/java/awt/GridLayou...
[2] https://github.com/eclipse-platform/eclipse.platform.swt/blo...
[3] https://stackoverflow.com/a/12867862/243613
[4] https://stackoverflow.com/questions/37304684/qwidgetsetlayou...
† Qt actually has a (XML-based, I think) layouting system, but you can also just do stuff in code, which is generally discouraged.
[5] https://gist.github.com/ledongthuc/9686787fe51bbe763fa1e5038...
lylejantzi3rd|1 year ago
chromanoid|1 year ago
dannyobrien|1 year ago
I'm a stuck record on this, but I really feel like the regressions in clipboard universality are one of most understated losses of UI shifts in the last few years (along with linkability and embedding)
b3orn|1 year ago
7bit|1 year ago
britannio|1 year ago
Woshiwuja|1 year ago
[deleted]
ilrwbwrkhv|1 year ago
Diti|1 year ago
Wouldn’t you try Zig instead?
erichocean|1 year ago
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…
zibzob|1 year ago
Okay, from the examples there's something like this:
unknown|1 year ago
[deleted]
citizenpaul|1 year ago
mdarens|1 year ago
- Mapping components or structured document data with something like MDX or slate on to Clay components to render in different contexts outside the browser reasonably closely to what shows up in a browser preview, for example content for HUDs, in-world display panels or documents in games, or batch rendering printed documents
- Layout for UI where something like Electron or React Native would be overkill, or isn't supported
hoppp|1 year ago
corysama|1 year ago
tenken|1 year ago
Put another way, this library is a step into writing an agnostic UI layer for your application which it just invokes from its business logic. If you can decouple your UI from your application code ala MVC or MVP architecture, as a developer you can find the right tool for the components that compose the sum of your project.
thiht|1 year ago
steve-chavez|1 year ago
wangii|1 year ago
mtnygard|1 year ago
The examples use Raylib as a renderer behind the layout engine. I suppose it would be possible to use Dear Imgui as a renderer, but you might have to write some glue code.
isagues|1 year ago
m3kw9|1 year ago
huhtenberg|1 year ago
Naru41|1 year ago
xhrpost|1 year ago
nine_k|1 year ago
Yes, the repo offers a couple of example renderers.
The idea is that you already have a rendering pipeline (e.g. in your game engine), but want to lay out more complex UIs in it. Then you can use this library to make nice settings / chat / stats / whatever screens, or even render realistic content onto screens of in-game computers, pages of books, etc.
thot_experiment|1 year ago
gnarlouse|1 year ago
fuzzythinker|1 year ago
mendor|1 year ago
sgt|1 year ago
Naru41|1 year ago
NoZZz|1 year ago
noamchompsit|1 year ago
esperent|1 year ago
recursive|1 year ago
unknown|1 year ago
[deleted]
inson|1 year ago