There is a moment every product designer has, when they open a competitor’s interface and think “this looks terrible.” Then they look at their own work and realize, no, actually, the competitor is just honest about what financial software is. It is a spreadsheet. Maybe a very expensive, very slow spreadsheet. But a spreadsheet.
I had this moment maybe six months into working at VALK. We were building portfolio management interfaces for institutional investors, fund managers, compliance officers, asset managers at banks. People who have Bloomberg terminals on one monitor and our product on the other. I kept trying to make things look like a modern SaaS dashboard. Clean cards. Big numbers. Charts. The users kept asking: “Where is the table?”
This was 2020 going into 2021. I was still learning how finance actually works, and the main lesson was this: financial professionals live in tables. Not because tables are better than charts. Because tables are honest. You cannot argue with a table. You can argue with a chart forever.
Why dashboards are mostly for demos
When you are presenting a product to investor or to potential client, dashboards look incredible. Cards with big green numbers, a nice chart showing growth over time, some summary statistics. It photographs well. It works for demos.
Then actual user sits down. They need to find which investor in their fund is overweight in a specific asset class. Or they need to check which deals closed in Q3 and compare fees across them. Or they need to export something for a compliance report.
You cannot do any of this from a dashboard.
You need to filter. Sort. See raw numbers next to each other. You need a table.
I started understanding this at VALK when I watched how people actually used early versions of the platform versus what I assumed they would do. Nobody clicked the chart. Nobody hovered over the portfolio donut to see allocation breakdown. They went straight to the data table, tried to sort by a column, found that the sort did not work, and opened Excel instead.
That was the moment I stopped designing dashboards first and started designing tables first.
The density problem is real and designers are usually wrong about it
Every design school, every design article, every system like Material Design teaches you: reduce cognitive load. Show less. Use whitespace. Do not overwhelm users.
This advice is correct for consumer products. It is wrong for enterprise finance.
Institutional investors want MORE data visible at once. They want to see 12 columns without scrolling horizontally. They have large monitors, two of them. They are trained to read dense tables. When I made the table “cleaner” by hiding some columns and adding more padding, users told me it felt “lightweight”, and they did not mean it as compliment.
I spent real time fighting this instinct to make things sparse. The compromise I eventually landed on: high information density as default, but not visual noise. The difference is subtle. You can have small row height with 8px vertical padding and still have very clear typographic hierarchy. You can show 15 columns if you choose the right column widths and do not add decoration that competes with the content.
The mistake I kept making early on was using cell backgrounds, borders everywhere, lots of color. A table with heavy grid lines and alternating row colors actually makes it harder to scan horizontally than a cleaner table with just a light separator between rows. I eventually removed most borders, kept only a light bottom border on each row, and users started finding information faster in tests.
The 20-column portfolio table
Concrete example. We had a portfolio overview table for one product area at VALK. Asset managers needed to see their entire portfolio in one view. The data model included: asset name, asset type, ISIN or token ID, current value, acquisition price, current price, unrealized P&L, P&L percentage, yield, maturity date, liquidity rating, custodian, jurisdiction, currency, allocation weight, last transaction date, compliance status, and a few internal fields.
That is 18-20 columns depending on the product variant.
My first instinct was to hide most of this. Show six core columns by default, let users add more. This is how Notion, Linear, Airtable handle it. It works well for products where users have different needs and nobody agrees on what is important.
For institutional investors, there was surprisingly high consensus on what they needed to see. Almost every user wanted the same 10-12 columns. The variation was in the remaining 8. So I reversed the approach: show 12 columns by default, let users hide the less common ones. Much better reception. Users felt like the product understood their workflow instead of asking them to configure it before they could work.
The custom column visibility still existed. But the default state was opinionated and correct for the majority of users.
Sorting, filtering, and why they are harder than they look
Sorting is easy to build badly. Single-column sort with a small arrow icon, every developer builds this in an afternoon. But financial tables need multi-column sort. You want to sort by asset type first, then by P&L descending within each type. This interaction is not obvious to design.
I tried several patterns. A sort priority panel, a small drawer that shows sort order visually, worked best. Users could see “sorted by: Asset Type (A-Z) → P&L (high to low)” as chips, drag to reorder priority, click X to remove a sort layer. Felt close to how Excel handles it, which was intentional. These users know Excel deeply. Borrowing patterns from Excel is not a failure of design creativity, it is respecting user’s existing mental model.
Filtering was more complex. We needed to support text search within a column, numeric ranges, date ranges, multi-select from predefined values (e. g., jurisdiction: UK, Germany, Netherlands), and presence/absence filters. Each column type needed different filter control.
Static mockups completely failed to communicate this. I would show the filter panel design and developers would say “yes, looks good” and then build something completely different because they did not understand which filter type applied to which column type, or how filter state should persist between sessions.
Prototyping table interactions in Principle
This is where static design tools reach their limits. Figma is great for showing what a table looks like. Figma is useless for showing how a table behaves.
I prototyped almost every key table interaction in Principle. Column reordering, the drag behavior, where the column ghost appears, how other columns shift. Sort state, where clicking a column header cycles through ascending, descending, no sort. Filter panel opening and how the table reacts when filters are applied. Horizontal scrolling with fixed first columns.
Principle forced me to think about states I would have missed in static mockups. What does the empty state look like when filter returns zero results? What happens when sort column gets hidden? What does hover state on a row look like when row has an inline action button? These are not details you naturally think about when designing screens. But in a prototype you hit them immediately.
I do not think every table component needs Principle prototyping. But any interaction that happens in time, drag and drop, scroll behavior, multi-step filter flow, needs to be animated. Static frames of “before” and “after” are not enough for developers to understand intent, and they are not enough for me to understand if the interaction actually makes sense.
Fixed headers, sticky columns, and horizontal scroll
This is a technical problem that designers often hand off to developers without thinking through. But the choices made here directly affect usability.
For our 20-column table: headers should be fixed on vertical scroll. First one or two columns (usually asset name, sometimes asset ID) should be sticky on horizontal scroll. Everything else can scroll horizontally.
The sticky column implementation looked straightforward until you hit the shadow. When content scrolls behind a sticky column, you need a visual separator, usually a box shadow on the right edge of the sticky column. Simple idea. But the shadow needs to appear only when content is actually scrolled beneath it, not always. Always-visible shadow makes the table feel broken when you are at leftmost position.
Small detail. Matters a lot for perceived quality. I specified it explicitly in handoff, with a note explaining the conditional logic, because I only noticed it after prototyping the scroll behavior and watching it carefully. Without that note it would have been built wrong.
Color coding financial data
Green and red. P&L positive is green, negative is red. This is so universal in finance that it feels like law.
Problem: about 8% of men have some form of red-green color blindness. In a product used by dozens of investment banks and hundreds of users, that is not a small edge case. At some point we had a user complain they could not reliably distinguish our P&L indicators.
I updated the color system to not rely on color alone. Positive values: green text with a small up arrow prefix. Negative values: red text, a minus sign, a small down arrow. Slightly more visually noisy but fully accessible. Users who see color get the same experience, users who do not can rely on the symbols.
I also added a high contrast mode toggle later, which changed the green to a brighter blue-green and red to a more orange-tinted red, both distinguishable for most types of color vision deficiency. This was not in the original design. It came from that one user complaint and then actual thinking about the problem.
Keyboard navigation and screen readers
Financial professionals often use keyboard shortcuts. Bloomberg terminal has trained entire generation of finance people to navigate without mouse. Expecting keyboard navigation is reasonable for this audience.
I specified full keyboard nav for our table: tab through interactive elements, arrow keys to move focus between cells in the active row, enter to open row details, space to select row for bulk action. This required working with developers closely because focus management in a table is actually complex. Which element receives focus when you open a filter panel? Where does focus return when you close it?
I did not have deep background in accessibility when I started at VALK. I learned a lot of this by reading WCAG guidelines and by testing with keyboard only, forcing myself to complete tasks without touching mouse. It revealed problems I could not have found any other way.
Screen reader support for tables requires proper semantic HTML, real <table>, <th>, <caption> elements with appropriate ARIA attributes, not divs styled to look like table. I marked this explicitly in my design specs, though making sure it was actually implemented was ongoing conversation with developers who sometimes preferred div-based approaches for styling flexibility.
Why Material Design table guidelines did not help
I tried applying Material Design’s data table guidelines early on. They are well-thought-out for certain use cases, list of users, list of orders, simple CRUD tables. Financial data tables are fundamentally different.
Material table guidelines suggest 56px row height for standard density. Our users needed 36px or even 32px rows to see enough data on screen. Material suggests limiting columns to what fits without horizontal scroll. We needed 20 columns. Multi-column sort, complex filter panels, column customization, none of this is really addressed.
I am not criticizing Material Design. It is excellent for what it is designed for. But using consumer design system guidelines for institutional finance software is like using a residential building code to design a hospital. Same general domain, completely different requirements.
Our table component ended up being custom in almost every meaningful way. The component library we built referenced some general principles, contrast ratios, spacing scale, but the table itself was designed from scratch based on how our actual users worked.
Every table eventually becomes a spreadsheet
The honest conclusion I reached after a year and a half of designing financial interfaces: users will always want to make it more like a spreadsheet. Not because they hate our product. Because spreadsheets are genuinely powerful for financial analysis in ways that most table components are not.
The right response is not to compete with Excel. It is to be better at the things Excel is bad at, real-time data, compliance-aware workflows, audit trail, multi-user collaboration. Let Excel be Excel. Let our product be the source of truth that feeds into Excel when users need raw flexibility.
I added a clean CSV export to every table we built. One click. Respects current filter state and column order. This single feature reduced friction more than almost any design improvement I made to the tables themselves. Sometimes best UX is giving users a way out.
Building data tables for people who stare at data for eight hours a day taught me more about designing for actual human behavior than any dashboard project ever did. It is detail work, specification work, edge case work. Nobody posts it on Dribbble. But it is where real product value lives.
Originally published on kargaev.me. Imported to blog.deeflect.com archive.