Get the top HN stories in your inbox every day.
mega-tux
rubymamis
It's so rare to see such a clear and intuitive explanation. This video is amazing.
porjo
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.
undefined
mi_lk
Just watched some of his videos and they are really good. Kudos @nicoburns
riazrizvi
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
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
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.
elcritch
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/cssgridnicoburns
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)
elcritch
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.
wg0
Would be so awesome if single header file also includes the grid layout algorithm.
I think a new framework for lightweight native app development can be built on top. Lightweight flutter sort of.
c-smile
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
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.
bee_rider
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
Text selection and zoomng is also problematic.
wffurr
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
In Chrome, it selects sometimes but sometimes it seems to unselect itself, probably due to the animation happening somewhere else on the page.
red_trumpet
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.
anonzzzies
Zooming is indeed an issue but selection works fine for me on safari ios.
Klaster_1
On Windows/Firefox, text selection doesn't work. Also not working is Home/End and wheel click scrolling. Cool project otherwise.
varispeed
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.
sgt
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.
undefined
jasonjmcghee
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.
Reubend
It's probably because it does it a full reset every frame, and there's an animation playing.
rmac
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 =>
rmgk
If you mean the text position that overflows, that seems to be computed by the library. The same happens in chromium at some resolutions.
bvisness
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.
dgan
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
Hey at least this way other languages can use it
virtualritz
There is also taffy (Rust) which has WIP C bindings.
wishinghand
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.
ahmedfromtunis
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
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
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
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
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
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.
lylejantzi3rd
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.chromanoid
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
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
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.
b3orn
Right and middle click on links behaves like a left click on the website.
7bit
Instant recycle bin.
britannio
So cool. I wonder if it'd work for a Raspberry Pi Pico + https://pimoroni.com/picodisplay or similar devices.
Woshiwuja
[dead]
Get the top HN stories in your inbox every day.
Looks very nice, I just watch a great YT video from the developer here https://www.youtube.com/watch?v=DYWTw19_8r4