DEV Community

Cover image for A Lightweight GUI Library for Low-code Platform
Zongbin
Zongbin

Posted on

A Lightweight GUI Library for Low-code Platform

Preface

The GUI config panel can be used in any low-code platform, such as prototyping tools (Figma), website building platforms (Webflow, Framer), BI reports (Power BI, Looker Studio), 3D model building (Spline, Womp), animation editor (Rive), etc., these are some very famous online tools.

Acrodata GUI is a lightweight GUI library for low-code platforms, now it's open sourced. πŸŽ‰

GitHub: https://github.com/acrodata/gui
Playground: https://acrodata.github.io/gui/playground

What is GUI

In front-end, we rarely use the description like GUI, so many people mistakenly think that GUI = UI library.

So what exactly is a GUI? For ease of understanding, we can refer to the more famous GUI project dat.gui. For those who have done 3D visualization or ThreeJS must be very familiar with this library. The main purpose of dat.gui is to convert configuration items into graphical controls to debug parameters.

dat.gui

In addition to dat.gui, there are several other GUI projects that are also doing well, tweakpane, lil-gui, leva.

Configuration panel in low-code platform

For those who have used low-code platforms or developed similar products, the layout of low-code platforms has become commonplace. On the right side of the layout is usually a configuration panel. Of course, the same goes for a lot of the software we use. Just post a few screenshots of some tools.

Webflow

Spline

Looker Studio

First of all, not every low-code product requires GUI generation configuration. For example, in the Webflow (first screenshot), the configuration items of all its components are the same (all are CSS visual configurations). In this case, it will be simpler to develop a common component.

However, for products like Looker Studio (third screenshot), each chart component has a different configuration and it allows users to customize chart component, so this type of product is in great need of a flexible and easy-to-use GUI library.

On the homepage of the Acrodata GUI documentation site, I used the GUI to create a complex CSS gradient generator. It is very similar to the configuration panel in the low-code platform. You are welcome to try it out.

Acrodata GUI

πŸ‘‰ View CSS gradient generator source code

How to design a lightweight GUI?

Due to the complexity of low-code platforms, GUI libraries must be designed to be able to combine arbitrary data structures while being simple and easy to use.

JSON-based configuration items

To support custom components, GUI libraries are more suitable for configuration using JSON data. This is very different from the use of the GUI libraries mentioned above. Let's take dat.gui and Acrodata GUI as examples.

Assume that the configuration items of a certain component are as follows:

const options = {
   content: 'Hello world',
   opacity: 0.3,
   visible: false,
}
Enter fullscreen mode Exit fullscreen mode

The usage of dat.gui is as follows:

const gui = new dat.GUI();

gui.add(options, 'content');
gui.add(options, 'opacity', 0, 1).step(0.1);
gui.add(options, 'visible');
Enter fullscreen mode Exit fullscreen mode

Although the usage of dat.gui is very simple, this functional declaration method is not suitable for dynamic components and is not conducive to data storage.

The usage in Acrodata GUI is like this:

<gui-form [config]="config" />
Enter fullscreen mode Exit fullscreen mode
const config = {
   content: {
     type: 'text',
     name: 'content',
     default: 'Hello world'
   },
   opacity: {
     type: 'slider',
     name: 'opacity',
     min: 0,
     max: 1,
     step: 0.1,
     default: 0.3
   },
   visible: {
     type: 'switch',
     name: 'visible',
     default: false
   },
}
Enter fullscreen mode Exit fullscreen mode

The structure of the above GUI configuration items is the same as that of the component. You only need to convert the value of each field in options into the JSON declaration of the UI control.

πŸ‘‰ View more basic control examples

Nested data structure

If you want to ensure that the GUI can generate any data structure, you need to design the definition format of JSON configuration items for five basic data (string, number, boolean, object, array). The above example has shown how three basic data types are defined.

The definition of object in Acrodata GUI is as follows:

{
   "size": {
     "type": "group",
     "name": "Size",
     "children": {
       "width": {
         "name": "Width",
         "type": "number",
         "default": 1920,
         "suffix": "px"
       },
       "height": {
         "name": "Height",
         "type": "number",
         "default": 1080,
         "suffix": "px"
       }
     }
   }
}
Enter fullscreen mode Exit fullscreen mode

The last array type is the most complex. Commonly used arrays include basic data arrays and object arrays, and each array also supports dynamic deletion of array items.

The following is how a dynamically deletable object array is defined:

{
   "series": {
     "type": "tabs",
     "name": "Series",
     "default": [
       { "id": 1, "name": "bar" },
       { "id": 2, "name": "foo" }
     ],
     "template": {
       "name": "No.<%= i + 1 %>",
       "children": {
         "id": {
           "type": "number",
           "name": "ID"
         },
         "name": {
           "type": "text",
           "name": "Name"
         }
       }
     }
   }
}
Enter fullscreen mode Exit fullscreen mode

If the array items of the object array are not the same, they must be defined with the tab type:

{
   "misc": {
     "type": "tabs",
     "name": "Misc",
     "children": [
       {
         "type": "tab",
         "name": "Full Name",
         "children": {
           "firstName": {
             "type": "text",
             "name": "First Name",
             "default": "James"
           },
           "lastName": {
             "type": "text",
             "name": "Last Name",
             "default": "Bob"
           }
         }
       },
       {
         "type": "tab",
         "name": "Contact",
         "children": {
           "phone": {
             "type": "text",
             "name": "Phone",
             "default": "5550100"
           }
}
       }
     ]
   }
}
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ View more group control examples

With the above five basic controls, any data structure can be generated through nested combination.

Limitations of JSON Schema

Why not use JSON Schema? Many people may think that using JSON Schema to define JSON data will be more standardized and more general. This idea makes sense, but JSON Schema also has certain limitations.

First of all, JSON Schema can only define the data type of the field, but cannot define the UI type of the field, so some dynamic form solutions that use JSON Schema will also add UI Schema, such as react-jsonschema-form.

In addition, the format of JSON Schema is relatively complex, and the mapping relationship between component configuration items and JSON Schema is very unintuitive.

Build a GUI based on reactive forms

Acrodata GUI is built based on Angular's reactive form, with only about 200 lines of core code (View source code ).

In order to facilitate traversing data in the template, you need to convert the GUI config object into an array, and use the registerControl of the reactive form to register all form controls in the instance of FormGroup. Then use the reactive form directives formGroupName, formControlName, formArrayName in the template to bind controls of different type.

Acrodata GUI uses Angular Material as the basic component library. All styles and components are imported in modules, so redundant code will not be generated. Other component libraries can also be used.

Start using GUI components

<gui-form [config]="config" [model]="model" [form]="form" />
Enter fullscreen mode Exit fullscreen mode

config represents the JSON configuration items of the GUI. The configuration items of different types of controls are slightly different, see the documentation for details. In addition to using default to define the default value of the control, you can also use model (form value, equivalent to the component's configuration item options) to define or update the default value of the form, thanks to Angular's reactive formpatchValue method.

If you need to monitor the state or value changes of the form, you can use the form parameter, which can track all state changes of the form.

form = new FormGroup({});

this.form.valueChanges.subscribe(v =>{...});
this.form.get('opacity').valueChanges.subscribe(v =>{...});
Enter fullscreen mode Exit fullscreen mode

Summarize

The GUI shown above is very powerful, but GUI can't completely replace the dynamic forms and not all configuration items are suitable for using GUI. Because the GUI has limited control types and does not have complex logic, maybe you should make a choice to use or not in a low-code platform.

If you like Acrodata GUI or have better ideas, please feel free to communicate with me!

Top comments (0)