loading...
Cover image for Reusing UI within an app with less hassle - judge my demo!

Reusing UI within an app with less hassle - judge my demo!

chrisczopp profile image chris-czopp ・3 min read

This is a continuation of series meant to explain rationales behind the design decisions we took at GlueCodes. In this article I'm going to cover a few topics:

  • reusable slots
  • making HTML dynamic
  • implementation assistant

How we made it

We split our UI into:

  • UI specific to a page - slots
  • UI shared across multiple apps - components
  • UI shared within an app - reusable slots

In our demo we'll focus on the latter - reusable slots.

So why to separate at all? - the answer is rather a common sense - it's easier to get your head around a smaller portion of information than big. Also, something that needs to be shared needs to be first extracted out. But, let's talk specifics.

GlueCodes IDE uses the concept of reusable slots. In your page HTML you can do this:

<div gc-as="slot" gc-name="header"></div>

and the slot will be pre-generated on the fly and you'll be able to choose it from top toolbar and customise the implementation which might look like this:

<div gc-as="slot" gc-name="header">
  <header class="header">
    <h1>todos</h1>
    <input-x
      autofocus
      type="text"
      class="new-todo"
      placeholder="What needs to be done?">
      <script>
        props.onkeyup = async (e) => {
          if (e.key === 'Enter' && e.target.value.trim() !== '') {
            await actions.addTodo(e.target.value)
            e.target.value = ''
            actions.reload()
          }
        }
      </script>
    </input-x>
  </header>
</div>

What's going on here you may ask! What's input-x? Well, the motivation here was to avoid JS expressions in HTML attributes like many templating languages do. Just think about it - JS in HTML!

At some point I've fallen in love with JSX. It's close to HTML, it isn't limited because you have access to pure JS, the learning curve is totally gradual. But that's the case in simple "hello world" apps. In more complicated applications, it may become unreadable because you can use only expression statements in the {}. No block statements i.e. ifs, fors whiles etc. Well, technically you can by either separating your UI into multiple helper functions or assigning vars, but then it doesn't read sequentially as HTML!

return (
  <div>
    {someCondition
    && (firstProgrammer && secondProgrammer
      ? <p><bold>{firstProgrammer}</bold>, you're going to do pair-programming with {secondProgrammer}.</p>
      : (firstProgrammer
        ? <p><bold>{firstProgrammer}</bold>, you'll code this task by yourself.</p>
        : <p>Hey man! Can you tell us your name before we give you job to do?</p>))

    }
  </div>
)

Hence we went for extending an HTML tag with an embedded script which may modify props and have access to actions, actionResults, and styles which is an object of CSS classes scoped to the given slot. So it's as close to HTML as possible and you get full access to block statements. Isn't that sweet? πŸ˜‰

The last thing - Implementation Assistant. In the demo I left you comments to present what happens when you change particular parts of the code. In our example you'll find out you can reference actions which have't been implemented yet. Check this out - I'm pretty sure you'll like it. πŸ˜ƒ

Enjoy exploring and gimme your feedback!

More links:

Our website
The framework repo
Our Kickstarter campaign

Here is the previous post

Posted on May 23 by:

chrisczopp profile

chris-czopp

@chrisczopp

Lead JS full-stack engineer and co-owner of GlueCodes

Discussion

markdown guide