New UX Pattern: Infinite Pagination

I have been thinking about combining two well-adopted UX patterns: Pagination and Infinite scrolling. According to Nielsen, Infinite scrolling is a listing-page design approach which loads content continuously as the user scrolls down. It eliminates the need for (traditional) pagination. Both patterns have advantages and disadvantages so whether to use one or another is a design choice. I decided to experiment and to combine both patterns, because while infinite scrolling has its benefits it also causes some usability issues especially when it is applied for desktop browsers. TLDR; scroll down with pages!

Introducing Infinite Pagination. Basic design of it is simple: it is vertical pagination where scrolling loads the next page starting from selected page (or page 1 by default). Another important thing is that each page is visually represented as a page – with a page number. There are previous work close to this called Infinite pages, but design and definition differs in my opinion. The idea behind the Infinite pagination is that it allows user visually accumulate already explored pages so that a page creates structure which is easier to grasp. Basically, when a user scrolls down, a new page will be loaded and the already loaded pages form a linked list. So this design allows random page access but keeps pages in order continuously.

Improving Data Grid (Table) Design: A Generic Design

Tables have evolved during the age of HTML. Nowadays it is more reasonable to make the difference between tables and data grids (aka data tables). A table is a visual data arrangement with rows and columns whereas a data grid is a table formatted arrangement of complex data and behavior. For example, in data grid you typically can search, filter, select, etc. data. You often see also actions for the data items – either single or bulk actions…

Designing data grids is not easy, and there is no single correct design that would fit for all use cases. The correct design is what fits for the purpose. However, there are some common features which I expect to see in a well-designed data grid. Also, many of designs out on the internet have decent design and user experience. But to me many of the implementations are not really outputs of a design process. So I wanted to design one of my own.

Data grid layout follows the design that I have found working well: it has header, menu and/or app bar, footer, left section, middle section, and right section. Left section is reserved for navigation where as right section is reserved for actions and/or details. The middle section is where the data will be located. As depicted in the image, there will be also optional part that is reserved for options depending on the context.

Data grid layout

Table data is one part of the layout. Let’s concentrate on to it next. There are tabs:

  • TABLE tab for viewing and selecting all data
  • FILTER tab for searching, filtering and selecting all data
  • CART tab for viewing selected data. User can insert and remove data (rows) from different views: the analogy would be shopping cart in web shops
  • OPTIONS tab for extra functionality

There are some important design choices too

  • Any row in any tab should NOT contain buttons or actions although it is a fairly typical approach. IMHO, it leads into bad UX. However, it is totally okay to have links – especially text format links. Actions should be displayed the right section (as discussed earlier). The analogy for actions is that you can think of it so that when you click a link in a column of a row it will open up “mouse right-click” view in a separate pane.
  • There will be single and bulk actions. Bulk actions can be executed only in the CART tab where it is possible to “remove all” and “remove selected” rows. This leads also to a meaningful separation of selecting and collecting. Selection should be understood so that the user clicks or touches one row which makes the row selected (or unselected with another click or touch). When user’s selection is marked by checking a checkbox, it will be defined as collecting it. Collecting/dismissing is done using the check marks.
  • When the user wants to collect all rows of a (paginated) page, they can click checkbox in the first column: checking it makes all rows collected, and unchecking makes all rows uncollected. If there are rows collected before clicking the checkbox, all of the rows become collected i.e. uncollected rows become collected. But note that the checkbox make only one page collected!
  • So how to collect all rows? Especially if the number of rows is large: for example let’s say 1000+ rows. IMO, the correct approach is to use Table tab menu where there should be options: “Insert all” and “Insert collected”. In the CART tab where the collected rows are visible, there will be only a mark that “All rows selected”, and there is no pagination because practically speaking going through so many pages is just not possible for humans.
  • Different extreme cases where grouping should be used are
    • “All rows selected” (as discussed)
    • “No rows selected” (it is not a good practise to display nothing on page)
    • “1000+ rows selected” (custom max. limit has bee reached)

Actual design of the table data part is show in the image. As said, there should be possibility to collect items (first column). Compared to many other designs the only new thing is the tabs, which is done because we don’t want to have Actions on rows at all.

Data grid table data design

There is still one unsolved issue: what if your SQL-query is a view using JOINs and having multiple million rows. In UI, humans can process only about 1-1000 rows. This means that result set size must be made smaller:

  • There can be a Query builder that narrows down database query and therefore the result set as well: the more exact query, the less result set items
  • It can be that the result set of the database query is still very large, for example tens of thousands of items. But since UI will still accept only a sample size of max. 1000 items the UI will display only “All” option
  • Whenever the result set size, after making the discovery/search query more exact, is less than 1000 items, they are displayed in the UI
  • When there are 1-1000 items in the result set, then they displayed in the UI as rows of the data table.

So we can say that there are three important parts:

  1. Database contains all rows
  2. Search function queries a subset of all rows
  3. Filter function can be used for exploring the subset

Semantically speaking in case search query return set size is more than maximum size, then we must not allow any write/modify operations over that group. In those cases, the UI should show only information about the group like size of the group and other statistics.

Improving Usability of Material-UI Transfer List

improved transfer list

Material-ui (MUI) provides React components for faster and easier web development. It allows you to build your own design system, or start with Material Design. What a fantastic effort and free to use! But not all of the components represent great design / UX unfortunately. Some of the components design is just copied from the “old” internet. And you guessed right, one of those components is the Transfer list. Transfer list pattern is also known as List builder pattern. The good thing about it is that it uses other components as building blocks. But still, the UX of it is just not up to par of the design system – cf. most of the other components.

There are many alternative designs for similar functionality. What I found useful were post from clearly experienced designers. One of the best posts actually tried to understand user behavior by collecting data and analyzing it: you must check it out from medium!  Another good post was Nielsen’s Listboxes vs. Dropdown Lists“. It should be pretty obvious that there is no one correct design, but some work better in certain context. For example, in the medium post the Foursquare badge based method is showcased.

One major trend is that a big proportion of the website visitors use mobile devices, which have inherently smaller screens than desktop/laptop computers. The Transfer might work with mobile devices but it is not a good match. The documentation states that it is meant for moving items from one list to another. To start with, the buttons are not intuitive nor they describe what they do. Users who are not familiar with this pattern might be afraid to click them – i.e. lose control. Next thing that comes into my mind is that what if the lists are long. You need to choose between showing all the lists in one screen or showing less list items in each list.

material-ui transfer list
material-ui.com Transfer List design

So this got me thinking. Could I try to contribute somehow. Well, I certainly can try: here is my proposal for improving the Transfer List UX. The design is based on general filtering pattern where filtering is reversed i.e. all of the data is available, but only for additive action first. This means that the secondary list has initially zero items. Later, when the list has items, the user can remove them from there with reverse action i.e. remove items.

The different lists are on top of the component: represented as a Toggle button. By clicking the button the user can switch lists. Optional filtering text field means, of course, filtering through the list items – whether “Select” or “Selected” in this case. Note! The filter itself should allow selecting: “All” and “None” options enable selecting all or none of the currently available items (i.e no checkbox next to an item). List content is shown/listed next. The gray arrow is not really part of the design, but it represents the presence of the vertical scrollbar for scrolling through items if there are too many to show all of them on the screen – according to some UX best practises the scrollbar is needed if there are over 6-7 items. Nor is the filter text field needed if all of the item fit into space reserved for the vertical list. You can select an item by checking the box in front of the text – and unselect it by redoing the action. Selecting an item should make it unselectable/disabled: it should not disappear from the “available” list so that the user seems every item in the list; but “selected” list should contain only selected items! Finally, the button on the bottom is used to execute the action – in this case adding the items to the “Selected” list. The opposite action is of course “Unselect items -“. That’s it, what do you think? Should this design replace the current design?

Actual implementation of this looks like this. First image shows a list of selectable items: please note that there are few selected items, which are shown in the second image. The second image shows a list of selected items. The component is available in Github

Web Form Design 101 (With Validation)

For some reason it seems that form design is left out in the UI frameworks like Material UI (MUI). Maybe the use cases are always too different to come up even with a single opionated design, because there is none. This post tries to lay out basic principles for a simple form design that includes:

  • How to use material design forms “correctly”
  • According to identified best practises
  • Assuming design is mobile first, but plays well with desktop too
  • Aiming to make forms more conversational!
  • Leaving multi-step forms aka. wizards outside the scope

Let’s get started.

The UX design part

Good list of UX sources for form design:

Good list of UX sources for form validation errors:

About animations, which IMO is really effective when used correctly

Basic scenarios.

  • user inputs wrong data -> single field immediate validation
  • user submits form -> life-cycle of form and groups validation
  • validation errors
  • submission errors

Reading through the sources I have identified the following best practises:

  1. Design for touch devices, and NOT for mouse. Mouse works too if the design is for touch devices. So for example, don’t use onHover events.
  2. Single column design, which works for both desktop and mobile screens.
  3. A form can have many different actions: primary, secondary, ternary, etc.
  4. Group related fields together to form logical sections – groups can be optional too – then must be marked as optional – don’t use (*)
  5. Ask as little information from user as possible – but incrementally
  6. Mark optional fields instead of mandatory ones, and use the “Optional” label to denote optional fields – don’t use asterisk (*). Sometimes it might be usable to label field with text like “(mandatory), (optional), (disabled)”.
  7. Field label is fixed and above the the text field. Don’t use floating labels, and don’t use captions
  8. Don’t use placeholders, but prefer masked input if needed.
  9. Typical structure for the field row: [leading icon] field [trailing icon]. The field itself: [icon | text] value [icon | text | action]. Text can be e.g. the unit like EUR, $, kg, etc. In MUI icons are InputAdornments and they can contain action. Action can be for example dropdown (see combo-box) or open calendar…
  10. Avoid select lists – it should be your last resort
  11. Validation error messages AND helper texts are placed under the input field. Use tooltip on-hover next to label when user might need extra information, help, suggestions, etc. – but avoid using tooltips for errors!
  12. Validation error messages must be informative: e.g. how error can be repaired. There are many guidelines which involve validation errors: see Nielsen articles for this
  13. The submit button should have clear click-to-action text: not “Submit” but “Create account” (verb-object)
  14. Opinionated, but IMO there can be cases when two buttons are required: then link button for “Cancel” and real button for CTA i.e. different styles for primary and secondary buttons

A note for complex forms or forms with a lot of fields (some of them optional and/or infrequently used): “hide irrelevant control” is a good guideline! So for example, when using a query builder, the query builder should be composable of parts, which user can select. This of course means that the query builder itself must be buildable – build a query with a query builder builder (no mistake here…)!

P.S. There are some validation libraries available

  • Formik: A form library that helps to manage form state and validation.
  • Yup: A schema validation library often used with Formik for defining validation rules.
  • React Hook Form: A library for managing form state and validation using React hooks.

Improving Your Grandad’s Web UX Pattern: File Upload

File upload. It was cool back in the 1990s when Internet was invented. Ever since it has been used, but never really improved until big companies like Google, Microsoft, Dropbox started to invest in web technology. And even still there are new players claiming that file upload is still a problem that needs solving: at least Resumable File Uploads.

What is file upload anyways? Why do we need it?

  1. User needs to move a file between desktop computer and a remote computer. It is easy way…
  2. Relatively secure due to browser sandbox technology
  3. Browsers are and work everywhere

But in an ideal situation, would we need it at all? Ideally:

  • The file doesn’t to be transferred – it is magically where you need it
  • User can just select the file and here the simultaneously the upload is removed, which should lead into simpler error cases
  • No upload means not waiting, which leads into great UX!
  • This virtual drive could be mounted everywhere i.e. user has one connectable drive that can be shared across different services as a “remote local” drive (cf. Dropbox)

Practical solution and thus the new File Upload (UX) Pattern:

  • A shared directory to where files are uploaded before using them (so yes, in a way an new extra step at this point)
  • An upload can be done using different options: existing HTTP form upload, object storage, IPFS, mounted NFS, webdav, whatever…
  • Synchronous, asynchronous, parallel upload for both UI based upload (form) and API based upload (HTTP, Ftp, gRPC, …)
  • HTML5 based file manager (GUI) and virtual drive: normal HTTP based upload is one offered method, but other integrations are possible too as mentioned. See Dropbox or Google Drive for an example.

Modern file upload pattern

Let’s assume that there is a web form with a submit button. In this example, you send your name, email, and personal photo to register to an online webinar. The important part is how photo upload happens:

  • A user sees a empty form with input fields.
  • The user selects image for a personal photo
    • The user’s virtual drive (similar in UX to what Dropbox or Google Drive has) opens up. This is functionality is called “file manager”
    • The file manager is shown with upload/download file options
    • The user selects “upload from my computer” and file manager uploads it normally (using asynch file upload protocol)
  • The user goes back to the registration form
  • The user selects the photo from the virtual drive (this is possible only after the photo is completely uploaded) and a preview is shown
  • The user enters name and email and hits submit to send the form
  • The user registration is completed!

So what is different? Often the file upload happens when the form is submitted, which is the grandpa -pattern. The new proposed pattern transforms the way file upload is thought: you should think like every file is already at the remote location and you choose the file as you would on your local desktop computer – or on your mobile too.

Dropbox.com

For implementing client-side functionality for uploading files you can use ready-made libraries like uppy.io (see image below for a screenshot):

uppy.io

P.S. When you do file upload like this, you will receive additional benefits like possibility to do file conversions (for example with pdf-tools pdftron or with pandoc or with libreofficelibreoffice-script=soffice --convert-to pdf --headless <FILE> --outdir <DIR>“), file versioning, (internet) file printing, file content preview server, etc.

UI and CLI Are Equivalent!

The idea? End-user’s interaction with webapp in a browser has equivalent command line command sequence! And how to avoid duplicating interface implementation for CLI, UI, and API? The answer is that the API should be the master API and both the UI and the CLI should use that. We can also go further and force UI to transform its API requests into CLI commands so that CLI can execute them. One potential use case is that many people might want to stick with the old UI event though the webapp evolves: see my post about this earlier. So in short, the pipeline could looks like this:

UI/Browser -> CLI -> API

For example, let’s imagine there is a service called “Deals” that informs you when there are good online deals available in your favorite online stores. If the user “[email protected]” types his email address in a form field and hits Submit button to register himself to a new service, the equivalent textual CLI command could be “deals register ‘[email protected]'”. Nowadays for example gloud service providers prefer using CLI – at least to cover most complex interactions.

Modern web application often consists of fronted (Javascript) application, application programming inteface (REST API), and backend. A concept in modern programming languages it a tool called Command Line Interface (CLI) that allows for example Repeat-Eval-Print-Loop (REPL) loops. Nowadays strict separation of the frontend from the API and backend is a popular design choice. I will claim that the following is true and that treating UI and CLI as interchangeable concepts is the future of web apps:

  1. Frontend is separated and it is independent from the backend. HTTP requests are text.
  2. Interactions which come from the UI should be formatted as they were native CLI commands and queries. This new idea has immediate impacts:
    – every UI command and query can be translated into CLI alternative, and vice versa
    – API must accept them as-is
  3. When backend implementation gets changed the API contract must not be changed.
  4. When frontend, i.e. UI, is changed the visual appearance should not changed always. It can change, but it should not be obvious that it changes. Changes increase cognitive stress for end-users, and typically require educating them.
  5. CLI can but not must require interaction with a user, which is programmatic automation requirement!

Automated testing is still quite difficult and the tests are brittle. What if you could test browsers by using visual AI to recognize different DOM elements and compare different interactions with textual output! The whole point is that text is still the de-facto way of communication in computer systems. The UIs exists because they hide complexities and improve discovery. So I propose that make your UI CLI compatible, allow users to use CLI alternatively, require textual input and output in APIs, and finally understand that visual layout should not change always when implementation changes – it is a contract too. . And see my other post about Human interaction Interface (HII)

Some requirements flow backwards too: many CLIs don’t provide proper synchronous and asynchronous communication patterns. And also many CLIs don’t return well-defined and parseable output e.g. in JSON format. Similar to APIs you should be able to provide arguments which state in what format the caller expects to receive response. For Linux, there are tools like “jq” which alleviate current situation, but good design is what we need!

P.S. There is interesting development going on related to this topic: see for example CLUI that is about how to build a graphical command line tool! In a way, also command-line auto-completion is also a UI: see for example client for PostgreSQL.

P.P.S. Another interesting development project is the tool that allows you to turn (almost) any Python Console Program into a GUI application with one liner.

Stop Changing My UI, I Don’t Want New UI!

The problem: with a new software there usually comes a new user interface (UI).
The solution: decouple UI from implementation, and continue using and iterating existing UI instead of building a new one.

Analogies:
* Google Material design: the visual design is the brand, but also it “is a visual language that synthesizes the classic principles of good design with the innovation of technology and science.” You can easily create web app components which implement the design. Also, on technical level components can expose an API for modifying them. I would like to extend the idea of design and contracts to the UI level to solve one very common problem. End-users are loaded with continuously changing applications. I argue that sometimes the UI should NOT change. For example medical systems. To summarize, Material design decouples design from implementation.

Existing old features should work the way they do now and not change visually or behaviorally, new features must follow the existing design and extend the functionalities of the existing app.

– end-users must learn new system means cognitive load
– old features change and might break (regression)
– new features are often the reason for starting using a new system

But there is a way: what if we start thinking User Interface (UI) as a contract.
– companies would actually own the Intelligent Property Rights (IPR) to the UI (and to automated tests written against it)
– (frontend) app itself would be separated from the backend app with an API (RPC, SOAP, REST, etc.)
– UI functionality must remain the same, no matter what changes in the backend: visual and behavioral contracts!!!
– software supplier can be changed: both frontend and especially backend

Benefits:
– end-users would not need to learn old ways of doing things, new features would accumulate meaning end-users can learn delta i.e. what has changed
– testability: ability to write automated UI tests with frameworks like Katalon or Robot.
– collecting and analyzing usage could be more long term and stabilized. Would allow improved end-user insight and control over features life-cycles.

Human Interaction Interface (HII)

What is Human Interaction Interface (HII)? It is a term that I invented to describe a potentially useful extra layer on top of representation layer (MVC) on the client side… It is a concept similar to that of Google’s layer for separating style from design (Material Design). Now HII is about separating user interaction from the user interface (i.e. the representation)

 O 
-+-
 | 
/ \
---
HII
---
MV*
---
API
---

The User Interface (UI) does not cover the interaction, which means true physical interaction between a person and software running on a piece hardware. We do need a way to model the this interaction between physical human world and digital computer world. You can argue that for example HTML forms already provide means for this (with mouse and keyboard), but there are certain problems with them. First and foremost, the HTML is not easy to test. Improvements would definitely be beneficial in this domain.

Although modern web browsers implement many WEB APIs they could benefit from an Interaction API. There are some existing efforts made in UI markup languages which abstract application development using XML. For example, VoiceXML and JavaFX are represented in XML format, but they could be rendered into HTML as well. Another way of looking this is visual flows in BMPN frameworks: inputs and outputs only are relevant. Anyways, the Interaction API would allow getting rid of HTML when defining application behavior.

When writing automated tests for a web application using React, I found myself writing HTML selectors (for Selenium) for Katalon/Robot framework. Now, the selectors themselves are pretty brittle, but most importantly the development flow goes backwards: I was writing selectors and adding element ids after I had already completed writing the app itself. There is nothing wrong with re-factoring code to make it more testable per se, but the changes I made caused me to add more code and the code became more messy – definitely not the right direction. And automated testing is a basic requirement for a high quality app.

My tests follow the usual pattern of Arrange-Act-Assert (AAA), and they are mostly automated end-to-end tests, which allow effective testing targeting end-user value. But again, because of how web apps are coded, the tests themselves became cluttered. I noticed that I would definitely benefit from being able to clearly define what are the required inputs from the user and the outputs from the system. For example, a user registration flow could require user’s email address, and the system would generate user name for the registered user.

But what is the Human Interaction Interface (HII) then?It sits between user and hardware that is used for controlling both inputs and software. The interface defines needed input and outputs which are required for specific flows. In Katalon, for instance, I end my test with an assertion which checks that all outputs for the end-user are given. And please note, this is a final check at the end; often tests just wait for certain (fixed) output from the system, but in my case the assertions cover the whole end-user path.

And before going any further I want to stress that figuring out user inputs and system outputs, creating arrangements and checking assertions against outcomes is REALLY painful when doing it by selecting HTML elements or attributes and checking their values etc. Automated testing is painful when HTML is present. Cleaner representation leads into easier testing…

If you have ever coded VoiceXML (VXML), you will have easier time to understand where I am going at. Since the “computer” is a telephone and the “keyboard” is the keypad, it is easier to realize that the “computer” awaits user’s input in a specific position. It is in a way “aware” of itself – it would be better to say that it is aware of its state. Typically internet apps are controlled by the user and thus the browsers are not aware of their states. HII makes it possible to define the sequence for interaction with the computer. And it also stores relevant user inputs and system outputs to the flow. And as stated: it is intelligent, so it knows what input is expected from the end-user. This (meta)data can be used for automated testing!

So how does my idea differ from the VXML or similar. Well, I would borrow and combine keywords into my idea. Keywords are keywords how they are defined and used in automated testing frameworks like Robot or Katalon. What I really like about the keywords is that they provide quite abstract and high-level means to describe WHAT. Keywords can contain variables which can be resolved and populated dynamically like in Ansible!

But there’s even more potential when you consider Accessibility (A11Y): many websites using HTML are lacking logical flow structures, which is not the case with for instance VXML. When the logical flow is present in HTML pages, it also makes it accessible: for example navigating the site using keyboard and a screen reader. Another way of putting is that websites are often missing semantic structure, which is partially solved with accessibility.

P.S. To retrofit this kind of feature in HTML5 is difficult. I would suggest trying to store some of the flow data to HTML tree where it can be accessed with normal testing selectors… Inspiration could be taken from Page Object Model (POM).