Creating custom table components
Tables are the bread and butter of data analytics applications. While at Tracer, a marketing data processing platform, I led the implementation of our updated design system that we nicknamed Emerald Forest v2. Our users, the analysts for our clients, almost always used Excel so our goal was to match and exceed the feature set they were used to with a directed focus on digital marketing analysis.
As with any quickly growing application we soon created several, similar components representing tabular data that shared traits and often duplicated code for common use cases such as column headers; select-ability of rows; data formatting for titles, numerical data, currency formatting; and action buttons.
After we conducted our component audit (see my post on Design Systems for more details) we broke down our data representation into 3 styles:
- Dataset → Displays large “blob” like datasets and is more robust than the other table types to make scanning the lengthy content easier.
- List → Lists records by displaying a subset of their data such as name, date, etc. that can be clicked into for more detailed view.
- Standard → a lightweight table mostly used for displaying a short or example list of data where performance and scannability are less of a concern.
My particular focus was on the “dataset” table type. Our original implementation of this table quickly could not handle the size of datasets that were being fed into it, causing flickering during scrolling, slow responsiveness, and a clunky user experience overall. There were also a handful of quality-of-life updates we wanted to integrate that simply wouldn’t work with the original implementation.
I decided to build the table in pure HTML and CSS as much as possible, reducing the overhead of having JS integrated components and adding extra <div> layers to the DOM. This also unlocked other performance upgrades such as:
Virtual scrolling
I chose to integrate a lightweight plugin called Clusterize.js to append and remove cells as they enter and exit the viewable area to limit the cells actually present in the DOM at one time.
Pivots in CSS
I could calculate the pivot height based on the provided data blob and use CSS Grid cell merging to create actual pivot rows in the table with sticky content. In the previous implementation we could only mock this behavior with a floating component tied to a scrolling event.
Resizable columns
I tied a mouse move event to column sizes stored in React state that was then used in a Styled Component to update a CSS Grid that was the basis for the whole table.
This new approach also allowed us to do some simple updates that we could not accomplish before without a heavy refactor including selectable pivot text, so analysts could copy ad names, for example, to look up in ad platform tools, and right aligned numerical data in a monospace font for easy scanning.
You can play with a live version in the published Storybook here.