[HN Gopher] Clay (short for C Layout) is a high performance 2D U...
       ___________________________________________________________________
        
       Clay (short for C Layout) is a high performance 2D UI layout
       library
        
       Author : ranger_danger
       Score  : 182 points
       Date   : 2024-08-24 15:26 UTC (3 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | whateveracct wrote:
       | This looks quite nice! Conceptually it reminds me of microui. But
       | a bit more fleshed out and a nicer API.
        
       | ngcc_hk wrote:
       | Can one use it with love2d I wonder?
        
         | ofrzeta wrote:
         | Not an answer to your question but the repo contains a Raylib
         | example :)
        
         | andrewmcwatters wrote:
         | Yes, you'd probably want to generate bindings using
         | https://github.com/Planimeter/lffiutils or something similar,
         | but then you can use it in Lua.
        
       | cyco130 wrote:
       | Hey, that's 6502 code!
        
         | ofrzeta wrote:
         | What is? Is there a compiler with 6502 target that has
         | uint64_t? :)
        
           | jsnell wrote:
           | The first demo application screenshot.
        
             | ofrzeta wrote:
             | Oh, I see, thanks. ASM for the NES or something.
        
         | 082349872349872 wrote:
         | looks like https://www.riverlanguage.org
         | 
         | > River is an experimental assembly-like programming language.
        
           | cyco130 wrote:
           | Hmm, I don't think so, doesn't seem similar. I see a
           | mario.chr in the next tab, seems NES-related. Pretty sure
           | it's our beloved 6502 :)
        
         | nicbarkeragain wrote:
         | Author here - yes you caught me. I'm building an asm IDE in C
         | (which is why I ended up building this layout library in the
         | first place) and the screenshot is from that application,
         | specifically while building a NES game for Pikuma's NES/6502
         | course :)
        
       | michelreij wrote:
       | Would this work on a microcontroller like an ESP32?
        
         | b3orn wrote:
         | Probably, but you'd have to write a custom renderer for it.
        
       | torlok wrote:
       | Has anybody made an attempt at making a library like this, but
       | with cross platform user input, and support for accessibility?
       | From personal experience, if you can output triangles and text,
       | writing a UI library like this is maybe 2-3 days of work. The fun
       | starts when you consider that younger people are touch-first.
        
         | kevingadd wrote:
         | The accessibility is the hardest part. My custom library (in C#
         | atop a weird rendering stack) has partial narration support and
         | full touch/gamepad/mouse/keyboard navigation, but getting all
         | the way to integrating with native screen readers is basically
         | impossible at this point - from investigating it, it'd probably
         | take me at least 3 months to get it working at all, and it
         | wouldn't be portable.
         | 
         | One thing you have to do for reasonable accessibility is
         | maintain a retained model behind the scenes even if you have an
         | immediate mode API, so that's what I did. The immediate mode
         | API does a bunch of caching in order to construct and maintain
         | an appropriate retained mode tree across frames, which makes it
         | possible to cleanly handle things like focus, selection and
         | narration for invisible controls, etc. You also have to bake
         | accessibility into the API from the start, for example by
         | making certain every single widget has a description or a
         | reasonable approximation of one, and by making sure there is an
         | approximation of roles for every widget too.
         | 
         | A simple 'read a text description of the focused/clicked
         | control' also doesn't get you far enough for narration - for
         | example if there's a slider or textarea, you don't want to read
         | the description and then the new value every time it changes,
         | your narration has to be 'smart' and know to only read the
         | description initially.
         | 
         | I'm hoping eventually AccessKit
         | (https://github.com/AccessKit/accesskit) will be mature enough
         | to use though.
        
         | 0x0203 wrote:
         | Have you seen libAgar (https://libagar.org)? Cross platform
         | support is certainly there, covering everything from windows XP
         | (and earlier) to *bsd and SGI IRIX. I'm not sure what all
         | having support for accessibility requires as I've never had to
         | worry about it, but am curious if 1, agar has what's needed,
         | and 2, what exactly is required of a GUI library for
         | accessibility. Screen reader support? (Are there SR standards
         | for desktop applications)? Dynamic scaling? High contrast?
         | 
         | (For embedded and/or touch first UI, LVGL is pretty nice, but
         | probably lacking any semblance of accessibility features apart
         | from keyboard navigation, but you could hook that yourself).
        
           | Teever wrote:
           | I've never seen this before, very cool.
           | 
           | The style in the screenshots reminds me of KDX[0] from
           | Haxial.
           | 
           | [0] https://wiki.preterhuman.net/Haxial_KDX_(software)
        
       | agentcooper wrote:
       | I wonder if you can get better performance than the built-in
       | browser engine for certain complex layouts by first calculating
       | the layout using Clay and then absolutely positioning the
       | elements with HTML/CSS.
       | 
       | There was some news feed web app that used <canvas /> for better
       | scrolling performance.
        
         | chii wrote:
         | if you can guarantee that layouts don't change during
         | interactions, i guess it _might_ save some time for the browser
         | (and thus battery, for low power devices).
         | 
         | If layouts change during interaction (e.g., orientation swap),
         | then you will have a roundtrip to the server to recalculate. I
         | assume this would cost more time than letting the browser css
         | engine do their thing.
        
           | agentcooper wrote:
           | In my comment I assumed that Clay layout is running in the
           | browser as well, but your idea of running it before serving
           | the HTML is quite interesting!
        
       | sevnin wrote:
       | Quite a lot of work went into those docs. I won't use it (because
       | I don't have a need for it) but the examples look quite pleasing,
       | nice work!
        
       | pistoleer wrote:
       | A big improvement over CSS, but still seems pretty manual and
       | finnicky, I wonder if a constraint solver based system and syntax
       | would be ideal for laying out UI.
       | 
       | For instance, being able to set the constraint "element.[x,y] =
       | other.[x,y]+other.[width,height]/2;", instead of working with
       | "attachment" objects.
        
         | loa_in_ wrote:
         | I think there already are existing mature solutions like you
         | described. Isn't QT constraint based?
        
           | 1oooqooq wrote:
           | qt lost it's golden momentum taking way too long to relax
           | licensing in the 90s. had they done it before the gtk shift
           | the world would be very different.
           | 
           | btw, gtk is based on tcl/tk which i believe is the, or one of
           | the, original auto layout engines
        
             | nine_k wrote:
             | Qt is C++, while GTK is pure C. These are very different
             | languages, and exposing a C interface for C++ code as rich
             | and complicated as Qt is not easy.
        
               | adastra22 wrote:
               | Ad yet TFA is kinda an example of that, no?
        
               | nine_k wrote:
               | Qt without slots and signals is a poorer experience. IDK
               | if the Qt Designer can work without them.
        
               | PaulDavisThe1st wrote:
               | GTK provides slots and signals, through an admittedly
               | baroque C-level implementation. Pretty easy to use, but
               | try not to open the hood.
        
             | PaulDavisThe1st wrote:
             | GTK has no relationship to tcl/tk whatsoever.
        
               | 1oooqooq wrote:
               | i see. always felt gtk layout experience similar. but i
               | have much more exposure to tcl/tk than proper gtk.
        
         | speps wrote:
         | Look up "cassowary" layout algorithm and all of its
         | implementations.
        
           | airstrike wrote:
           | Thank you for this! If you or any one else has any other
           | literature to recommend, I'm all ears!
        
             | PaulDavisThe1st wrote:
             | the algorithm is cool but it does not scale well.
             | 
             | it's awesome for small things (like mobile-style app GUIs),
             | but not usable for full-scale desktop apps (e.g. a DAW).
        
               | kragen wrote:
               | when you say 'does not scale well', are you talking about
               | the algorithm's performance or about some kind of
               | maintainability concern?
        
             | danielvaughn wrote:
             | I spent some time digging into Cassowary around 2019, so I
             | can't recall much, but here's a link to the seminal paper:
             | https://constraints.cs.washington.edu/solvers/cassowary-
             | toch...
        
         | pavlov wrote:
         | Apple adopted such a constraint-based system about 10 years ago
         | in iOS and macOS. It's called Auto Layout.
         | 
         | It's powerful but not trivial to adopt. In particular, the
         | design experience in Interface Builder has gone backwards in
         | usability. The old system of resizing rules visualized as
         | "springs and struts" was easier to understand in a visual
         | design tool.
         | 
         | One might argue that's the cost of progress, and that designers
         | using Interface Builder become better UI engineers when they
         | have to figure out how to express themselves in constraints.
         | But it seems to me that the reality is that a lot of people
         | just stopped using IB.
         | 
         | IB used to be a crown jewel of NeXT's development suite in the
         | 1990s. It was simple and focused, and allowed you to build
         | surprisingly powerful UIs that connected to high-performance
         | native code (unlike its mainstream competitor Visual Basic).
         | 
         | I don't think a lot of people have such fond feelings about
         | Apple's current IB. Something was lost along the way.
        
           | pistoleer wrote:
           | I sense a parallel between that and the dropoff of SQL over
           | lossy and impedance mismatched but "easy" ORMs and document
           | stores. People don't realize they're trying to have their
           | cake and eat it too maybe?
           | 
           | I wonder how we can stimulate "expert" tools and systems for
           | those who don't want to take the greedy path of least
           | resistance, and are tired of painting themselves into corners
           | that way.
        
             | bckr wrote:
             | Stimulate? Or simulate?
             | 
             | My learning path went something like this:
             | 
             | (The dark ages of data processing for personal use)
             | 
             | - Use a text file: Fine, you have to write your own read &
             | write logic, but for small amounts of data this works.
             | 
             | - Use a CSV file: less custom logic than plaintext
             | 
             | - Use a JSON file: really nice to have structured data!
             | 
             | - Use a Python pickle file: the idea is you can "pick up
             | where you left off", but it's slow, clunky, and inflexible
             | 
             | (Finally learning to use a database)
             | 
             | - Use Google Sheets: oh, it's nice to be able to index
             | things without needing to read/write the entire dataset!
             | You can also do searches and stuff, it's great.
             | 
             | - Django ORM + MongoDB: Oh my god, so horrible. MongoDB was
             | supposed to be simple. This set up was slow and
             | complicated. Migrations were a constant pain. And we didn't
             | even have any users.
             | 
             | - Postgres: It all makes sense. SQL is great. You can think
             | about and query your data in reasonable ways. And it's
             | fast.
             | 
             | - DynamoDB: Yeah whatever, as long as you do validation on
             | every read/write you'll probably be fine.
        
           | WillAdams wrote:
           | That is really sad.
           | 
           | I always thought that Apple should have really pushed the
           | whole "Applescript Studio" thing so as to create something
           | even better and more approachable than Visual Basic --- it
           | could have been a true HyperCard replacement.
        
           | gwking wrote:
           | This is a topic about which I have long simmering opinions. I
           | suspect that several things happened.
           | 
           | First, expectations and requirements went up. Laying stuff
           | out with a mouse and snap-to alignment guides is ok for
           | simple UI, but the more complex the design, the more I would
           | end up fighting the vector-art style design interface. I
           | remember staying up late fixing pixel alignment errors in nib
           | files. Often you would need to move objects around to inspect
           | another underneath and then play undo games to get things
           | back exactly where they were.
           | 
           | The interesting parallel here is that the designers were
           | doing all the designs in vector art apps, and were also
           | frequently missing dynamic aspects of the design
           | requirements.
           | 
           | It was one thing to design complex dialog boxes for desktop;
           | think of a photoshop filter control pane. You target a
           | minimum size screen, and then work with a fixed pane and lay
           | things out. When the iPhone came out, IB worked ok for early
           | versions and stock components. Screens were crowded but fixed
           | width.
           | 
           | Once bigger screens came out, more designs started needing
           | variable width layout computation. The APIs for dynamic
           | layout were (as I recall now) more subtle than they sounded
           | in the docs, and I recall joining several teams that misused
           | them. "sizeToFit" and "sizeThatFits" were two culprits.
           | Perhaps it made more sense in the simpler NeXT days, and
           | perhaps the docs degraded. If you didn't read Apple's
           | "Programming Guide" docs, it was hard to know how these
           | things were supposed to work together, and those were like
           | mini books. The guides got increasingly ignored as the
           | iPhone's UIKit took center stage. I was always a fan of
           | NSAutoresizingMaskOptions but rarely saw others use them.
           | 
           | Second, modern version control made the binary nib files
           | unmanageable, and merging the xml xib files was also awful.
           | 
           | Third, and to the parent comment's point, there were quality
           | problems with Interface Builder. New stuff got heaped on
           | every year. The data model was proprietary but looking at the
           | xml clearly just got more complicated and version-encumbered
           | over time.
           | 
           | In summary, it is tempting to glorify the original NeXT
           | tools, but I never used them. I started toying with IB in
           | 2004. It never felt like a brilliant system because I
           | couldn't express the underlying logic of designs in the
           | visual box dragging paradigm. Ironically auto layout pushed
           | me further towards UI in code. But to each their own.
        
             | zowa wrote:
             | > [...] pushed me further towards UI in code.
             | 
             | Did you make any progress on this for macOS or iOS/iPadOS?
             | 
             | Out of total hatred of Xcode and Interface Builder I
             | started experimenting with writing Apple UI stuff in C
             | (calling Cocoa methods through libobjc), but there's
             | precious few resources on doing so-called "Nibless/Xibless"
             | development beyond the basics.
             | 
             | I'd love to find a decent-sized open-source macOS app
             | written in [Objective-]C/C++ but with a good assortment of
             | common UI paradigms, all done in code. I shudder whenever I
             | see that dreaded .xcodeproj directory...
        
           | HexDecOctBin wrote:
           | > "springs and struts"
           | 
           | This seems to have originated in something called Visix
           | Galaxy, and supposedly done better there than in Interface
           | Builder. See here: https://wiki.c2.com/?SpringsAndStruts
           | 
           | I tried finding any documentation on this tool/SDK, but no
           | luck. Any one else has any more information on what this
           | Galaxy looked like?
        
             | kragen wrote:
             | i don't know when visix galaxy existed, but springs and
             | struts are how tex did text layout in 01978 and how tex and
             | latex still do it today. 'visix' sounds like a name from
             | after 01978, though i could be wrong
        
               | HexDecOctBin wrote:
               | Huh, interesting. I do keep planning to read the TeX
               | book, just can't find the time.
        
               | kragen wrote:
               | i read it when i was 18 and taking motel reservations in
               | a call center. it has 27 chapters totaling 304 pages,
               | thus averaging 11.3 pages per chapter. you can read a
               | chapter each night before bed in 15 minutes and you'll be
               | done by october. doing the exercises will take you
               | longer, of course, and probably require you to sudo apt
               | install texlive (i didn't have a computer to do that on)
        
         | danielvaughn wrote:
         | I'd been working on a similar syntax for a while, mostly was
         | inspired by some work I did in iOS back in 2015/2016. They used
         | a constraint system and it's honestly pretty great, though some
         | of the more complex features can be daunting.
         | 
         | I'd love something like this:                 red-box {
         | width: 100         height: 100         top: 10         left: 10
         | }            blue-box {         width: 50         height: 50
         | top: $red-box.bottom * 2         left: $red-box.right + 100
         | }
        
           | pistoleer wrote:
           | Yes, that's exactly what I'm talking about!
        
             | danielvaughn wrote:
             | Yeah it would be nice if it felt like saying "this goes
             | here, that goes there." I wanted it to mirror how someone
             | might verbally speak about layout. It gets harder when you
             | consider multi-dimensional layouts like grids, but for 1D
             | things like headers or lists, it would significantly reduce
             | complexity.
        
           | graypegg wrote:
           | I think CSS's own internal logic prevents this sort of syntax
           | from working, since you could be talking about any element
           | matching `red-box`. There's no good way to refer to a
           | specific match of a selector, unless you enforce that the
           | selector only selects 1 thing, even then, that would be
           | conceptually hard to deal with.
           | 
           | I think flexbox and grid handle a good chunk of what you'd
           | want here, but having to handle constraints at the "group"
           | level. Either flexbox, so the browser finds the best way to
           | place elements into a line based on your rules, or grid for 2
           | dimensions:                 boxes {         display: grid;
           | /* there are only 2 columns, 100px each */         grid-
           | template-columns: 100px 100px;              /* all rows are
           | 100px tall */         grid-auto-rows: 100px;              > *
           | {            /* All children take up 1 col, and 1 row */
           | grid-column-end: span 1;            grid-row-end: span 1;
           | }       }            blue-box {         /* blue-box must
           | start at col #2 and row #2 */         grid-column-start: 2;
           | grid-row-start: 2;       }
        
             | danielvaughn wrote:
             | I hear you, though one of the newest CSS features does in
             | fact support this. It's called the anchor positioning API:
             | https://developer.chrome.com/blog/anchor-positioning-api
             | 
             | The problem with this specific API is that it depends on
             | source order. To have element-b anchored to element-a,
             | element-a must come first in source. I'm not really sure if
             | it was designed that way or just implemented that way in
             | Chrome, but it's the behavior I experienced when I played
             | around with it.
        
       | doodpants wrote:
       | It seems that the Clay website (https://www.nicbarker.com/clay)
       | can't be scrolled via keyboard.
        
         | shakna wrote:
         | It's worse than that. The site isn't accessible at all. I can't
         | get my screenreader to make heads or tails of it.
        
           | lelandfe wrote:
           | That's because all the text is inside <div> elements, so
           | there is no hierarchy for a screenreader to latch on to:
           | https://imgur.com/a/D78Tbgk
           | 
           | ...And the three nav links are made via empty, transparent
           | <a> containers absolutely positioned _over_ <div> text.
           | Focusing, therefore, has nothing to read.
           | 
           | N.b both left- and right-clicking activates these anchors,
           | because navigation is implemented as a delegated `mousedown`
           | event on the document.
        
             | codethief wrote:
             | Keep in mind that Clay is a _layouting_ library, the
             | rendering as HTML, as OP mentions elsewhere, is just a
             | demo.
        
         | daemonologist wrote:
         | Yeah the scrolling is handled by Clay rather than being native
         | (everything has position: absolute and there's almost no
         | nesting). It's very cool but I don't know if I'd want to ever
         | use it for a website. Native apps though, might be worth trying
         | out.
        
           | SkiFire13 wrote:
           | As if native apps do not need to be accessible
        
             | darby_nine wrote:
             | Most games, for instance, do not offer accessible user
             | interfaces on any level.
        
               | g15jv2dp wrote:
               | Which is bad.
        
         | TinkersW wrote:
         | Lots of other issues also such as page up/page down on keyboard
         | not working and mouse scroll wheel is very slow(it behaves as
         | if acceleration is turned off).
        
         | avhon1 wrote:
         | It doesn't render anything for me in Firefox, just a blank
         | white page. After a moment, a message shows up: "This page is
         | slowing down Firefox. To speed up your browser, stop this
         | page."
        
           | kragen wrote:
           | yeah, i have the same problem. it's been hanging for almost
           | an hour for me now. probably an infinite-loop bug rather than
           | a working but slow algorithm?
        
           | codethief wrote:
           | Same thing (blank page) for me in Chrome/Vanadium on a Pixel
           | 8.
           | 
           | EDIT: It does work in Firefox for Android!
        
         | nicbarkeragain wrote:
         | Author here, thanks for pointing that out - I'll implement it
         | now.
        
         | nicbarkeragain wrote:
         | I've fixed it up :)
        
       | jb1991 wrote:
       | The website says:
       | 
       | > Fast enough to recompute your entire UI every frame
       | 
       | Yet, when I scroll the front page, made with Clay, it stutters
       | and feels like it can barely handle smooth scrolling, even on a
       | modern Apple Silicon laptop.
        
         | xyst wrote:
         | On mobile, iPhone 15 PM, feels janky as well. It's subtle but
         | it's there. Thought it was just me, but checked the comments to
         | find similar experiences.
         | 
         | Also, poor accessibility as well.
        
           | kragen wrote:
           | i'm guessing that this is because safari doesn't allow the
           | layout code (or anything else) to run while it's scrolling,
           | which with normal websites (which don't use fixed positioning
           | for everything) results in _less_ janky experiences, and was
           | famously critically important to get reasonable scrolling on
           | the original iphone. it doesn 't matter how fast clay's
           | algorithms are if they're not allowed to run
           | 
           | (otoh when i try to load the web page it doesn't work at all,
           | not even jankily, if we're talking about
           | https://www.nicbarker.com/clay)
        
             | jb1991 wrote:
             | The problem is not isolated to the iPhone. I'm using
             | Firefox on a Macbook, still very stuttering site.
        
               | kragen wrote:
               | aha, thanks for the data point! i guess i was wrong; it
               | must be the clay algorithms
        
         | nicbarkeragain wrote:
         | Author here. I'm sorry that it performs poorly on your machine
         | - if it makes any difference, it's the rendering that is slow,
         | not the layout. The HTML examples are more meant as a demo than
         | anything else, as the library actually doesn't do any rendering
         | itself at all, it's exclusively a layout tool. I'm honestly not
         | sure why the performance differs significantly between machines
         | - I'm on an M1 mbp / firefox and it scrolls at 120 fps for me.
        
       | zoogeny wrote:
       | I literally thought of building this kind of thing recently,
       | although I have some differing ideas on how to implement it. But
       | the general idea of a single header C-like file that compiles to
       | wasm and outputs primitive drawing commands is exactly what I was
       | thinking.
       | 
       | What I really want is something like the old Flash/ActionScript
       | display list. Just a 2d scene graph with the option to output
       | draw commands, text or sprites. Things like containers (with
       | things like border/backgrounds/etc.) and layouts can be built on
       | top of that, so you could have two separate header files, one for
       | the display list and another for a layout library.
        
       | aarongeisler wrote:
       | This looks great! I am a big fan of the single header format.
       | I've linked Clay from my list of game resources for C developers.
       | Cheers!
       | 
       | https://github.com/aaron9000/c-game-resources
        
       | mottosso wrote:
       | I was looking for exactly this about two weeks ago for a 3D
       | editor UI and ended up with Facebook's Yoga library. So far
       | things are running smooth.
       | 
       | I would look closer at this library too, if it wasn't for:
       | 
       | "Clay UI hierarchies are built using C macros"
       | 
       | Yikes :S
        
       | jasonjmcghee wrote:
       | For what it's worth, my experience with the linked website was:
       | 
       | - Text selection isn't possible, except on the final slide when I
       | change to HTML Renderer and then it works very strangely
       | (randomly selects all texts sometimes)
       | 
       | - The page crashed: "Error code: STATUS_ACCESS_VIOLATION"
       | 
       | - Also rounded corners look very strange
        
         | nicbarkeragain wrote:
         | Author here - apologies that the site didn't work correctly for
         | you. Just OOI did it default to the Canvas renderer when you
         | first opened it?
        
       | codethief wrote:
       | 2000 loc, no dependencies, well-documented -- this looks very
       | nice! Kudos to the author!
        
       ___________________________________________________________________
       (page generated 2024-08-27 23:01 UTC)