Build a SaaS UI design system around hierarchy, density, and empty states so dashboards stay scannable, shippable, and honest after real data arrives. I design and build these systems in the same engagement, because hierarchy decisions that look fine in Figma fail the moment a table has 400 rows.
Short answer
A SaaS UI design system is not a museum of components. It is a hierarchy contract: what users see first, how dense data can get, and what empty, loading, and error look like before the happy path. Ship primitives plus states for the one core workflow. Polish the illustration library later.
Hierarchy beats component count
Every product view should answer three questions in under three seconds:
- Where am I?
- What is the most important object or metric?
- What is the next safe action?
If your page needs a legend to explain its own chrome, hierarchy failed. One primary action, secondary actions visually quieter, destructive actions deliberate. Marketing landings and product apps share this rule, even when density differs.
Density is a product decision
Founders often ask for “Apple-like whitespace” in an ops tool that lives in tables. Comfortable consumer spacing in a B2B control panel creates endless scroll and hides relationships between columns.
Set density with tokens: control height, row padding, type size for data, and gap in toolbars. A good default for admin SaaS is slightly compact with room for focus rings. If you need a compact mode, change tokens, do not fork every component.
Touch targets on hybrid laptop/tablet use still need hit area even when visuals are tight. Density without accessibility is just cramped.
Empty, loading, and error are the system
Happy-path mock data lies. Design the trio as first-class patterns:
- Empty: short explanation, one CTA, optional secondary learn link
- Loading: skeletons that match final layout to avoid CLS
- Error: human cause + retry or support path, not only a red toast
Reuse the same empty-state primitive across lists, boards, and search results so the product feels intentional on day one.
Primitives that pay rent in week one
- Button (primary, secondary, ghost, destructive) with loading
- Field stack: label, hint, error, input/select/textarea
- Badge and status pill used sparingly
- Table/list row with selection, actions menu, and responsive stacked variant
- App shell: sidebar/top nav, page header, content width rules
- Toast/inline alert with clear severity
Skip building twelve card elevations. Cards are for interaction containers; many SaaS screens work better as structured pages with dividers and spacing rhythm.
Navigation and information architecture
IA mistakes masquerade as UI bugs. Group by user jobs, not by your org chart. Keep settings out of the primary job path. Use page headers with title + primary action consistently so users build muscle memory.
Multi-tenant products need org context always visible. Silent tenant switching is how support tickets are born.
Motion in product UI (different budget than marketing)
Framer Motion in SaaS should confirm state changes, not stage a film. Short fades for panels, layout animations only when they clarify relationship, and hard respect for reduced motion. Product FPS on data-heavy pages is a retention issue; treat it that way.
MVP system vs later system
MVP: tokens, shell, primitives, states for one workflow, basic table, settings. Later: advanced filters, saved views, keyboard command palette, theming marketplace, dense customization. The second list is valuable after people live in the product daily.
This studio often ships engineer-led product UI with a tight token set when speed matters, then hardens the system as usage reveals real density needs. Vite SPA admin tools and Next.js App Router SaaS both work when the hierarchy contract is clear.
Tables, filters, and the scan path
Most B2B value lives in lists. Design the row before the dashboard chart:
- Primary identifier leftmost and sticky in mental model even if not sticky in CSS yet
- Status as a quiet badge, not a rainbow
- Row actions behind a single menu unless one action is truly primary
- Filters as a progressive disclosure; do not dump twelve controls above an empty table
- Bulk actions appear only after selection to protect hierarchy
On mobile, stack key fields and keep the primary row action reachable with a thumb. Horizontal scroll can work for power tables; say so in the handoff instead of pretending a 9-column grid will “just wrap.”
Forms and settings without form fatigue
Group fields by decisions the user is making, not by database columns. Inline hints beat tooltip archaeology. Destructive settings need confirmations with consequences named in plain language. For multi-tenant SaaS, show which org the setting applies to on every sensitive page.
Validation copy is part of the system: one error tone, one placement rule, one disabled-submit behavior. Inconsistent forms feel like multiple products bolted together.
Theming and dark mode realism
If you ship dark mode, define semantic tokens first (surface, text, border, danger) and map both themes. Do not invert hexes blindly. Charts, maps, and uploaded brand assets need explicit treatment. Many MVPs should ship one excellent theme and schedule the second after hierarchy stabilizes.
Documentation that keeps the system alive
A Figma library without usage rules dies. Pair components with do/don’t examples: when to use ghost buttons, when badges become noise, when empty states are required. In code, Storybook or a lightweight gallery with real states beats screenshots in Notion. Review new one-off styles in the same ritual as dependency upgrades: if it is not a token or a primitive extension, it is debt.
Assign an owner. Systems without owners become suggestion folders.
Density decision matrix
| Product type | Default density | Primary pattern | Watch out |
|---|---|---|---|
| Ops / admin SaaS | Compact+ | Table + row actions | Consumer whitespace |
| Creator / consumer app | Comfortable | Cards sparingly | Over-dense toolbars |
| Analytics | Mixed | Chart + filter bar | Competing primaries |
| Marketplace back office | Compact | Queues + status | Unlabeled badges |
Pick a row before you open Figma. Changing density mid-build rewrites every page header and table.
Empty / loading / error measurement
Instrument the trio like product features:
- Empty → first success: time and percent of new orgs that complete the CTA on the empty state
- Loading abandonment: exits during skeleton longer than your p95 fetch
- Error recovery: retry click rate and support tickets tagged “something broke”
- Hierarchy probe: five-second first-click tests on the page header primary action
If empty-state CTA conversion is weak, rewrite copy and the next action before adding more dashboard widgets. Widgets do not fix a missing job story.
System debt checklist (monthly)
- Count one-off spacing values outside the token scale
- List pages missing empty or error states on primary lists
- Audit primary-action uniqueness per view (more than one = hierarchy bug)
- Check focus rings on new controls in both themes if you ship two
- Remove unused variants that exist only in Figma
- Confirm marketing tokens did not leak oversized radii into tables
Treat rising one-off counts like rising dependency count: schedule cleanup before the next feature epic.
How this maps to studio work
Shipped product UI on zaneone.one/portfolio favors scannable hierarchy, honest empty states, and motion that does not fight data. If you need a design-and-build pass on your SaaS shell, see services.
Related reading: Figma to React handoff, hiring for a SaaS MVP, and landing motion performance.
FAQ
What belongs in a SaaS UI design system for an MVP?
Start with tokens, typography, spacing, a small set of primitives (button, input, select, checkbox, badge, toast), table/list row patterns, empty/loading/error states, and one app shell (nav + content). Delay elaborate illustration libraries and twenty modal sizes until usage proves need.
How dense should a B2B SaaS dashboard be?
Dense enough that power users can scan without endless scrolling, loose enough that labels, focus rings, and touch targets remain usable. Offer a comfortable default and, if needed, a compact density token later. Never confuse density with clutter: one primary action per view still applies.
Why do empty states matter so much in SaaS UI?
Empty is the first real screen for new orgs. A good empty state explains the job, offers one next action, and sets hierarchy for the filled state. A blank table teaches users that your product is unfinished.
Should SaaS marketing and product UI share one system?
Share brand tokens and type families where possible, but keep product density and marketing hero composition as separate templates. Marketing wants presence; product wants scan speed. Forcing both into identical card chrome usually harms both.
Next step
Pick one core screen, redesign its hierarchy and empty/loading/error trio, and extract tokens from what you actually reused. Expand components only after those patterns stabilize. For a fixed-scope system plus build, use contact.
Want this built for your product? Start a project with Zane, or explore shipped work, services, and more guides.