DEV Community

Cover image for Another way to create a user interface - New project
Dev Geos
Dev Geos

Posted on

Another way to create a user interface - New project

Short history ...

We are in the middle of 2021. I got to work on static sites for personal purpose. At the time, I only used Bootstrap and Django for my sites. Interactions between DOM elements are done with vanilla.

I'm looking for ways to avoid repetition and delivered fast, so I'm doing some research. I'm testing REACT, VueJS, Tailwind which seem to work very well but I'm still not comfortable with it. And their learning curves are unpredictable...

Afterwards, I started working on my first tool which will be later released to public: MOD-CSS. I did it to work with to Bootstrap, to do CSS in templates and to prototype quickly.

In 2023, I'm testing SVELTE and I like it. Very easy to understand, intuitive but I'm stuck with the integration into Django. It's doable but it requires some manipulations which breaks my balls ^^. So, event if I love SVELTE, my need for a component manager tiny with single file that integrates with almost any backend remains...

Because we are better served than by ourselves

(in theory)

I decide once again to create my own tool according to my ideal.
In the best of all worlds, a good component manager must at least allow :

  • creation of reusable HTML components
  • Data binding (read-only or not)
  • CSS injection for each component (with possibility of loading via stylesheet).
  • 2 modes of instantiation of components: directly via a tag in template and/or by calling a class.
    • The mode by the class must allow adding of new parameters and/or updating default parameters.
    • Loading via tag must allow customization of the component by modifying/updating of certain parameters.
  • No virtual DOM to avoid slow loading.
  • Monitoring updates on component
  • Everything is full javascript without dependency, only based on vanilla native APIs.

I hate complexity because I am lazy

Yes I admit it, I'm a lazy man. I don't like searching, nor do I break my ass; although as a developer it should be considered a sin not to do it.

I like simple things: a simple object to define its component.

Most of the time, we use Json to save application settings and it works well. Because it's simple, universal, fast and above all it's human readable. why not do the same with components?

A good unbranded t-shirt, which fits well and has a unique color, what could be better? Ok I'm digressing from the main topic.

Short code looks like ...

We create a component that we will reuse

import { Component } from 'http://127.0.0.1:8000/static/Engine.js' 

new Component('liste', {
    template: `<ul class="ul">{{li}}</ul>`,
    css: `.ul { list-style: none; padding: 0; width: 90%; margin: 15px; }
    .ul li { color: {{co}}; background: {{bg}}; padding: 6px 15px; border: 0.5px solid #ddd; cursor: pointer; } 
    .ul li:hover { background: lightblue; color: blue; font-family: monospace} 
    .ul li:first-child { border-radius: 6px 6px 2px 2px; }
    .ul li:last-child{ border-radius: 2px 2px 6px 6px; }`,

    props: {
        bg: 'lightgray',
        co: '#202020',
    },
    events: {
        pointerup: function(event){
            console.log(event.target.textContent + " li hover")
        }
    },
})

Enter fullscreen mode Exit fullscreen mode

As you can see, we can use props in the CSS of the component, which will prevent the component from having the same look each time.
This works like an injection system, so you should in principle be able to dynamically load lists or any data. But, I admit, I haven't test it yet.

1. We instantiate via Tag

The first parameter of new Component() was the component class name/tag name. we use it followed by $.
And the attributes are the props that we are going to update so that they render something else.

    <liste$ bg="#70707020" co="blue"></liste$>
Enter fullscreen mode Exit fullscreen mode

Don't worry, this tag is replaced by its original on rendering.

2. We instantiate via the class

For the moment, via the class, we always instantiate under addEventListener 'DOMContentLoaded'.

The first parameter of new Component() was the class name.
So, we just do a simple new classname() followed by define.

the component will be rendered as last child of the selector you define in parent.

I add another event specifically for this instance.

   // Chargement des lignes
   var array = ""
   var y = ['John DOE - UK', 'Dev GEOS - CI', 'Jack MA - CHN', 'Bill GATES - USA', 'Mark ZUCKERBERG - USA']
   y.forEach((x) => array +=`<li>${x}</li>`)

  // instanciation
     document.addEventListener('DOMContentLoaded', ()=>{
         new liste().define =  {
             parent: 'body',
             props: {
                bg: "#70707020",
                co: "blue",
                li: array
             },
             events: {
                pointerleave: (e)=> { 
                  console.log('Hover' + e.target.textContent)
                   }
            },
     }
})
Enter fullscreen mode Exit fullscreen mode

And finally...

Here is a small presentation of my current project. I grant you the title is not very suitable but if you don't like this design paradigm, I dare to believe that you will do as in the title.

Otherwise, If this interests you, it is with pleasure that I read you and I will tell you more about it.
Let me know please.

Thanks !

PS: Sorry for my bad english ;-)

Top comments (0)