Hacker News new | past | comments | ask | show | jobs | submit login
7GUIs (eugenkiss.github.io)
753 points by miguelrochefort on May 5, 2022 | hide | past | favorite | 113 comments



Related:

Show HN: 7GUIs in Vanilla HTML, CSS, JavaScript - https://news.ycombinator.com/item?id=28600804 - Sept 2021 (56 comments)

7GUIs - https://news.ycombinator.com/item?id=24958725 - Nov 2020 (56 comments)

7GUIs: A GUI Programming Benchmark (2018) - https://news.ycombinator.com/item?id=21883306 - Dec 2019 (16 comments)

7GUIs – A Notational Usability Benchmark for GUI Programming - https://news.ycombinator.com/item?id=15703230 - Nov 2017 (6 comments)

7GUIs – A Notational Usability Benchmark for GUI Programming - https://news.ycombinator.com/item?id=9050480 - Feb 2015 (17 comments including "Very cool to see my master's project here on hn")


I like the temperature converter one because it immediately introduces some of the more fuzzy design questions and annoying details that pop up when you implement data binding.

Such as: when exactly should the other side update? When the user switches focus (where to?) or on every keystroke? Does it make sense to a user that they temporarily see the Fahrenheit value for 2°C if they really want to type in 20°C? What happens if they type an invalid value (or clear the box, which they often have to do)? What happens if they type an incorrect value and then type something into the other field? Etc etc.

I think there are a lot of interesting tensions between a "formally correct" system and one that feels usable and intuitive to use. Especially with bidirectional data flow, they show up quickly.


These are some good UX questions, none of which have a really clear answer.

I think most of your 'when should the fields update' type of questions, have already been solved in Google Translate web UI. There, you can only update the left-sided input field. So there becomes this simple flow of: 1) decide which language you're translated from. 2) edit that value. 3) the UI picks up that a keystroke has not occurred in the last X seconds 4). The right-hand side field updates.


That was kind of his point though. In order to deactivate one side you have to program that in the UI. Also, if you provide this kind of forced directionality to the two temperatures, you now how to make the units toggle on each side ( otherwise you can only convert from one fixed choice to the other - eg. C to F but not F to C ).

As soon as you start asking these questions, the UI requirements change.


Sure, it doesn't remove all complexity. But I think it would result in a more intuitive interface all round.


It’s also good for data formatting. You don’t want to see 22.2222222C for 72F. Ideally when you adjust one, the values are internally consistent.


Good point. This in turn shows the risk of endless event propagation loops: So you decide to solve the formatting problem by using floor() and only showing the integer parts.

So now when the user enters 72°F, it shows 22°C. However, in a naive implementation, updating the celsius field would trigger a change in the other direction as 22°C converted back would round to 71°F. But 71°F rounds to 21°C, triggering another change, etc etc.


Vuejs has a interesting and great way to avoid such feedback loops even in the presence of 2-way data binding. Most importantly you wouldn't use any watchers/effects to trigger logic on property-updates, but rather you use what they call computed property, which can do conversion on the fly, in both directions, giving different behavior on read and write.

    celcius: {
        get() { return this._inputCelcius || ctof(this._inputFahrenheit) }
        set(newVal) {
            this._inputCelcius = newVal
            this._inputFahrenheit = null
        }
    }
Repeat for fahrenheit. Now i've seen shorter examples but most of them are very coupled to the UI, with each event on textbox writing directly to the other textbox attributes, this property can be bound to any number of textboxes and sliders without any additional code to keep them in sync. Similar techniques can be used for more complex synchronizations with conversions, like a date picker that allows both text-input and clicking a calendar.


An interesting solution would account for the precision of the user input when formatting other fields, with different results for 72 and 72.000



I suspect a temperature converter should actually be modelled as a slider, with two labels showing both temperatures.

The user must drag the slider to find the temperature they have, and read the converted version. May be the slider is marked with different axis top and bottom (may be top is Celsius and bottom is Fahrenheit).


you don’t need a slider, just look at a photograph of a thermometer with both scales on it


The slider is there so that you can get an accurate reading without having to use your mouse as the slider or eyeball the scale.


Reminds me of the principles brought up in this talk by Sean Parent:

https://youtu.be/0WlJEz2wb8Y

The temperature converter is a good example of an “implies” relationship, which Sean argues is difficult to model in UIs.


Honestly I think a label, 1 textbox, and 2 buttons- 1 "convert to F" and 1 "convert to C" is just so much simpler.

Or even 2 completely separate pages, 1 for C and 1 for F.


it's simpler and might even be a better UX, but that's not the point of this exercise


I think the point is stated as making the best ux for "bidirectional data flow."

That doesn't mean it has to be reactive.


I implemented these a while ago in Clojure because it was part of the job application process at roam research.

Didn't even get a reply... it cost me quite some hours to do this in a language I have almost no experience in.

At least there was the upside that I got to experience Clojure and Om which was great to learn about :D


You didn't get closure, but at least you got Clojure.


Presumably they used ClojureScript, which does indeed use Closure compiler.


The joke all were thinking, but were afraid to type out. Kudos!


I think you're looking for the Dad Joke thread from a few days ago


I would not waste effort with these test if it is not a language or system you are familiar with (unless you want to for fun). The companies that do this are looking for code monkeys. They want to feed you tickets and get code in return. Many of the people critiquing the submitted code are often not qualified to do so.


In general I'm also not a big fan of these interview assignments but I gotta say it probably heavily depends on how they're used. About a year ago I got my first Go job that way with little prior experience and it ended up being great.

Granted, my assignment was smaller and I knew they would get back to me. If I had been asked to develop a spreadsheet editor from first principles that would have been a major red flag.


I encourage candidates submitting something like this ask the hiring manager what will the process be. Questions like:

- Will feedback be provided on the submitted application?

- What does that feedback look like, are you spending 60 minutes asking about my implementation choices or will you also spend time offering feedback on how I could have improved my solution?

For any hiring managers by providing feedback to candidates you are showing that candidates will grow and develop on your team. By not providing feedback you risk ending up like Roam Research and loosing out on many potential applicants because you demonstrate that you aren't interested in developing your staff.


More than that, I would ask what their acceptance criteria are. I’ve taken a test like this only to get feedback that felt like a giant “got you!” from the hiring manager. There’s so much that goes into coding one of these up, and there’s a limit to how much effort a candidate is willing to put into free work, so this felt kind of bad. This was for Thomson-Reuters on their Clojurescript team.


I just wrote a post about a quite similar experience. I feel like if a candidate takes a few hours to complete a test the feedback could be a slightly more involved process but from the hiring side it doesn't really scale.

https://d22qefpbdavdoz.cloudfront.net/#interviewing-and-fail...


Yeah this really captures what I experienced too. There’s zero back and forth which is how you would actually work with someone. I think that’s what bothered me most — it was an unrealistic situation for how people work together, and there was no chance to defend my decisions or feel out what the actual acceptance criteria were.


I would love to know, collectively, how much labor/time is wasted per year on applications that test whether someone is good enough to do “real” labor. It’s bonkers.


It's one thing to have someone write a toy program. It's another to have someone write seven increasingly-complicated toy programs. That's really grotesque and overkill.


>I implemented these a while ago in Clojure because it was part of the job application process at roam research.

Didn't even get a reply...

Don't feel bad, you're not the only one they didn't bother replying to:

https://news.ycombinator.com/item?id=26316793


The Author passed away. That's probably why you didn't receive a response.


I'm sorry, who passed away? Rich Hickey? Conor Sullivan? Huh


I only see complaints when it comes to interviews. People either complain that they're asked leetcode questions which doesn't reflect the real work, or they complain that they were expected to implement real work tasks which takes too much time out of their week.

Unless your complaint was just about the lack of follow through, that's valid, kind of shitty to not be told that you didn't get the job at least.

Anyways, my point is, interviewing just sucks.


0 Follow-up, that's my complaint. I don't mind doing hard exercises, I find them fun.


The author Eugene unfortunately passed away in 2019.

Source: https://news.ycombinator.com/item?id=24961110


:(


This is pretty neat. The complexity jump from CRUD to Circles and Cells is pretty radical, though.

I feel like a Master/Detail task would be a nice addition, and it could include a resizable divider so that the GUI framework's layout functionality is exercised.


From a web POV I think, yes, but from a platform with something like AppKit it’s very, very straightforward honestly.

Note they’re explicitly encouraging the use of something like JTable/NSTableView in the cells example, the focus is on appearance/behavior customization and change propagation. And in the circles example, undo/redo is ideally provided for “free” by the environment, and with the system’s drawing frameworks & dialogs it really does make for a simple task.

If the environment lacks these basic capabilities though..


> f the environment lacks these basic capabilities though..

And that's the point, right? You're evaluating the toolkit, and if it lacks the features to make these tasks fairly easy, then it's going to be harder to do a lot of straightforward things.

I imagine a similar set of tasks could (and have) easily be contrived for other common libraries/toolkits that are used, such as HTTP client libraries, numerical libraries, etc.


Yeah, I'm primarily an AppKit developer, and honestly the circle drawing task seems a bit easier than the CRUD task to me.


Excellent list of UI challenges. I’ve been working through a similar list of my own to see if I can make a widget library I’m building in Nim do this [1]. Building on an event-driven immediate mode GUI has been fun.

Now I’m totally going to run off this list. I've only got circles and cells left before I can do all of these challenges.

1: https://github.com/elcritch/fidgets


This is missing challenges which include async content and proper error handling, which are both essential in modern web development.

For example:

You're loading or submitting content asnychronously and must handle different loading states in order to give the user feedback. If an action fails due to spotty internet you must also include a retry or refresh button.

You load a model form to modify some data, and when you submit your changes someone else has already made modifications to the model.


Is the second case handled by the "frontend"? Shouldn't be handled by the backend and then return an error state/message?


It's not as simple as cases where both data and logic are local to the gui.

In this identified case, the gui has to react/behave correctly according to the results/errors of asynchronous remote logic over a spotty network.


Not in the list: an example in C and Lua with IUP (an underrated library)

https://www.tecgraf.puc-rio.br/iup/en/7gui/7gui.html


IUP is definitely underrated. On the other hand, there are very few developers indeed.


Great idea, would be nice to use this to compare different GUIs framework. Interested in c++ immediate GUIs, shadertoy.com like GUI and Red language https://www.red-lang.org/



Is a .slint file without an .rs file a complete example or just a work in progress? Curious how you do "cells" without a table widget (Not being a slint user it looks like they used loops to build a bunch of "Text" widgets, but it is the _logic_ of handling them as a cohesive table that I'm interested in, and that seems like a TON of work without a proper table widget)


Yes, the .slint file without a .rs file is a complete example.

They can be viewed with the online editor. For example, the cells: https://slint-ui.com/releases/0.2.2/editor/?load_url=https:/... The cells example is actually not finished and admittedly missing a lot of features, it is far from being a spreadsheet.


This doesn't actually fully implement any of the tasks though.


Implementation in Racket: https://github.com/mfelleisen/7GUI


Racket is so neat. I started learning it through How to Design Programs (https://htdp.org/2022-2-9/Book/index.html) and I was blown away you could paste pictures into the source and assign them to variables and draw them on the screen. I'm not sure why I'm surprised they have a while GUI framework too.


I'm surprised how often I reach for racket just to check something out or explore an idea quickly. I've never taken anything too far with it but it's an incredible tool for that, and because it's so easy to implement languages in it most languages have an implementation in it.

A couple weeks ago there was a burst of posts on HN about prolog, a language family I know nothing about. Took no time to spin up dr racket, find a prolog dialect in it, and play around.

I probably do something like that with it every couple months. And yeah being able to easily visually output stuff from a new language without having to grapple with the tooling and output quirks of a new language takes so much of the initial friction out.


You can technically do that in Xcode, but I don't think they love it as it's been getting harder to do, even though it does still work. For colors it's more interesting since the color itself can be embedded in the source code.


It’s not the only version either

See https://github.com/Bogdanp/racket-gui-easy/tree/master/examp...

  },
  {
    title: "Racket",
    technologies: ["Racket", "racket/gui"],
    link: "https://github.com/mfelleisen/7GUI/",
    src: "https://github.com/mfelleisen/7GUI",
  },
  {
    title: "GUI-Easy declarative GUI",
    technologies: ["GUI-Easy", "Racket", "racket/gui"],
    author: "Bogdan Popa",
    authorLink: "https://github.com/Bogdanp/",
    link: "https://github.com/Bogdanp/racket-gui-easy/tree/master/examples",
    src: "https://github.com/Bogdanp/racket-gui-easy/tree/master/examples",
  }  
]


I’ve been writing SwiftUI lately and it’s the most productive GUI toolkit out there.

Taylor Holliday of the Audulus fame is porting it to Rust

https://github.com/audulus/rui


Yours is the first positive comment I read on HN about SwiftUI.


That could be because early on, SwiftUI was pretty rough. Compile errors were inscrutable and there were various gotchas. It's gotten a whole lot better, and at this point I'd say is mostly a pleasure to use.


It's unlike any other UI Framework I've used and at first I didn't like it. If you approach SwiftUI without doing things the way the framework expects you too it's going to be frustrating. Once I learned how SwiftUI wanted me to think about the UI I found it pleasant to use. The documentation has improved a lot too (as have the third party tutorials), although there are still some suprises that I've encountered.

There is at least one important feature that is missing that many desktop apps need so I can't unreservedly recommend it for that yet, but for mobile development it is very nice. I am much more productive with SwiftUI than anything else.


What is that important feature?


The ability to set the tab focus order if you have a large group of inputs (so that tab and shift-tab cycle through them in appropriate way). The last time I checked SwiftUI had no straightforward way of doing this.


Strange. That's even part of the Apple design guidelines, if I remember correctly.


Why are people complaining? That it’s buggy or that it’s fundamentally flawed?


It can be very buggy (even on iOS 15), especially when you start doing anything complicated. It’s also still relatively new compared to UIKit and AppKit, so it can be hard to tell if something is not working because you aren’t doing it right or if there is a legitimate bug.

It’s missing a lot of features that are currently in UIKit and the way that views are structs and it’s a declarative UI means it can be hard to add custom UI and work around missing features. You have to wait for Apple’s developers to implement things. In UIKit you can just start overriding things (even if you probably shouldn’t).

Also in my experience performance can be awful in ways you can’t work around or fix easily, if at all. e.g. The framework is supposed to diff and determine if things have changed, if two views are equivalent, etc. This can slower than just forcing the system to consider everything changed and nothing is equivalent so it should reload everything. This might be a bug, but sometimes this diffing can happen even when you change nothing. Ive gotten incredibly stuttery performance when scrolling. When I hook it up to the performance analyzer I see it’s trying to diff the whole screen multiple times every frame for static, scrolling content. But this only happens with finger scrolling. Programmatic scrolling (e.g. with the crown in the watch) doesn’t do this and is stutter free.

Finally, Xcode support is bad. It still gives inscrutable errors (that are usually just a misplaced parenthesis or brace) and the type inference system can peg up the CPU at 100% CPU (and then the system will throw up its hands that the type is too complicated to figure out.)

Prototyping in SwiftUI is so, so much faster than in UIKit though.


To add to the list: Coming from the web and being used to having a ton of control how every thing looks I found that customizing elements sometimes have surprising limitations in SwiftUI. Also be wary of trying anything UX wise which is non-conformant with the official spec.

Also xcode in general is such a bizarre IDE compared to the IDEA products or even VSCode which I felt was limiting me severely, even after making quite some effort to adjust and learn shortcuts. I also found that the screen/component preview was just so inconsistent, performance hungry and slow that I stopped using it pretty quickly. I want to like SwiftUI but it feels too rough around the edges for me so I guess I'll check back in a year.

I tried flutter after and it was SO much less painful, more/easier customizable and tooling felt heaps better.


tooling really matters and its the biggest issue with swiftui still...

its what killed ibdesignable and storyboard in the end (too slow, needs to compile the whole app before it can do anything, noisy hard-to-diff xml etc)


I'm the author of rui, in case anyone has questions :)


How different is the state managementin SwiftUI compared to the state in rui?


I've built some of the same sort of primitives, albeit with different syntax. Rui's `state` function will give you a state handle allowing you to mutate state similarly to how @State works in SwiftUI. rui also has a notion of bindings, just like SwiftUI, and even environment. This is all great for defining state that's local to a widget, which I've seen some other reactive/declarative libraries struggle with actually. Rui doesn't have an equivalent of @ObservedObject, and it's not clear to me that it needs one because state values can be accessed by reference.


I like SwiftUI, but somehow I still like UIKit and even AppKit a little more. Some things are still just slightly too broken in SwiftUI, for example navigation. In the WWDC talk when they introduced SwiftUI they said that we can let Apple do the work of making the UI just by listing what we need, but I don't trust Apple to do this yet.


You can go back and forth relatively easily. I think that even if most of your views are still NSViews/UIViews SwiftUI makes sense even just to hook them up. ViewControllers are an anti-pattern.


You should usually use a UIView instead of a view controller anyway (if you do UIKit programmatically, which is the only sane way to do it). Then it is easy enough. I have my own little layout library on top of AutoLayout, and at that point SwiftUI is nice to combine with UIViews.


How are ViewController an anti-pattern? It depends how they're used, no?

And yeah it's easy to use a SwiftUI view in AppKit or UIKit using a UIHostingController or NSHostingController


A big part of what ViewControllers do is synching data. I think that bindings do a better job at this.


Bindings might be better but that doesn't necessarily mean that ViewControllers are an anti-pattern. Is there a better way to do it in an non-declarative OOP way?


not the op but what i usually do is just write a plain-old-class with actions/outlets/delegate-methods and place those in the storyboard/xib

if you are programmatically doing it, then you can just init it directly or use some injection/indirection mechanism

you can use the responder chain to send messages up to the nearest view controller if you need to, and if you need some lifecycle awareness, you can always delegate those from the view controller in various ways (protocols, notifications etc)

testing is also easier since they are plain objects with a few methods on them (just fill in their outlets with mocks and you are ready)


Except for the part where components are locked to an iOS/macOS version. Still have to support iOS 13 ? Have fun basically doing everything with only VStacks.

Compose at least makes it only a library bump away.


  > Compose at least makes it only a library bump away.
this to me is the most annoying thing with regard to swiftui and apple development in general... especially considering swiftui views are mostly wrapping uiviews....


So I’m still not sold on SwiftUI, and I’m beginning to think I’m learning the wrong paradigms to “get it.”

What would you say are the core concepts that make it click for you? Do you have any resources to recommend?


Did you watch any WWDC videos? Also the objc.io book on the topic is decent.


The videos from PointFree [1] are also excellent.

[1]: https://pointfree.co


First time I see it, pretty nice framework. Rust needs more of those.


Watch this space. Specifically I am writing up my ideas for a fusion of SwiftUI and Druid, inspired in large part by Taylor's work on rui. This work is conceptual at the moment, not a finished product, but I am hopeful it will be a better direction for UI in Rust.


I did this exercise with Godot Engine : https://triptych.neocities.org/sevenguis/index.html


I was nostalgic/excited by the 20 second loading bar, brings me back to the dialup days. Unfortunately afterwards I was greeted by a black screen. Looks like it doesn't work on my phone :( Time to get out of bed, I guess!


would you recommend Godot for GUI applications that aren't games? Is it a good tool for it, and is it better than using electron?


I was wondering if one could write something actually worth taking home and showing to others.

1 - Make your resume into a slide show with background music.

2 - Create fancy transitions

3 - replace the numbers in your slideshow resume with fast running counters that count up to the desired value.

4 - add something original that you feel should be part of the task

5 - create a fully functional inquiry form as the final slide of your resume

6 - All tasks are optional, have the amount of work you put in reflect how desperately you need this job.


Nice list. One change I would make for the CRUD example is to do a Todo list instead since it might be more useful/doesn’t teach bad assumptions about names.


I agree with the premise, but please, anything other than a todo list.


Do similar tasks exist that would apply more generally to picking up any programming language? Working on non-trivial projects seems to be a great way of learning new languages and tools, and I wonder if there are a set of projects that would touch on a decent chunk of a what is offered by a typical language.

Then again, every language has its strengths and weaknesses so perhaps such projects do not exist?


I like to implement a Conway Life engine for this purpose. Small self-contained problem that requires UI, timing loops / iteration, and graphics.

It's also embarrassingly parallelizable if your language supports parallelization primitives you want to exercise.


Games are a fun way of trying out a new toolset. I've implemented a few sudokus now.


Minesweeper is always fun!


It has been taken over and moved to a new site

The website hasn’t been rebuilt but you can see the list of implementations here: https://github.com/7guis/7guis/blob/master/site/src/containe...


It’s a useful list. I think some of the interaction design could do with updating though - things like disabling buttons without explanation and popping up modals for data entry are no longer universal UI toolkit tropes. Different interactions might be more idiomatic in different contexts and - while you’ll learn a lot by implementing these exactly as specified, in some cases it might be an uphill struggle - and the reason could be that the framework is trying to tell you to implement it another way.

So a second version of this challenge might be to implement the same capability, through a more native interaction idiom. Suspect much can be learned by doing it both ways.


Only 8 days late, but I have an implementation of this in PyScript as well: https://jeff.glass/project/the-7-guis-pyscript/


Very pragmatic, there's more to this I think than we might recognize.

Using these as template starting points is a great idea.


First time heard about this, now I know why the vuejs examples I am learning is calle 7 examples: https://vuejs.org/examples/#hello-world

this is like the Todo applications for GUI


I did an implementation using We components https://crisdosyago.github.io/der.Knall.Gerust/7guis/


> In addition, all cells which depend on C must be reevaluated. This process repeats until there are no more changes in the values of any cell (change propagation).

What if there are circular dependencies?


> What if there are circular dependencies?

You could model the dependencies as a directed graph, and ensure that there's no cycles in the graph, and if there is, don't evaluate and warn/error msg the user.


Svelte won't let you. Knockout claims it isn't a problem. What happens in Excel, are you able to create circular dependencies there and crash Excel?


How would Svelte prevent a user from creating an infinite recursion at run-time? It doesn't know what the cell's expressions are at compile time.


Not stated, but I'd do what Excel does which is to have a maximum recursion level.


I tried this out using Lazarus and Free Pascal and it seems pretty trivial to do - except for the timer example which will take a little bit more time.


Some of these seem like they could be really cool challenges in the context of a designer/engineer job interview


Nice. I might try these out in AppKit


Just for fun, I timed myself doing the first one in both AppKit and SwiftUI. I started with Xcode running but no project created yet, and hit stop when the app was launched and I had clicked the count button. It took me 1m57s to do it in AppKit, and 3m16s in SwiftUI. (I'm far more experienced with AppKit than SwiftUI).


Nice. Just out of interest (since I'm new to AppKit), did you decide to use Storyboard or a XIB?


Storyboard, but I don’t think that would have made a difference in the time it took me.


This is awesome. More! Thank you.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: