Best Practices for Creating an Enterprise Standardized Data Grid Table in Figma
It’s 2024, Do We Still Need to Build Data Grid Table From Scratch?
This is a question I asked myself countless times while creating data grid table in Figma. Even though Figma has recently launched its first AI features, it still can’t automate this task, as the data grid table is one of the most complex and dynamic components in a design system.
There are several ways to create a data grid table in Figma — you can use plugins or open-source libraries like Ant Design, Material UI, etc. However, after evaluating these options, we found that none of those were able to comprehensively address our use cases, and considerations we had in play. To ensure consistency with our overall design system and product, we decided to build our own. This article details the strategy we used, the process we undertook and lessons we learned building this complex yet table-stakes component on a design system.
From Simple Atoms to Complex Organisms 🧱
Building a data grid is like playing with Lego. The first and most fundamental step is to define the specifications of the bricks.
Atomic Design Methodology provided us a practical strategy to tackle this challenge. The Cell Box is an atom and the foundational component of our data grid. Cells are composed of Cell Boxes. Despite their variants, each cell maintains consistency by being built from the Cell Box. Since each column and row is composed of Cells, it’s crucial that the Cell Box is scalable and adaptable to various use cases.
- The Cell Box has two properties: Style and Size. We used style to differentiates paddings and includes Default and Indent options. The Indent style, specifically designed for tree grids, requires precise padding calculations to ensure text alignment within columns.
- Another key technique was to include all potential components within the Cell Box and add each as a Boolean property for easy show/hide. This approach ensures that any type of cell can be constructed using the Cell Box without compromising its integrity, allowing changes to the Cell Box (such as Height, Indents or Paddings) to be consistently inherited.
Once we have the comprehensive Cell Box, the next step is to build various types of cells. After reviewing all use cases in our product, we summarized 30 cell styles, including combinations like Checkbox + Text, Text + Badge, Status, Sparkline Chart, and Action Icons. Additionally, we defined a Custom style, allowing designers to create cells freely if the predefined styles do not meet their needs.
In addition to style, another property added is ‘states.’ With different states, designers can show interactions on table.
Cell Header uses a different font size and color and doesn’t need to include all the components, we defined its style separately instead of using the Cell Box.
Completing this step means key pieces to construction are done. The next step is to form molecules from atoms. However, we need to make a critical decision: should it be row-based or column-based?
Row-based or column-based? It’s a question 🤔
The debate surrounding this question has been persistent and contentious, as each approach — row-based or column-based — offers distinct advantages and drawbacks. The methodology adopted by one team may not necessarily align with the unique requirements and workflows of another. Consequently, it is important to understand the nuances and implications of both methods before making an informed decision tailored to your team’s specific needs and objectives. The rationale behind our decision to choose the column-based method is the following:
- For our team, tables typically require many columns, each with different types. As product requirements frequently change, designers need to adjust column types and content accordingly. It’s more efficient to change all cells’ types and widths in a column together. If it’s row-based component, designers need to manually update the content of each cell and detach instances to adjust the widths for column consistency.
- The row heights in our table are fixed, with three predefined cell sizes, each with a different height. Depending on the scenario, we select the appropriate size to build the table. This approach eliminates the need for designers to adjust row heights for each table.
- One advantage of a row-based approach is the ease of implementing zebra striping by simply changing the color of the entire row. However, we typically don’t use zebra striping in our tables. Our only use case is to display a secondary row within an expanded row. Since this is uncommon and modifying cells within a row is not particularly challenging, the benefit is minimal.
In summary, the main issue with row-based table is the inability to change the width of a nested element in a component without detaching cells, which is frustrating.
To construct a column with cells is simple. Adding cells from top to bottom and hide some cells. Then wrapping all columns in a table frame with auto layout ensures a responsive table where columns fill the table automatically, even when some are hidden or deleted.
The Structure Is Built, How to Make It Functional?
With a table in place, the next step is to make it functional. Users require more than just a read-only table; they need the ability to perform various operations. Therefore, several additional components are necessary.
Action Bar
Located on top of the table, it supports adding new rows and batch row actions. By default, it supports filter, show/hide columns, download data, search, and view management. Users can filter or sort the data in the table and save it to a custom view.
Footer
By default, it shows the number of entities, refresh timestamp, and hides pagination and edit mode icons. We hide pagination as we usually adopt an infinite scrolling pattern, which is more convenient for browsing, searching, and filtering large sets of data quickly.
Grid Columns Notes
One communication issue we have been facing is UI engineers don’t know which columns should be shown or hidden by default, or the width ratio for each column. After discussion and testing, we came up with this note to clearly outline the necessary information for a data grid. The notes list all necessary columns, shows which columns are displayed by default, which are pinned, and their width ratios, facilitating collaboration between designers and engineers.
Every System Needs Maintenance, Including the Design System
Reflecting on our journey, we encountered several challenges and learned valuable lessons along the way. Building the Design System is an ongoing process, and we have iterated on the Data Grid Table several times based on feedback from other designers.
Fundamental Components Worth More Thinking
We spent a large amount of time creating basic Cell Box. How to group all these elements within it? What padding would look best? Should the width be Hug contents or Fill container? Each of these questions required many times experimentation to find the answers.
Consider Edge cases
“In the real world, the most important problems are often edge cases.”
— Tim O’Reilly
We incorporated few common edge cases also into the extension of Data Grid in the Design System. When the table displays no data, customers are left wondering if they should refresh the page or take other actions. Recognizing this user confusion, we began exploring and implementing an empty state feature.
Be Creative and Enjoy the Creating Process
In upgrading to FlightSuit 2.0, our Design System, we seized the opportunity to conduct thorough research, identifying issues with existing patterns, adopting new methodologies, and exploring a variety of innovative ideas.
As designers, we shouldn’t feel constrained by old patterns; it’s essential to approach each product with a fresh perspective. This continuous exploration and innovation are what make the design process truly enjoyable.
To be Continued
After this release, we began using the new data grid component in our design files and continuously iterated based on actual use cases. In subsequent articles, we will discuss our thought process and iterations in detail. Stay tuned, and thank you for your time!