← Back

Case Study · Design System · 2025

Vault
Design System

A production-grade design language built for Vault- a fictional fintech SaaS dashboard product. It covers the full spectrum: primitive & semantic token architecture, a 58-component Figma library, WCAG 2.1 AA accessibility, motion principles, and a living documentation layer - built entirely in Figma with W3C Design Token tooling.

FigmaDesign TokensComponent LibraryWCAG 2.1 AATypographyMotion DesignFigma VariablesAuto Layout
VAULT
Design System v1.0

A single source of truth for colour, type, spacing, and interaction - built in Figma, consumed by engineers.

240+ tokens58 componentsWCAG 2.1 AA
Dashboard
Portfolio
Transactions
Reports
Settings
Dashboard
Portfolio Value
$248,391
+12.4%
MTD Return
$9,204
+3.9%
Pending
7
3 need review
Alerts
2
Action required
Portfolio Performance
Recent Transactions
Stripe Inc.+$1,200
AWS Services-$340
Figma SaaS-$45
240+
Design Tokens
58
Components
14
Screen Templates
AA
WCAG 2.1

01 - The Brief

Why a design system?

Vault is a fictional B2B fintech platform for portfolio analytics, transactions, and compliance reporting. The brief was to design a system that a team of 8 engineers and 3 designers could ship from confidently - with zero ambiguity on color, spacing, motion, or component behaviour.

The system needed to be dark-first (dashboard context), fully accessible at AA minimum, and documented well enough that a new hire could be productive on day one. No Storybook - the entire source of truth lives in Figma using Variables and Auto Layout 4.

"A design system is not a component library. It is a shared language. The components are sentences. The tokens are the words."

02 - Process & Decisions

How the key decisions were made

Step 01
Audit before building

Before a single token was defined, I catalogued every colour, spacing value, and component pattern that a fintech dashboard needs. This produced a list of 60+ raw values that were then grouped into candidates for the token system. Skipping this step is the most common reason design systems get abandoned - you end up with tokens that don't map to real product decisions.

DecisionAudit first, token later - every token must trace back to a real product usage, not a hypothetical.
Step 02
Primitive → semantic split

The hardest architectural question was where to draw the line between primitive and semantic tokens. I settled on a strict rule: primitives are pure values (no usage meaning), semantics carry intent and reference primitives. Engineers consume semantics only. This means a rebrand or dark/light switch never touches component code.

DecisionEngineers import color.brand, never color.indigo.500 - the primitive layer is internal scaffolding.
Step 03
Dark-first, not dark-only

Vault is a dashboard product - users spend hours in it. Dark-first reduces eye strain and makes data visualisations pop. But dark-first doesn't mean dark-only: semantic tokens are structured so a light theme can be applied by swapping token values without touching a single component.

DecisionAll colour decisions validated on dark surfaces first; light mode is a future token swap, not a redesign.
Step 04
Accessibility as a constraint, not a checklist

Every colour pair was contrast-checked at the primitive layer before being promoted to a semantic token. If a pair failed AA it was adjusted at the source - not compensated for in usage. Focus states are a 2px ring baked into the component API: there is no prop to suppress them.

DecisionContrast is a token-layer guarantee, not a component-layer option. No escape hatch exists.

Token Export (W3C Format)

vault-tokens.jsonW3C Design Tokens
{
  "color": {
    "primitive": {
      "indigo": {
        "400": { "$value": "#818CF8", "$type": "color" },
        "500": { "$value": "#6366F1", "$type": "color" },
        "600": { "$value": "#4F46E5", "$type": "color" }
      },
      "slate": {
        "950": { "$value": "#0A0E1A", "$type": "color" },
        "900": { "$value": "#111827", "$type": "color" }
      }
    },
    "semantic": {
      "bg":          { "$value": "{color.primitive.slate.950}", "$type": "color" },
      "surface":     { "$value": "{color.primitive.slate.900}", "$type": "color" },
      "brand":       { "$value": "{color.primitive.indigo.500}", "$type": "color" },
      "brand-hover": { "$value": "{color.primitive.indigo.400}", "$type": "color" },
      "success":     { "$value": "#10B981", "$type": "color" },
      "warning":     { "$value": "#F59E0B", "$type": "color" },
      "danger":      { "$value": "#F43F5E", "$type": "color" }
    }
  },
  "space": {
    "1": { "$value": "4px",  "$type": "dimension" },
    "2": { "$value": "8px",  "$type": "dimension" },
    "4": { "$value": "16px", "$type": "dimension" },
    "6": { "$value": "32px", "$type": "dimension" }
  },
  "motion": {
    "duration": {
      "base":     { "$value": "200ms", "$type": "duration" },
      "moderate": { "$value": "300ms", "$type": "duration" }
    },
    "ease": {
      "standard": { "$value": "cubic-bezier(0.4, 0, 0.2, 1)", "$type": "cubicBezier" }
    }
  }
}

03 - Brand Identity

Personality & visual language

Secure

Every visual decision communicates trust. Dark surfaces, precise geometry, no decoration without function.

Precise

8pt grid. No arbitrary values. Spacing, radius, and type are mathematically derived - not approximated.

Modern

Indigo-forward palette that reads as technical and forward-looking without being cold or clinical.

Accessible

WCAG 2.1 AA as a floor, not a ceiling. Most pairings achieve AAA. Focus states are never suppressed.

Vault logo - dark variantDark
Vault logo - light variantLight
Vault logo - mono variantMono

04 - Color System

Two-tier token architecture

Vault uses a primitive → semantic token model. Primitive tokens are raw values (hex, rem, ms). Semantic tokens reference primitives and carry intent - they are what engineers and designers consume. This decouples the palette from usage, making theming and dark/light switching trivial.

Primitive Palette

#818CF8
Indigo 400
color.indigo.400
#6366F1
Indigo 500
color.indigo.500
#4F46E5
Indigo 600
color.indigo.600
#10B981
Emerald 500
color.emerald.500
#F59E0B
Amber 500
color.amber.500
#F43F5E
Rose 500
color.rose.500
#0A0E1A
Slate 950
color.slate.950
#111827
Slate 900
color.slate.900
#1C2333
Slate 800
color.slate.800
#1F2937
Slate 700
color.slate.700
#9CA3AF
Slate 300
color.slate.300
#FFFFFF
White
color.white

Semantic Mapping

color.bg
App canvas
#0A0E1A
color.surface
Cards, panels
#111827
color.surface-raised
Dropdowns, modals
#1C2333
color.border
Dividers, inputs
#1F2937
color.brand
Primary actions
#6366F1
color.brand-hover
Interactive state
#818CF8
color.text-primary
Body, headings
#F9FAFB
color.text-secondary
Labels, captions
#9CA3AF
color.success
Confirmations
#10B981
color.warning
Alerts, caution
#F59E0B
color.danger
Errors, delete
#F43F5E

05 - Typography

Type system

Plus Jakarta Sans for display and headings (geometric, trustworthy). Inter for body and UI (maximum legibility at small sizes). JetBrains Mono for data, codes, and IDs. All sizes follow a modular scale built on a 1.25 ratio base.

Plus Jakarta Sans Display / Headings
Inter Body / UI
JetBrains Mono Data / Code
Displaytype.display3rem / 800 / lh 1
Vault Fintech
H1type.h12rem / 700 / lh 1.1
Dashboard Overview
H2type.h21.5rem / 700 / lh 1.15
Portfolio Performance
H3type.h31.125rem / 600 / lh 1.2
Account Summary
Body LGtype.body-lg1rem / 400 / lh 1.75
Your balance has increased by 12.4% this quarter.
Body SMtype.body-sm0.875rem / 400 / lh 1.65
Last updated 2 minutes ago.
Labeltype.label0.75rem / 600 / lh 1.4
TRANSACTION TYPE
Codetype.code0.8rem / 400 / lh 1.6
VAULT-TX-00291847

06 - Spacing & Grid

8pt base grid

All spacing tokens are multiples of 4px (half the base unit), enabling both micro (4px, 8px) and macro (32px, 64px) control from a single consistent scale. The layout grid is 12-column with 24px gutters and a max-width of 1280px.

space.1
4px / 0.25rem
space.2
8px / 0.5rem
space.3
12px / 0.75rem
space.4
16px / 1rem
space.5
24px / 1.5rem
space.6
32px / 2rem
space.8
48px / 3rem
space.10
64px / 4rem
space.12
80px / 5rem

Border Radius Scale

sm
4px
md
8px
lg
12px
xl
16px
2xl
24px
full

07 - Component Library

58 production components

Every component is built with Auto Layout 4, Figma Variables, and documented with props, variants, and usage rules. Below is a live rendering of key components from the library - built purely in HTML/CSS to demonstrate the token system in action.

Button

Badge

ProActivePendingOverdueDraftArchived

Input

Account Label
e.g. Main Trading Account
Amount
$
0.00
Status
Invalid IBAN format
Must be a valid IBAN.

Card

Total Portfolio Value
$248,391.40
↑ 12.4% this month
Pending Transactions
7
3 require approval
Stripe Inc.
14 Jun 2025
+$1,200.00
AWS Services
12 Jun 2025
-$340.00
Figma SaaS
10 Jun 2025
-$45.00

Alert

Two-factor authentication enabled
Your account is protected. Review recovery codes in Security settings.
Payment method expiring
Your card ending in 4242 expires in 14 days. Update it to avoid interruption.
Transaction failed
VAULT-TX-00291847 was declined. Insufficient funds or invalid payment details.

Full library also includes: Avatar · Checkbox · Radio · Toggle · Select · Combobox · DatePicker · Tooltip · Popover · Modal · Drawer · Toast · ProgressBar · Stepper · Pagination · Table · Tabs · Accordion · Breadcrumb · Skeleton · Spinner · Tag Input · Search · EmptyState · DataCard · KPITile · and more.

08 - Component Anatomy

Every property is a token

No hardcoded values exist inside components. Each visual property - colour, radius, spacing, shadow, duration - references a token. The diagram below traces the primary button back to its source tokens, showing the full semantic chain.

Default

Resting state. Background uses color.brand.

Hover

Background shifts to color.brand-hover via 200ms ease.

Focus

2px ring using color.brand-hover · 2px offset. Never suppressed.

Property → token mapping
01backgroundcolor.brand#6366F1
02background:hovercolor.brand-hover#818CF8
03colorcolor.text-on-brand#FFFFFF
04border-radiusradius.md8px
05paddingspace.3 / space.512px / 24px
06font-sizetype.label.size0.75rem
07font-weighttype.label.weight600
08letter-spacingtype.label.tracking0.1em
09transitionmotion.duration.base200ms ease
10focus ringcolor.brand-hover2px offset
Token resolution chain
Component
Button.background
↓ references
Semantic
color.brand
↓ references
Primitive
color.indigo.500
↓ resolves to
Raw value
#6366F1
To rebrand Vault, only the primitive layer changes. Zero component code is touched.

09 - Screen Templates

The system applied

14 screen templates demonstrate the design system in a real product context. Every element on every screen traces back to a token - no hardcoded values. Three key screens are shown below, built entirely from the component library.

Screen 01 - Dashboard Overview

JR
Juanre R.
Admin
Dashboard
Home / Overview
Live
Total Portfolio
$248,391
+12.4% this month
MTD Return
$9,204
+3.9% vs last month
Open Positions
34
Across 6 markets
Pending Actions
7
3 require approval
Portfolio Performance 6M
$260k$230k$200k
JanFebMarAprMayJun
Allocation
Equities52%
Bonds24%
Cash14%
Alt.10%

Screen 02 - Transaction History

Transactions
Home / Transactions
Search transactions…
Transaction IDCounterpartyDateTypeAmountStatus
VAULT-TX-00291847Stripe Inc.14 Jun 2025Credit+$1,200.00Settled
VAULT-TX-00291846AWS Services12 Jun 2025Debit-$340.00Settled
VAULT-TX-00291845Figma SaaS10 Jun 2025Debit-$45.00Pending
VAULT-TX-00291844Acme Corp Ltd.08 Jun 2025Credit+$8,400.00Settled
VAULT-TX-00291843PayPal Payout07 Jun 2025Debit-$230.00Failed
Showing 1-5 of 1,284 transactions

Screen 03 - Account Settings

Account Settings
Home / Settings
Profile
Security
Notifications
Billing
API Keys
First Name
Juanre
Last Name
Retief
Email Address
juanre@vault.io
Role
Portfolio Administrator
Two-factor authentication is enabled
Your account is protected with an authenticator app.
JR
Juanre Retief
Admin · Pretoria, ZA
Danger Zone

Permanently delete your account and all associated data. This action cannot be undone.

🖥

Best viewed on desktop. The three screen templates - Dashboard Overview, Transaction History, and Account Settings - are detailed product UI mockups that require a wider viewport to display correctly.

10 - Accessibility

WCAG 2.1 AA - by design

Contrast ratios are baked into the token layer, not checked after the fact. Every semantic color pair was validated at definition time. Focus states use a 2px offset ring in brand color - never suppressed. All interactive components are keyboard-navigable and ARIA-annotated in the Figma component notes.

Aa
Brand on Surface
7.2:1
#818CF8 on #111827
AAA
Aa
Text on Background
18.8:1
#F9FAFB on #0A0E1A
AAA
Aa
Secondary on Surface
4.8:1
#9CA3AF on #111827
AA
Aa
Success on Surface
5.1:1
#10B981 on #111827
AA
Aa
Warning on Surface
7.6:1
#F59E0B on #111827
AAA
Aa
Danger on Surface
4.6:1
#F43F5E on #111827
AA

Focus State Standard

Focused input
2px solid #818CF8 · 2px offset · never suppressed

11 - Motion Principles

Purposeful, not decorative

Motion in Vault communicates hierarchy and state - it is never used for its own sake. All durations and easing curves are tokenised. Reduced Motion preferences are always respected via prefers-reduced-motion.

motion.duration.fast
100ms
Micro-interactions, hover state entry
motion.duration.base
200ms
Buttons, toggles, badges
motion.duration.moderate
300ms
Panels, dropdowns, tooltips
motion.duration.slow
500ms
Page transitions, modals
motion.ease.standard
cubic-bezier(0.4, 0, 0.2, 1)
Default UI motion
motion.ease.enter
cubic-bezier(0, 0, 0.2, 1)
Elements entering
motion.ease.exit
cubic-bezier(0.4, 0, 1, 1)
Elements leaving
motion.ease.spring
cubic-bezier(0.34, 1.56, 0.64, 1)
Emphasis, delight

Live Transition Demo

100ms · fast
200ms · base
300ms · moderate
500ms · spring

12 - Documentation

The system documents itself

Every Figma component has a Usage, Don't, and Props section built into the frame using a standardised documentation template. Tokens are exported as a W3C-compatible JSON file for engineering handoff. The Figma file is the single source of truth.

Token Export

W3C Design Token format. One JSON file, auto-imported into the engineering repo via a build step.

Component Docs

Each component frame includes: purpose, props, do/don't, and keyboard nav. No external doc site needed.

Handoff Spec

Dev Mode annotations cover spacing, colour tokens, radius, and state logic. Zero guessing for engineers.

A11y Annotations

Separate accessibility layer on every component: ARIA role, focus order, keyboard shortcuts.

Change Log

Version-controlled Figma branches with semantic versioning. Breaking changes flagged in the component notes.

Usage Examples

Each component ships with real-world screen examples from the Vault product showing it in context.

13 - Outcomes

What this system demonstrates

01
Systems thinking at scale

Token architecture that separates primitive values from semantic intent - enabling theming, rebranding, and dark/light mode without component rewrites.

02
Accessibility as infrastructure

Contrast, focus, and keyboard nav baked into the token layer and component API - not added as an afterthought. All pairs verified at AA minimum.

03
Component API design

Each component is designed with the engineer's mental model in mind: predictable props, documented variants, explicit state logic, and zero magic.

04
Documentation discipline

A system no one can use is not a system. The documentation layer - built inside Figma - ensures every decision is legible to designers, engineers, and stakeholders.

Vault is a fictional system - but every decision reflects real production constraints. The token architecture, component API thinking, accessibility standards, and documentation approach are all drawn from building design systems that ship.

← All Projects