Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.
Blazej Sewera edited this page May 31, 2022 · 7 revisions

UI Design

When designing the UI of Notipie, I tried to maximize usability, and minimize complexity of the interface.

Inspirations

My main inspirations for the interface were Apple Human Interface Guidelines and Google's Material Design, but by far the most inspiration was taken from Github Primer.

I tried to break down what is useful, what is unnecessary in my project, and extract only the essentials for my design.

Final design

The card

The card is a building block for the entire user interface. It provides the most interaction in the whole application, therefore it had to be designed with clearly laid out information and intuitive controls.

The card with labeled elements

The card itself consists of several elements:

  1. logo, it can be an image or automatically generated SVG from the first two letters of the app's name,
  2. indicator, whether the notification has been seen or not,
  3. title of the notification,
  4. subtitle,
  5. body, that collapses after it reaches a certain length, so that an ellipsis appears ([...]),
  6. information about what app sent the notification and when it happened,
  7. controls to archive, mark as read, or go to external site connected with the notification, like a certain build on Jenkins, or the notification page on Github.
The card with guides

The card was also designed with aesthetics in mind. All elements were carefully positioned and aligned, so they are not only pleasant to look at, but also have some features important for visual communication:

  • the rounded corners take the focus away from the card frame, and provide a natural, neutral enclosure for the notification,
  • the inner padding is of equal size in each direction to provide optical stability,
  • the distance between the logo and title – subtitle combo is the same size as the padding, making the logo appear centered,
  • the title – subtitle combo itself is centered vertically relative to the logo,
  • the distances between the logo, notification body, and app name – timestamp combo are shorter in order to make the inner section more connected,
  • the controls are centered relative to the app name – timestamp combo,
  • the unread indicator is unobtrusive enough not to steal all the focus from the card's content,
  • finally, the unread indicator is positioned slightly outside the inner section, so that it belongs to the card itself, not its content, therefore it is easier to spot at a glance.

UI component library

When choosing the library for the UI components, I considered:

All those libraries are very popular, so I chose React, because I had the most experience with it in my professional work.

UI networking

The nature of notifications required me to use both REST data fetching and asynchronous data pushes from the backend. For the latter, I decided to use WebSockets, a standard defined in RFC6455, and RxJS, an implementation of ReactiveX library.

REST data fetching

I used simple REST requests for fetching the notifications that are already on the backend server. The standard Fetch browser API was sufficient for the task.

Reactive Raven

This project was an experiment on using RxJS for all real-time data fetching, enabling the separation of concerns in the code, and decoupling the state management implementation from the networking implementation.

More of the reasons for making such an experiment are in this section.

This separation of concerns enabled me to migrate from Redux to Zustand as my store implementation, as described in the next section.

State management in UI

To simplify the frontend code, I needed to use a single source of truth for the data. I used both Redux, and Zustand for this task as store implementations, and Zustand came on top as a simpler solution for my application.

Redux

Redux is great for big applications with lots of components. Being one of the most popular state management libraries for React, it was my first choice.

Unfortunately, it required me to write a lot of boilerplate code, and thus was not easily maintainable for a smaller project like Notipie.

Zustand

Zustand is a lot simpler than Redux, requires a lot less boilerplate code, and was sufficient for my application. I migrated to it in commit 7677d13, and it reduced the lines of code by over 200. I did not however give up the connected components, as they provide better testability and separation of concerns, which is worth a bit extra code for that.

TypeScript in UI

I decided to use TypeScript in my project for the frontend part because of its type checking tools, huge popularity, and a growing demand for in on the job market.

Choosing the language

When choosing which language to use in the UI, I considered a couple of options:

  • plain JavaScript,
  • TypeScript,
  • Elm, and
  • CoffeeScript.

I immediately discarded the last two, due to their smaller popularity compared to JavaScript or TypeScript.

The featureset of the language was also very important to me. JavaScript is by far the most popular, but it lacks type annotations or pre-runtime type checking. TypeScript and Elm turned out to be winners in the type checking toolchain.

TypeScript also has a big advantage of being very similar to plain JavaScript, so the transpiled code is very readable.

A big factor was general trend of language's popularity growth. TypeScript was a clear winner in this scenario, being third most loved language and second most wanted language in the Stack Overflow Developer Survey 2021. It was only beaten by Rust and Clojure in the Most Loved section, both of which are non-frontend languages, and Python in the Most Wanted section, which is also not a frontend language.

Another report confirming the growing popularity of TypeScript is Github Octoverse Report 2021. Since 2017 it beat Ruby, C, C++, C#, Shell, and PHP and is, as of 2021, fourth top language on Github.

Working with TypeScript

Starting with TypeScript was fairly easy, the toolchain was included in the project creation scripts. Most dependencies had good TypeScript annotations, or they were completely written in TypeScript, which was very helpful for maintaining type safety.

Learning the language was also very easy. I was already familiar with JavaScript, so I only needed to learn the type annotations, which were very intuitive to use.

Build system

For the build and bundle software, I wanted to use something modern, with hot module reloading, easy to use setup scripts, customizable development server, and short bundle times.

Snowpack and Vite

I started with Snowpack and used it until I decided to move to Vite in commit c11bc35.

Snowpack offered both hot module reloading and short bundle times, however, there were some minor problems from time to time, the project had a slow development, and the alternative, Vite did not seem to have those problems.

I tried Vite in my other project, Reactive Raven, and the integration with React, TypeScript, Tailwind CSS, and other tools I used was seamless, therefore I decided to migrate to it in Notipie as well.

On April 20th, 2022, Snowpack's maintainer stated in the project's Readme document (commit 45456aa) that they would no longer maintain the project and mentioned Vite as a good alternative for it.