[HN Gopher] Clay - UI Layout Library
___________________________________________________________________
Clay - UI Layout Library
Author : ivmoreau
Score : 357 points
Date : 2024-12-19 16:36 UTC (1 days ago)
(HTM) web link (www.nicbarker.com)
(TXT) w3m dump (www.nicbarker.com)
| mega-tux wrote:
| Looks very nice, I just watch a great YT video from the developer
| here https://www.youtube.com/watch?v=DYWTw19_8r4
| rubymamis wrote:
| It's so rare to see such a clear and intuitive explanation.
| This video is amazing.
| porjo wrote:
| This. It is a rare and unique thing for the author to a) have
| the skills to put together such a presentation and b) take
| the time to do so. Thankyou.
| riazrizvi wrote:
| 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.
| keyle wrote:
| I'm a gray beard like you probably but I disagree with this
| statement.
|
| This library makes use of modern composable components, is
| declarative driven and not imperative; and doesn't do
| immediate rendering in all cases.
|
| It can target incredibly different backends, e.g.
| DOM/canvas/raylib.
|
| All of this in modern C as a `.h` library alone.
|
| These are great features and not just a 'youngster discovers'
| project.
| riazrizvi wrote:
| Maybe a README that shows how it works and what it does
| would help. As it is it is quite opaque IMO, with just a
| few high level comments.
| fredrikholm wrote:
| It's in the repo; landing pages are usually for
| generating interest.
|
| https://github.com/nicbarker/clay
| contrast wrote:
| The README for the project is one of the most detailed
| READMEs I've ever seen. The landing page for the website
| has as much detail as you can reasonably expect, even
| including a couple of feature demos. There are clear
| links to the docs and the code.
|
| The developer has clearly put a lot of thought into this
| content. Worth taking a second or two to see what's
| available before criticising it.
| coolgoose wrote:
| I swear to god, I thought this is AI generated response.
| chromanoid wrote:
| 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.
| dannyobrien wrote:
| 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)
| __m wrote:
| Should that be part of a layout engine though? I'd expect to
| insert a tree of nodes with styling information that affect
| layout and receive a tree with calculated x, y, width and
| height for its elements.
| britannio wrote:
| So cool. I wonder if it'd work for a Raspberry Pi Pico +
| https://pimoroni.com/picodisplay or similar devices.
| zibzob wrote:
| 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")))) {
| jasonjmcghee wrote:
| 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.
| rmac wrote:
| this happens to me on mobile using all chromium and gecko based
| browsers
|
| what's also interesting is how much worse Firefox is at
| rendering this page; example =>
|
| https://imgur.com/a/DNYe2WN
| rmgk wrote:
| If you mean the text position that overflows, that seems to
| be computed by the library. The same happens in chromium at
| some resolutions.
| Reubend wrote:
| It's probably because it does it a full reset every frame, and
| there's an animation playing.
| ahmedfromtunis wrote:
| 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...
| dvt wrote:
| 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.
|
| [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...
| righthand wrote:
| Qt has uic xml layout engine which was cumbersome to use, you
| weren't discouraged from using c++ classes instead. The
| discouragement came later when Qt shifted towards qml (a bad
| shift as it's just as unweildly, imo), now they discourage
| writing qml in c++ because the qml engine can get out of
| sync. Qt can prevent this but they want you to pay for a
| premium license for it. Slint is a sister to qt that does not
| have this restriction afaik.
|
| I wish there would be an elegant c++ class/function based ui
| framework again.
| OvbiousError wrote:
| Agreed that a C++ API for qml would be great. qml by itself
| is great though, I don't see why it is unweildy. If
| anything it's unpolished, there is stuff that is more
| difficult than it should be, but it's miles ahead of what
| there was before imo.
| CyberDildonics wrote:
| It's not difficult or disorganized to layout GUIs in a
| programming language. HTML exists as an alternative to having
| nothing. If you have a programming language you can give the
| data to the GUI library directly without having to learn a
| new markup language, have the bloat of a new markup language
| or learn the quirks a new markup language. You can also put
| format it and put newlines in there.
| mvc wrote:
| The thing is, most GUIs by necessity involve fairly deep
| hierarchies of graphical objects so you're either going to
| have deeply nested calls like this, or you're going to
| scatter the fragments across a number of files in a way
| that they need to be reassembled in the reader's head in
| order to understand what's going on.
| CyberDildonics wrote:
| _most GUIs by necessity involve fairly deep hierarchies
| of graphical objects_
|
| First, this isn't really true. You might typically have a
| window, a container, a layout object and then your gui
| components.
|
| Second you don't need nested calls, you just add one
| component to another.
|
| _or you 're going to scatter the fragments across a
| number of files_
|
| Why would that be true?
|
| _they need to be reassembled in the reader 's head in
| order to understand what's going on._
|
| This is a bizarre way to make a GUI let alone thinking
| it's necessary. Where is this idea coming from?
|
| FLTK, JUCE, Tk, ImGUI, Swing and Qt are not like this at
| all.
| lylejantzi3rd wrote:
| It's not all that much different than html or even React. You
| can assign each part to named functions and turn it into
| something more like this:
| LandingPageDesktop(landingPageDesktopId,
| landingPageDesktopProperties) {
| LandingPage(landingPageId, landingPageProperties) {
| LeftText() { 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.
| ilrwbwrkhv wrote:
| 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.
| Diti wrote:
| > C is also such a good language. If I wasn't doing Rust, I
| would have gone back to C.
|
| Wouldn't you try Zig instead?
| ilrwbwrkhv wrote:
| I'm not sure I would have. There is a terseness in C which
| zig lags. I think. To be fair, I haven't played with Zig that
| much.
| huhtenberg wrote:
| 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.
| virtualritz wrote:
| There is also taffy (Rust) which has WIP C bindings.
|
| https://crates.io/crates/taffy
| fuzzythinker wrote:
| Press "d" to debug didn't work for me. On Chrome in Mac.
| dgan wrote:
| 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!
| PittleyDunkin wrote:
| Hey at least this way other languages can use it
| bee_rider wrote:
| 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.
| spiderfarmer wrote:
| Text selection and zoomng is also problematic.
| anonzzzies wrote:
| Zooming is indeed an issue but selection works fine for me on
| safari ios.
| Klaster_1 wrote:
| On Windows/Firefox, text selection doesn't work. Also not
| working is Home/End and wheel click scrolling. Cool project
| otherwise.
| red_trumpet wrote:
| My Firefox on Linux zooms fine with both renderers. Text
| selection doesn't work though. Also the cursor doesn't adapt
| when hovering text, a button etc.
| wffurr wrote:
| It won't help with dark mode, but the canvas-place-element
| proposal (https://github.com/WICG/canvas-place-element)
| should allow those interactions on canvas-rendered text
| backed by a text element placed under the canvas.
| sgt wrote:
| In Chrome, it selects sometimes but sometimes it seems to
| unselect itself, probably due to the animation happening
| somewhere else on the page.
| sgt wrote:
| 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.
| varispeed wrote:
| It says:
|
| > 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.
| noamchompsit wrote:
| Cool, so if i look for 'clay', i'll find your lib?
| recursive wrote:
| You mean, like, using a search engine? I don't think anyone
| here is in any special position to be able to answer that
| question.
| esperent wrote:
| "clay ui" or "clay layout" will find it, which seems ok to me.
| elcritch wrote:
| 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"]
|
| 1: https://github.com/elcritch/cssgrid
| nicoburns wrote:
| 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)
|
| 1: https://github.com/DioxusLabs/taffy
|
| 2: https://github.com/facebook/yoga
| elcritch wrote:
| Hey thanks! That's awesome and great to see other
| implementations. Figuring out test cases is half the battle
| and I've really only done the basics. I'll definitely look to
| stealing things. ;)
|
| > 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.
|
| Good call, I'll add the license file.
| c-smile wrote:
| 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.
|
| 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...
| nicoburns wrote:
| You definitely don't need a general constraint solver for CSS
| Grid. The algorithm (including for cases where there are
| spanned cells) is well defined in the spec [1], and can be
| translated directly into code.
|
| 1: https://www.w3.org/TR/css-grid-1/#algo-content
| xhrpost wrote:
| I'm not proficient in C. Does this "just work" or do you need to
| provide some sort of rendering environment like SDL?
| thot_experiment wrote:
| This is just a layout library, it doesn't do any rendering at
| all.
| nine_k wrote:
| No, the library is about doing the layout only.
|
| 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.
| bvisness wrote:
| 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.
| wangii wrote:
| Looks impressive! What are the connection/comparison with imgui
| though?
| thiht wrote:
| 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.
| gnarlouse wrote:
| Highlighting is degraded for me running on Firefox, it's wigging
| out every time I nudge my cursor
| sgt wrote:
| This is basically what Flutter web is doing - its own canvas,
| rendering UI, and leveraging Wasm
| b3orn wrote:
| Right and middle click on links behaves like a left click on the
| website.
| 7bit wrote:
| Instant recycle bin.
| inson wrote:
| why it's not written in rust?! now every cool kid writes in
| rust)) Jokes aside this is nice!
| citizenpaul wrote:
| 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.
| hoppp wrote:
| Maybe you want the compile some C to wasm and render to canvas.
| Then it's pretty neat.
| mdarens wrote:
| 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
| wishinghand wrote:
| 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.
| mendor wrote:
| 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
| NoZZz wrote:
| Oh sweet jesus, the preprocessor? Go away.
| erichocean wrote:
| 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...
___________________________________________________________________
(page generated 2024-12-20 23:01 UTC)