Back

Show HN: 7GUIs in Vanilla HTML, CSS, JavaScript

144 points3 years7guis.bradwoods.io
dsego3 years ago

This is what you can end up with, managing all possible state changes manually. I've done this myself with jQuery, show/hide, enable/disable elements. Turns into a game of Whac-A-Mole and full-time job for testers. Now imagine adding/removing elements and having to update this monster. No thank you.

https://github.com/bradwoods/7guis-html-css-js/blob/19279899...

whalesalad3 years ago

Monster? It's very straightforward, functional and easy to follow. You could easily refactor that and break it up without fuss. Not sure what the big deal is here. The fact that it operates on a state machine makes it even easier. You can see all the different ways the UI will render by stubbing the state value.

dmix3 years ago

The problem is when you have a large app with multiple components and plenty of state to manage. These things always look easy when they are small toy isolated projects.

This sort of thing in a production app would be littered with global state, it would be difficult to change anything / refactor without serious anxiety, if you have multiple developers good luck getting them to program the same predictable way, importing libraries see previous point, etc, etc.

dsego3 years ago

Yes it's okay for this example. I think it can get out of hand.

jdthedisciple3 years ago

Not the worst. Seems acceptable imo, yes its a long function with giant switch statement but its pretty clear what it does and easy to read.

dsego3 years ago

Adding a few more fields would require me to update every case plus add some more, no? Resulting in an hard to maintain explosion of state? Or am I missing something.

https://statecharts.dev/state-machine-state-explosion.html

tonetheman3 years ago

What are the other options here then? Not trolling just wondering. If an app has state it has to be dealt with somewhere...

edflsafoiewq3 years ago

You can dispense with the whole intermediate state variable and just do everything directly

  function calcState() {
    // Return field disabled for one-way trips
    elems.return.disabled = isOneWay();
    
    let allOk = true;
    
    // All enabled fields are valid?
    for (const f of [elems.departure, elems.return]) {
      const isInvalid = (
        !f.disabled &&
        isBadFormat(f.value)
      );
      setInvalid(f, isInvalid);
      if (isInvalid) allOk = false;
    }
    
    // Return trip after departure trip?
    if (allOk && !isOneWay() && isEarlyReturn()) {
      allOk = false;
    }
    
    // Enable submit if everything is OK
    elems.submit.disabled = !allOk;
  }

  function setInvalid(elem, invalid) {
    elem.setAttribute(ARIA_INVALID, invalid);
  }
This follows the problem description quite closely, eg. "The return textfield is enabled if the combobox’s value is return flight" is implemented by one line, and not spread across seven different enable/disable calls.
BiteCode_dev3 years ago

I like it, and it's also a good example of why a framework will start to be useful if you get more complex code.

When we arrive at the CRUD widget,a simple <script> dep on petite-vue (6ko: https://github.com/vuejs/petite-vue) would half the implementation by half.

Of course it would still count as more lines of code in total, but not sure that matters.

Anyway, when I teach react/vue, I always start with the vanilla example because just like with ORM, people need to know the benefit and cost of the abstraction.

dsego3 years ago

I think this is a good teaching example of doing GUIs with the DOM and the MVC approach. It builds up step by step to introduce all the concepts.

https://github.com/madhadron/mvc_for_the_web

seer3 years ago

A few years back I stumbled into something a bit more complex, still done in pure js, just for the hell of it: https://github.com/morris/vanilla-todo

And then wrote my own version, with code a lot closer to modern react, with undo/redo and other niceties - https://github.com/ivank/vanilla-teuxdeux

And what I leaned is that is astonishingly easy to write code that would be understandable to people coming from the redux crowd. Maybe that’s because redux is just such a simple concept in and off itself - a glorified switch on a big object. And it’s also quite easy to hack a simple version of vdom to make it all work.

What’s missing from all those vanilla js efforts though turned out to be testability. There is a ton of code in the modern js world just to allow you to mock/test your components, and thats for me the real tragedy of vanilla js.

I have no idea why W3C crowd have not invested into standardizing js tests in all these years…

benatkin3 years ago

The Cells example is super interesting to me, because I've longed for an open source, liberally licensed, spreadsheet component for the web, similar to what exists for rich editing (ProseMirror, Slate, Quill). Some UI frameworks like Material UI have a neat table component, but the pro version gets the fancy data grid, and it isn't designed to be able to function as a spreadsheet anyway.

Besides lacking an open source version, spreadsheets and data grids haven't been studied as well as they should be.

It is also difficult to build one using just the DOM. For instance, you can't have a table be horizontally scrollable with the scrollbar fixed at the bottom and also have a fixed header.

Here's something I played around with a while back that has keyboard navigation between cells. Going between pages isn't great. The default focus scrolling in Chrome skips a few rows, and it doesn't respect the fixed header when scrolling up to the top after scrolling down. https://table-edit-20210409.vercel.app/ https://gitlab.com/ResourcesCo/table-edit-20210409 I tried making it with CSS Grid just to see if it could be done, and it turns out, only with Firefox. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_La... I'm thinking of drawing it with JavaScript, perhaps with a combination of canvas and DOM elements.

Back to the 7 GUIs - what's great about it is trying to build stuff from scratch. So much of web development is just putting components together and customizing them, but there is a lot of lower level work to do, and the more developers that attempt it, the more progress will be made.

Edit: found this, pretty interesting: https://github.com/TonyGermaneri/canvas-datagrid

csande173 years ago

> For instance, you can't have a table be horizontally scrollable with the scrollbar fixed at the bottom and also have a fixed header.

You might actually be able to do that with position:sticky now: https://jsfiddle.net/0ydsve3x/1/

benatkin3 years ago

I couldn't get it to work with a table - only with having to scroll all the way to the bottom to find the horizontal scrollbar.

Edit: hmm, it's working in the CodePen here: https://css-tricks.com/a-table-with-both-a-sticky-header-and... I'll have to fully revisit what I was trying to do and see if I can get it working.

Edit 2: Oh, I realized that I wanted the horizontal scrollbar to be sticky when it is an element taking part of the vertical space of a page, but more than a screenful. I found this that solves it but not for a table with a fixed header: https://amphiluke.github.io/handy-scroll/ To see what I'm talking about, go to the top of the demo, horizontally scroll, and note that horizontal scrollbar is shown when scrolling horizontally. Then click disable, and note that it isn't shown when scrolling horizontally, unless you go all the way to the bottom. Or, if you don't have a trackpad, you actually have to go all the way to the bottom to scroll it horizontally.

scns3 years ago

Have you tried holding shift while scrolling?

benatkin3 years ago

Yeah, it doesn't make a difference, and my use case is scrolling with just a mouse.

jhgb3 years ago

> because I've longed for an open source, liberally licensed, spreadsheet component for the web

I assume SlickGrid (https://github.com/6pac/SlickGrid/wiki/Examples) didn't satisfy your requirements?

benatkin3 years ago

I hadn't checked it out in a while. Thanks. It satisfies some but not others, and is a bit more monolithic. I found a project called slickgrid-universal by one of the recent contributors. This looks neat except it takes a while to scroll: https://ghiscoding.github.io/slickgrid-universal/#/example11

adlpz3 years ago

These examples are very reassuring to me. Sometimes, after a long day of fighting whatever trendy JS framework my current project uses, I may be tempted to advocate for a "back to the basics" approach with vanilla JS or even jQuery.

Anything after the temperature converter example makes it painfully obvious that it would not be a pleasant experience.

tdeck3 years ago

The whole environment around JS frameworks had got to be especially intimidating for new developers. There's this false sense that you can't do "anything" these days in JS without a package manager, a build pipeline, a local server, a view library, a state management library, etc...

Meanwhile all the functionality of vanilla JS is still there, and the language and runtime are arguably much better than they ever were.

It's worth experimenting with these things every now and then on your own, even if you don't have a simple setup at work.

_red3 years ago

Not arguing your point, because I believe its really valid.

However, the issue is, any moderately complex application will soon develop its own in-house Framework. Its the natural progression, very soon the head Dev will say "lets create a library to handle all our form validation requirements....lets create library separate UI from business logic...etc"

That's the real "slippery slope" from a management perspective.

Do we wind up developing our own in-house Framework which our current developers are very productive in (but new hires don't understand)? Or do we bite the bullet and opt for an already existing Framework that already has a dev community? I'm not suggesting its an easy answer as there are pros/cons to each. In the end for 90% of cases I think starting with an existing Framework (or at least "Framework-lite") is best approach.

dspillett3 years ago

> intimidating for new developers

Or in my case seasoned developers who have been away from that front (concentrating on database/infrastructure/security matters) for some time and might like to catch up a bit. I can still do things the vanilla (or jquery/similar) way but that might not be ideal, but beyond that the sea of choice is daunting to think about navigating.

Or maybe I've been away so long I should consider myself to be a newbie in a new environment, instead of just a bit out-of-date in one that has moved forwards rapidly in my absence!

fendy30023 years ago

It works well until you need to manage many states in one page. Even with knockout js, when an application become a little complex, it become hard to develop.

rimliu3 years ago

Alas, the common thing I see this days is devs fighting infrastructure instead of developing product.

tonis23 years ago

Yep,it has become popularity contest for frameworks, and in the end they make developing even harder.

Otek3 years ago

That's simply not true. You know better than thousands of developers who are using React or Vue in their projects, and they are just making their life harder?

+1
sgc3 years ago
bradwoodsio3 years ago

nodemon was my build tool.

z3t43 years ago

The trick to write vanilla HTML is to make it static (no dynamic changes except layout/mobile responsiveness) Meanwhile the trick to writing a statefull app in vanilla JS is to not use HTML instead create the DOM tree using JS functions which gives you the ability to use higher abstractions, local/private state management and automatic UX tests.

xixixao3 years ago

Now get that list of different implementations going.

I’ve been thinking of something similar, and this is a good list, but is it “exhaustive”? What would such a list look like? Is there an objective way to explore all the various challenges of building UI?

Here’s one example: Very large forms. This is not covered, and can be quite challenging, especially when different parts of the form show up at different times. Even vanilla React fits this poorly (this is where Flux came into being, which ultimately spurred Redux, Recoil etc).

But also a CLI. A flow chart. Notebooks (Jupyter). So many types of UI to cover.

chrismorgan3 years ago

The cells example would be improved by keeping the top left corner clear by making that cell stick in place and on top:

  #colHeadings .rowHeading {
    z-index: 3;
    top: 0;
  }
I also believe keyboard navigability is essential for the cells example, although the task specification neglected to mention it. (But then, the spec doesn’t specify anything about the formulas either—though it does include a picture depicting something like =SUM(B1:C4).) Tab and Shift+Tab work to shift cell focus, but that’s all; at the very least, Up/Down/Left/Right should work for cell navigation, and some way of entering edit mode without needing the mouse (start with F2, which is standard across spreadsheet apps that I know; perhaps Enter too, though they don’t).
benatkin3 years ago

This also doesn't have that issue, and it's also using a z-index: https://css-tricks.com/a-table-with-both-a-sticky-header-and...

bradwoodsio3 years ago

Good points.

brianzelip3 years ago

Regarding the author's content online - great work! Nice minimal design with clean and bold lines, right alongside a fantasy and whimsical design from the early days. Love the education background - keep up the good work and output!

WA3 years ago

Very cool. I had to code a Cells app in Java back in university, too.

One thing though: add undo/redo to the Cell task as a requirement. After all, "a good paradigm should give you this functionality for free" :)

tobr3 years ago

Imagine if a GUI programming benchmark had GUI specifications with reasonable UX? The 7GUIs designs are criminally bad, especially CRUD and Circle drawer.

aethertron3 years ago

Then you'd need more complex implementations, which would be more difficult to compare, muddying up the point of the exercise: to produce various comparible implementations.

tobr3 years ago

I don’t believe that the UX problems here are motivated by reducing complexity. Perhaps the circle drawer one, where any reasonable redesign would turn it into a direct manipulation GUI, but honestly direct manipulation is table stakes and something that you must be able to implement, and not really that complex in most cases.

The CRUD example is just bad for no reason. It looks like a typical master-detail view, but the detail view doesn’t give any feedback when the selection in the list changes.

aethertron3 years ago

Hmm. Well, that circle-drawer is indeed atrocious. But its atrocity is according to the design spec. It says to use a modal window with a slider. Everyone's supposed to build the same thing. Your criticisms should go 'upstream' to the original 7GUIs task specifier, eugenkiss (whose domain has been hijacked by some gambling operation, onoes!)

eta: Bad UX granted, I gather that the task is meant to compare DX. (And it'd be useful for comparing coding approaches by individuals, for evaluating interview candidates. For that purpose, it'd perhaps be useful to be able to test a person's particular design choices, and how they interpret the spec, perhaps to see if they are justified in building something not-quite-to-spec.)

eta2: https://eugenkiss.github.io/7guis/tasks#circle

Man, look how detailed this is. I suppose some people's job as developers is to literally implement specs exactly. Glad that's not my job. But maybe some folks would prefer not to have to deal with ambiguity.

tobr3 years ago

Yes, my criticism is about 7GUIs as benchmark, that’s right there in my first post.

yarcob3 years ago

Yeah, this benchmark is way too specific. Would be much more interesting to see how different implementations could take advantage of their frameworks. Eg. some frameworks may make it easy to use animations, or they may have reusable components like date pickers. And of course they should take the target device in account - phone apps should look different from desktop apps, and they would probably also look different from control interfaces on industrial equipment.

bradwoodsio3 years ago

They are pretty windows 95ish.

xupybd3 years ago

I just read some more of Brad's stuff. His piece on problem solving is worth a read.

scns3 years ago

Can you supply a link please, could not find it. His page is worth looking at, even if it takes a while to load.

(edit) nevermind, found it: https://garden.bradwoods.io/notes/problem-solving

wsc9813 years ago

The Cells example doesn't seem to work properly on my Mac in Safari:

https://7guis.bradwoods.io/cells/

bradwoodsio3 years ago

Classic Safari, I'll get right onto that.

dspillett3 years ago

Was the problem an error on your part (that other browsers let you get away with) or something that should be OK but Safari doesn't support properly that you had to work around?

dmitriid3 years ago

Hmm... Worked fine for me (unless you fixed something since your comment) :)

The only "issue" I see: visually it's hard to see whether a cell is just focused, or is in edit mode.

bradwoodsio3 years ago

I thought about making the blinking cursor a lot fatter to differentiate the 2 different states.

wsc9813 years ago

Thanks it works now. I ain't a web dev but it seems like some nice examples. I also like the black-on-white UI, reminds me of classic Macintosh systems :)

whatsapps20203 years ago

Cells and Circle do not work on iOS

begueradj3 years ago

smart approach, but a framework would be needed for complex stuff

splch3 years ago

Fun Fact: 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999°C = 32.00°F

phist_mcgee3 years ago

That is a fun fact