Design System Documentation
Design System Documentation
Project: Drop — Fintech Payment App
Version: 0.1.0
Date: 2026-02-23
Author: John (AI Director, ALAI)
Status: In Review
Reviewers: Alem Bašić (CEO)
Document History
| Version |
Date |
Author |
Changes |
| 0.1 |
2026-02-23 |
John |
Initial draft from source code + brand guide analysis |
1. Design Principles
| Principle |
Description |
| Clarity first |
Every UI element must communicate its purpose without explanation. Amounts are large and legible. Actions are labeled. |
| Scandinavian minimal |
Generous whitespace, no visual noise. Forest green + white — nothing extra. |
| Trust through transparency |
Fees visible before every transaction. No hidden costs. PSD2 disclosures shown explicitly. |
| Mobile-first |
The app is a mobile PWA. max-w-sm containers, pb-24 for BottomNav clearance, touch targets ≥ 44×44px. |
| Accessible by default |
WCAG AA compliance is a baseline requirement, not an optional enhancement. |
| Light mode only (Phase 1) |
Background is always off-white (#FAFCF8) or white. Dark mode is Phase 2. |
2. Color System
2.1 Primitive Palette (Raw Values)
/* Brand primitives — defined in brand/colors.css and globals.css */
/* Green scale */
--color-green-primary: #0B6E35; /* Forest Green — primary brand */
--color-green-dark: #095C2C; /* Hover/pressed state */
--color-green-light: #E8F5E9; /* Light green tint, badges */
/* Gold scale */
--color-gold-primary: #D4A017; /* Gold accent, logo arrow, premium elements */
--color-gold-light: #FFF8E1; /* Gold tint */
/* Neutral scale */
--color-neutral-0: #FFFFFF; /* White — cards, elevated surfaces */
--color-neutral-50: #FAFCF8; /* Off-white — page background */
--color-neutral-100: #F9FAFB; /* Input field backgrounds */
--color-neutral-200: #F3F4F6; /* Section backgrounds, shadcn secondary */
--color-neutral-300: #E5E7EB; /* Input borders, card borders, dividers */
--color-neutral-400: #D1D5DB; /* Horizontal rule dividers */
--color-neutral-500: #9CA3AF; /* Muted text, inactive nav items */
--color-neutral-600: #6B7280; /* Secondary text, placeholders */
--color-neutral-700: #374151; /* Dark text on light backgrounds */
--color-neutral-900: #1A1A1A; /* Near-black — headings, primary text */
--color-neutral-1000: #000000;
/* Semantic */
--color-success: #10B981; /* Emerald — success, positive amounts */
--color-error: #EF4444; /* Red — error states, negative amounts */
--color-warning: #D97706; /* Warning — pending transactions */
--color-info: #2563EB; /* Info — PSD2 banners */
2.2 Semantic Tokens (Light Mode — from globals.css :root)
:root {
/* shadcn/ui CSS variable tokens */
--background: #FAFCF8;
--foreground: #1A1A1A;
--primary: #0B6E35;
--primary-foreground: #FFFFFF;
--secondary: #F3F4F6;
--secondary-foreground: #1A1A1A;
--accent: #F3F4F6;
--accent-foreground: #1A1A1A;
--muted: #F3F4F6;
--muted-foreground: #6B7280;
--destructive: #EF4444;
--border: #E5E7EB;
--input: #E5E7EB;
--ring: #0B6E35;
--radius: 0.75rem;
/* Drop custom semantic tokens */
--color-drop-primary: #0B6E35;
--color-drop-secondary: #D4A017;
--color-drop-accent: #10B981;
--color-drop-dark: #1A1A1A;
--color-drop-light: #FAFCF8;
--color-drop-error: #EF4444;
}
2.3 Semantic Tokens (Dark Mode)
/* Phase 2 — Dark mode TBD */
[data-theme="dark"] {
/* TBD — requires design review */
/* Drop is light-mode-first. Dark mode planned for Phase 2. */
}
2.4 Brand Gradient
.bg-gradient-brand {
background: linear-gradient(135deg, #0B6E35 0%, #D4A017 100%);
}
2.5 Contrast Ratios (WCAG)
| Pair |
Text Color |
Background |
Ratio |
WCAG AA (4.5:1) |
WCAG AAA (7:1) |
| Primary text on page bg |
#1A1A1A |
#FAFCF8 |
~18.6:1 |
Pass |
Pass |
| Secondary text on page bg |
#6B7280 |
#FAFCF8 |
~4.7:1 |
Pass |
Fail |
| Primary button text |
#FFFFFF |
#0B6E35 |
~5.0:1 |
Pass |
Fail |
| Success text |
#10B981 |
#FFFFFF |
~3.0:1 |
Fail (large text only) |
Fail |
| Error text |
#EF4444 |
#FFFFFF |
~3.9:1 |
Fail (large text only) |
Fail |
| Muted text |
#9CA3AF |
#FFFFFF |
~2.9:1 |
Fail |
Fail |
Action items: Success (#10B981), error (#EF4444), and muted (#9CA3AF) colors fail WCAG AA for small text. These are used for semantic indicators (amount colors, hints) — always paired with a non-color indicator. Full audit in accessibility-audit.md.
3. Typography
3.1 Font Families
| Token |
Value |
Usage |
--font-fraunces |
Fraunces, Georgia, "Times New Roman", serif |
Display/headings, logo wordmark, brand text |
--font-dm-sans |
"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif |
Body text, UI labels, inputs (default body font) |
--font-geist-mono |
"Geist Mono", "JetBrains Mono", "Fira Code", "Courier New", monospace |
Code, monospace elements |
Why these fonts:
- Fraunces — Variable serif with "wonky" optical size. Gives character and warmth. Differentiates Drop from every other fintech app (which all use sans-serif). Signals: "we are different, we are human."
- DM Sans — Clean geometric sans-serif. Readable at all screen sizes. Friendly without being playful. Good number legibility (critical for fintech).
3.2 Type Scale
| Token |
Size |
Weight |
Line Height |
Letter Spacing |
Usage |
| Display |
56px |
700 (Fraunces) |
1.1 |
-0.02em |
Hero headlines (landing page) |
| H1 |
40px |
600 (Fraunces) |
1.2 |
-0.01em |
Page titles |
| H2 |
32px |
600 (Fraunces) |
1.3 |
-0.005em |
Section headers |
| H3 |
24px |
500 (Fraunces) |
1.3 |
normal |
Sub-sections |
| H4 |
20px |
600 (DM Sans) |
1.4 |
normal |
Card titles |
| Body Large |
18px |
400 (DM Sans) |
1.7 |
normal |
Lead paragraphs |
| Body |
16px |
400 (DM Sans) |
1.6 |
normal |
Default text |
| Body Small |
14px |
400 (DM Sans) |
1.5 |
normal |
Secondary content, captions |
| Label |
14px |
500 (DM Sans) |
1.4 |
0.01em |
Form labels, UI labels |
| Caption |
12px |
500 (DM Sans) |
1.4 |
0.02em |
Timestamps, meta, hints |
3.3 In-App Tailwind Typography Patterns
| Context |
Tailwind Class |
Example |
| Logo wordmark |
font-[family-name:var(--font-fraunces)] text-3xl font-bold |
"drop" on login |
| Page heading |
text-xl font-semibold text-[#1A1A1A] |
Dashboard greeting |
| Section heading |
text-lg font-semibold text-[#1A1A1A] |
"Siste transaksjoner" |
| Form label |
text-sm font-medium text-[#1A1A1A] |
"E-post" |
| Body text |
Inherited DM Sans |
General content |
| Muted text |
text-sm text-[#6B7280] |
Descriptions, timestamps |
| Small text |
text-xs text-[#9CA3AF] |
Footers, hints |
| Balance (large) |
text-2xl font-bold text-[#1A1A1A] |
Balance display |
| Amount (list) |
text-sm font-semibold + color |
Transaction amounts |
4. Spacing & Layout
4.1 Spacing Scale (4px Base Unit — Tailwind defaults)
| Tailwind |
Value |
Usage |
p-1 |
4px |
Micro gaps |
p-2 |
8px |
Tight inline spacing |
p-3 |
12px |
Compact elements |
p-4 |
16px |
Default content spacing |
p-6 |
24px |
Card padding, section padding |
p-8 |
32px |
Large section gaps |
px-6 |
24px |
Page horizontal padding (standard) |
pb-24 |
96px |
Bottom padding (BottomNav clearance) |
4.2 Page Structure Patterns
/* Standard authenticated page */
min-h-screen bg-[#FAFCF8] /* Off-white background */
px-6 pb-24 pt-6 /* Padding: horizontal 24px, bottom 96px (nav), top 24px */
/* Login / onboarding (centered) */
min-h-screen bg-[#EEEEEE] /* Slightly darker bg for auth pages */
max-w-sm mx-auto /* 384px max width, centered */
/* Card pattern (standard) */
rounded-2xl bg-white p-6 shadow-sm
/* Card pattern (compact) */
rounded-xl bg-white p-4 shadow-sm
4.3 Responsive Breakpoints (Tailwind defaults)
| Name |
Min Width |
Usage |
| Default |
0px |
Mobile — primary design target |
sm |
640px |
Larger phones |
md |
768px |
Tablets — landing page 2-column grid |
lg |
1024px |
Desktop — landing page 3-column grid |
Note: The app is mobile-first. max-w-sm containers keep content readable on wider screens.
4.4 Bottom Nav
The BottomNav is fixed bottom-0 left-0 right-0 with h-16 border-t bg-white. All pages that include BottomNav must add pb-24 to their content container.
5. Component Library
5.1 Custom Drop Components
| Component |
File |
Status |
Description |
| BottomNav |
components/bottom-nav.tsx |
Done |
Fixed 5-tab navigation |
| DropLogo |
components/drop-logo.tsx |
Done |
Forward-D SVG mark |
| DropWordmark |
components/drop-logo.tsx |
Done |
"drop" in Fraunces |
| DropLogoFull |
components/drop-logo.tsx |
Done |
Logo mark + wordmark |
| DropAppIcon |
components/drop-logo.tsx |
Done |
App icon — rounded green square |
| CookieConsent |
components/cookie-consent.tsx |
Done |
GDPR consent banner + modal |
| PrePaymentDisclosure |
components/pre-payment-disclosure.tsx |
Done |
PSD2 pre-payment modal |
| PWARegister |
components/pwa-register.tsx |
Done |
Service Worker registration |
| drop-icons |
components/drop-icons.tsx |
Done |
9 custom fintech icons |
5.2 shadcn/ui Primitive Components (Atoms)
| Component |
File |
Radix Primitive |
Status |
| Alert |
ui/alert.tsx |
— (div-based) |
Done |
| Avatar |
ui/avatar.tsx |
@radix-ui/react-avatar |
Done |
| Badge |
ui/badge.tsx |
— (cva variants) |
Done |
| Button |
ui/button.tsx |
@radix-ui/react-slot |
Done |
| Card |
ui/card.tsx |
— (div-based) |
Done |
| Dialog |
ui/dialog.tsx |
@radix-ui/react-dialog |
Done |
| Input |
ui/input.tsx |
— (input element) |
Done |
| ScrollArea |
ui/scroll-area.tsx |
@radix-ui/react-scroll-area |
Done |
| Select |
ui/select.tsx |
@radix-ui/react-select |
Done |
| Separator |
ui/separator.tsx |
@radix-ui/react-separator |
Done |
| Sheet |
ui/sheet.tsx |
@radix-ui/react-dialog |
Done |
| Skeleton |
ui/skeleton.tsx |
— (pulse animation) |
Done |
| Sonner |
ui/sonner.tsx |
sonner toast library |
Done |
| Tabs |
ui/tabs.tsx |
@radix-ui/react-tabs |
Done |
5.3 Layout Components
| Component |
Description |
| Page wrapper |
min-h-screen bg-[#FAFCF8] px-6 pb-24 pt-6 |
| Auth wrapper |
min-h-screen flex items-center justify-center bg-[#EEEEEE] |
| Card |
rounded-2xl bg-white p-6 shadow-sm |
| Scroll area |
ScrollArea from shadcn/ui for transaction lists |
6. Iconography Guidelines
| Item |
Standard |
| Primary library |
lucide-react |
| Delivery |
Inline SVG via React component |
| Sizes |
h-4 w-4 (inline/small), h-5 w-5 (nav/buttons), h-6 w-6 (feature icons) |
| Stroke width |
1.5px at 24px (Lucide default) |
| Color |
currentColor — inherits from parent text color |
| Custom icons |
components/drop-icons.tsx — 9 domain-specific icons |
| Social auth |
Inline SVG — BankID (green rounded rect, "ID"), Vipps (orange circle, "V") |
Custom Drop Icons:
| Export |
Description |
IconSendMoney |
Arrow going up-right from horizontal line |
IconQrScan |
QR code frame with scan corners |
IconVirtualCard |
Credit card outline |
IconShield |
Shield with checkmark |
IconFastTransfer |
Lightning bolt |
IconCorridors |
Globe with meridians |
IconWallet |
Wallet outline (unused — no wallet in pass-through model) |
IconHistory |
Clock with arrow |
IconTopUp |
Plus inside circle (unused — no top-up in pass-through model) |
Accessibility rule: Icons conveying meaning must have aria-label. Decorative icons: aria-hidden="true".
7. Motion & Animation Standards
7.1 Duration Tokens
7.2 Easing Tokens
| Token |
Value |
Usage |
--ease-default |
cubic-bezier(0.4, 0, 0.2, 1) |
General UI transitions |
--ease-enter |
cubic-bezier(0, 0, 0.2, 1) |
Elements entering |
--ease-exit |
cubic-bezier(0.4, 0, 1, 1) |
Elements leaving |
7.3 Reduced Motion
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Rule: Every animated component MUST respect prefers-reduced-motion.
8. Accessibility Requirements Per Component
9.1 CSS Custom Properties (Source of Truth)
/* src/app/globals.css */
:root {
--color-drop-primary: #0B6E35;
--color-drop-secondary: #D4A017;
--color-drop-accent: #10B981;
--color-drop-dark: #1A1A1A;
--color-drop-light: #FAFCF8;
--color-drop-error: #EF4444;
/* shadcn/ui tokens... */
}
9.2 Tailwind Config Extension
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
drop: {
primary: '#0B6E35',
secondary: '#D4A017',
accent: '#10B981',
dark: '#1A1A1A',
light: '#FAFCF8',
error: '#EF4444',
}
},
fontFamily: {
fraunces: ['var(--font-fraunces)', 'Georgia', 'serif'],
sans: ['var(--font-dm-sans)', 'system-ui', 'sans-serif'],
mono: ['var(--font-geist-mono)', 'monospace'],
}
}
}
}
9.3 JavaScript/TypeScript Constants (for charting/canvas)
// For use in non-CSS contexts (future charts, canvas)
export const dropColors = {
primary: '#0B6E35',
secondary: '#D4A017',
accent: '#10B981',
dark: '#1A1A1A',
light: '#FAFCF8',
error: '#EF4444',
} as const;
Token update process: Figma → update globals.css CSS variables → update Tailwind config → PR review.
10. Component Code Patterns
<Button className="h-12 w-full rounded-xl bg-[#0B6E35] text-sm font-semibold text-white shadow-sm hover:bg-[#095C2C]">
Send penger
</Button>
<button className="flex h-12 flex-1 items-center justify-center gap-2 rounded-xl border border-[#E5E7EB] bg-white text-sm font-medium text-[#1A1A1A] hover:bg-[#F9FAFB]">
Avbryt
</button>
Text Input with Left Icon
<div className="relative">
<Mail className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
<input
className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-3 text-sm outline-none focus:border-[#0B6E35] focus:ring-1 focus:ring-[#0B6E35]"
type="email"
placeholder="din@epost.no"
/>
</div>
Error Message
<p className="rounded-md bg-[#EF4444]/10 p-2 text-sm text-[#EF4444]">
{error}
</p>
Primary Badge
<span className="rounded-full bg-[#0B6E35]/10 px-2 py-0.5 text-xs font-medium text-[#0B6E35]">
Primær konto
</span>
Avatar (Initials)
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#0B6E35] text-sm font-bold text-white">
{initials}
</div>
Transaction Amount (Positive / Negative)
// Positive (received)
<span className="text-sm font-semibold text-[#10B981]">+1 250,00 NOK</span>
// Negative (sent)
<span className="text-sm font-semibold text-[#EF4444]">-500,00 NOK</span>
Approval
| Role |
Name |
Date |
Signature |
| Author |
John (AI Director) |
2026-02-23 |
|
| Lead Designer |
|
|
|
| Frontend Lead |
|
|
|
| Accessibility Reviewer |
|
|
|