Skip to main content
Back to blog
  • Other

Updated 12 min read

How should a B2B SaaS product design data tables, filters and saved views?

A B2B SaaS team can decide what filters, saved views, columns, paging and row actions should do by filling in one specification worksheet per table, then testing each decision with a short acceptance check.

Illustrative situation: a collections manager at a B2B billing platform opens the invoices table every Monday. She filters to overdue, over $5,000 and owned by her team, sorts by days late, hides four columns and pastes the link into chat for a colleague. The colleague sees every invoice, in a different column order, newest first. Later that week an admin edits the shared “Overdue” view to add a region filter, and the manager’s Monday list quietly loses rows. Nobody can say which view is the real one, so she keeps a screenshot. The scene is invented, but the pattern is common: filters, columns and views were built as separate features, and nobody decided what a “view” is.

Humbleteam, a digital product design agency, publishes this guide. It treats a table as a set of decisions a team can write down and test: what task the table serves, how filters behave, what a saved view stores, how rows load, and what a click on a row does. A worksheet near the end collects them.

What job should the table do?

Nielsen Norman Group (NN/g) names four core tasks a table should support: find records that fit criteria, compare data, view, edit or add a single row, and take action on records. Rank them for each table before drawing anything. A collections queue is mostly find and act. An audit log is find and compare.

The ranking also shows when a table is the wrong tool. Carbon’s data table guidance says not to use one as a replacement for a spreadsheet application. If people need 30 columns side by side and their own formulas, the right deliverable may be a good export, not a bigger grid.

Two NN/g defaults are cheap. Make the first column a human-readable identifier, such as an invoice number with a customer name, not an auto-generated ID. And order columns by importance, with related ones adjacent, so nobody’s eyes travel between column 1 and column 20.

How should filters work?

Start with the labels. NN/g’s guidance on filter categories and values asks for filters that are appropriate, predictable, free of jargon and prioritized. In one NN/g test, a vague “Item type” category beside a more specific “Style” category sent a participant to the wrong place when she looked for sandals. In B2B products the usual culprit is internal status codes. Use the words your customer’s finance or ops team uses.

Then decide when a filter applies. Carbon’s filtering pattern separates instant updates, good when users make one selection, from batch updates behind an “Apply filters” button, better for several selections across categories and for slow data return.

Show the state. NN/g says users should be able to tell at a glance that the data is filtered. Carbon adds that when filters hide in a drawer, the closed control needs a count of applied filters and a way to clear them without reopening it. Polaris suggests no more than 2 or 3 promoted filters, and the rest behind a menu.

Logic needs a stated rule. GitHub Projects treats multiple filters as AND, and multiple values for one field as OR, and does not support OR across different fields. Linear’s filter docs describe advanced filters with AND/OR logic and nested groups. Our suggestion: use AND across fields and OR within a field by default, write the result as a sentence (“Status is Overdue or Disputed, and Owner is my team”), and put nested groups behind an Advanced control.

Design the empty result. NN/g warns that a blank panel after filtering leaves users asking whether it is still loading, failed, or just empty, and recommends a short status message. Its guidance on no-results pages adds starting points. Our suggestion for a table: name the active filters, offer “Remove Region: West” on the most recent chip, and offer “Clear all.”

Which columns, sorting and density should people control?

NN/g says hiding and reordering columns must be low-effort and accessible to people who don’t use drag and drop, with a clear indicator when columns are hidden. HubSpot’s edit-columns dialog pairs checkboxes with drag-to-reorder. Stripe notes that column choices in a report apply to the on-screen view, while exports have their own column selection. Whichever you build, tell people which of the two a setting changes.

The WAI-ARIA Authoring Practices sortable table example wraps header text in a button and sets the aria-sort attribute on the sorted column. Add a stable tiebreaker, such as the record ID, so equal rows don’t reshuffle between loads. The tiebreaker is our suggestion.

Density has an accessibility limit. Carbon offers five row heights, from 24 to 64 px, and recommends the tallest only for two-line content. WCAG 2.2 sets a minimum pointer target of 24 by 24 CSS pixels, with a spacing exception. Tiny row buttons in a compact table can fail it. Whether density belongs to the person or to the view is a call to make explicitly; we lean toward the person.

Freezing needs a test. NN/g recommends freezing header rows and header columns when the table is larger than the screen. WCAG notes that sticky headers and footers can cover a focused element. Tab through the table with a frozen column and check that the focused cell stays visible.

What is a saved view, and who owns it?

Three products answer the ownership question differently.

Linear gives every view an owner and reflects temporary filters in the URL: a copied link applies them, but sharing a link doesn’t grant access to a view.

From these, our suggestion is a model with three layers:

  1. The saved definition. It has a name, an owner and a visibility level. It stores filters, sort and columns.
  2. Personal changes on top. The view shows a “modified” marker with three actions: Save, Save as new view and Reset. Nothing reaches other people until the owner saves.
  3. The URL. It carries filters, sort, search and view ID, so a pasted link reproduces what you see, if the recipient has access.

Under that model the admin’s region filter is a deliberate save by the view’s owner, and the manager keeps a personal view that nobody else can edit.

Name views by purpose (“Overdue over $5,000, my team”), not by person, and choose the default view on purpose.

How should rows load: pages, load more or infinite scroll?

NN/g says infinite scrolling suits long lists of similar items but is less suited to finding a particular item. A Load More button restores access to the page footer and signals that more content exists, at the price of an extra click. Polaris says to paginate when a list holds more than 50 items.

For a work table that people leave and return to, pages are the safer default (our suggestion): “Showing 1-50 of 1,284,” a page-size control and the page in the URL, so Back returns to the same place.

Two limits matter at scale. Airtable loads views with more than 1,000 records as a preview with a “Load all records” action. And a table’s page is not its dataset: Stripe’s export includes all transactions matching your current filters, not just the visible page. Label export buttons with the count they will export.

What should a row click, a row action and an inline edit do?

Polaris says index table items should perform an action when clicked, usually opening the details page. NN/g notes that inline single-record actions work for one or two actions, and beyond that end up crowded or hidden behind hover or a generic menu. A default that follows: row click opens the record, one or two visible actions at most, the rest in a labeled menu.

Hover-only controls cost keyboard users. In a plain table, each widget is a separate tab stop, so 50 rows with three buttons each means 150 stops. The APG grid pattern shortens that with arrow-key navigation, but it requires focus-management code, and arrow keys then move between cells. Use it when the table is truly interactive or editable, and otherwise prefer a native HTML table.

For editing, NN/g says edit in place works only if the table is narrow, and the row should look different in edit mode. A modal hides neighboring records that people use as reference. A nonmodal side panel keeps both. Bulk actions, with their selection scope across pages and filters, are a separate problem; our guide to enterprise bulk action UX covers it.

What should loading, partial and stale states show?

Nielsen’s response-time limits give a rough scale: under 0.1 seconds needs no feedback, past 1 second show that the system is busy, and past about 10 seconds use a percent-done indicator with a way to cancel. Carbon recommends skeleton states instead of spinners when extra load time is expected. Our suggestions: keep the filter bar and headers usable while rows load, say plainly when the table shows a part of the data (“First 1,000 of 4,212 rows”), and show when data was last refreshed. Nielsen’s first heuristic is to keep users informed about what is going on, so a table that looks current but isn’t should say so.

The table specification worksheet

Fill one per table. The defaults are our suggestions, not standards, and the last column is a check a team or an agency can run.

Table specification worksheet
DecisionOptionsReasonable defaultAcceptance check
Lead taskFind, compare, edit one, actOne lead task per table, written in one sentenceThree team members state the same task
First columnGenerated ID, readable nameReadable identifierA new user finds a known record by scanning
Filter applyInstant, batchInstant when fast; batch for slow queries or many categoriesTime from change to result, measured
Filter logicAND, OR, nestedAND across fields, OR within a field, nested behind AdvancedReading the chips aloud gives the right query
Zero resultsBlank, messageNames active filters; remove-last and clear-allApply filters that match nothing
View visibilityPrivate, team, everyone, lockedPrivate by default; owner controls sharingA teammate cannot silently change your view
What a view storesFilters, sort, columns, density, pageFilters, sort, columns; density and page stay personalOpen one view in two accounts
Unsaved changesAuto-save, marker plus actionsMarker with Save, Save as new, ResetChange a filter, reload, check
URL stateNone, filters, filters plus viewFilters, sort, search, view ID; link is not accessOpen a link with and without access
PagingPages, load more, infinitePages with count and page sizeOpen a record, press Back, same place
Row clickOpen, select, nothingOpen record; 1-2 visible actions; rest in menuKeyboard-only run through a full page
EditingIn place, side panel, modalSide panel; in place only for narrow tablesCompare against a neighboring row while editing
ExportVisible, matching, allMatching rows; button shows the countFile row count equals header count
Load, partial, staleSpinner, skeleton, noticeSkeleton, partial notice, last-updated timeThrottle the network and read each state

Illustrative worked example: back to the invoices table

This continuation is invented. The billing team writes the worksheet for the invoices table and changes five things.

Illustrative before-and-after for the invoices table
AreaBeforeAfter
Shared “Overdue” viewAnyone can edit it; changes appear for everyoneOwned by the collections lead; others get a modified marker and Save as new
Manager’s Monday listRebuilt by hand each weekPersonal view “Overdue over $5,000, my team,” opened by default
FiltersEight dropdowns, state lost on reloadThree promoted filters, chips with counts, state in the URL
No matchesBlank table“No invoices match Region: West and Over $5,000.” with remove and clear actions
ExportThe 50 visible rowsAll matching rows, button reads “Export 212 invoices” (invented count)

Open questions remain: whether a locked view is worth building yet, and what density people choose. A short session with a few collections staff, using their own Monday view, would answer both.

Where do these defaults stop working?

The sources are design-system documentation, accessibility standards and product help pages. They show how well-known products behave, not how your users behave, and the products differ: Airtable’s personal and locked views need a paid plan, and HubSpot’s sharing is account-based. This guide does not cover mobile layouts for wide tables, which NN/g treats separately, real-time collaborative editing, or the engineering of very large datasets.

What can you produce now?

Four things, before anyone draws a screen:

  1. A worksheet per table with the lead task and a default for every row.
  2. A view model: the saved definition, personal changes and the URL, with ownership and sharing rules.
  3. A state list: default, filtered, zero results, loading, partial, stale and error, each with its copy.
  4. Acceptance checks you can run in a working session, including keyboard-only and network-throttled runs.

If you plan to bring in outside designers for the table, ask each team to fill the worksheet for one of your real tables and to explain the view model. Our comparison of UX/UI agencies that design complex B2B SaaS platforms shows which studios publish work on screens like these.

Let's talk

Have questions? Ask AI
Opens a new chat with context about us pre-loaded — ask anything

We’ll reply within 24 hours with case studies, a timeline, and an estimate.

Prefer email? Write to hi@humbleteam.com
All set – our team’s on it. Expect a reply soon.
Send another one
Oops! Something went wrong while submitting the form.
Have questions? Ask AI
Opens a new chat with context about us pre-loaded — ask anything
Europe
Národní 135/14, Prague
Middle East
UAE, Dubai, Internet City Offices
We use cookies to enhance your browsing experience,
serve personalised ads or content, and analyse our traffic.
By clicking "Accept All", you consent to our use of cookies.
Privacy policy