đ§ Design Systems Demystified: The Complete Technical Guide [v2.0]
The definitive technical guide to design systems for rookie engineers. Master design tokens, Gestalt principles, Atomic Design methodology, visual hierarchy, accessibility standards, and build production-ready component libraries from first principles.
Introduction: The Science Behind Beautiful Interfaces
Visual Designer Skills Illustrated!
Youâve seen it happen: you land on a website and within a fraction of a secondâbefore youâve consciously read a single wordâyour brain has already judged it. Beautiful or ugly. Trustworthy or sketchy. Professional or amateur.
Research shows this judgment happens in just 50 milliseconds. Thatâs faster than a single eye blink.
But hereâs the fascinating part: this instantaneous reaction isnât random. Itâs driven by fundamental principles of human perceptionâprinciples that have been studied by psychologists, neuroscientists, and designers for over a century. Your brain isnât actually judging âbeautyâ in some abstract sense. Itâs evaluating cognitive efficiency: how easily can it parse the information on screen?
When you build enterprise applicationsâplatforms with authentication, blogging, comments, real-time notifications, project management, and team collaborationâvisual consistency isnât just aesthetic polish. Itâs the difference between an interface that feels effortless and one that exhausts users mentally.
This guide will teach you:
- The psychological principles that govern how humans perceive interfaces (Gestalt theory, cognitive load)
- The scientific foundation of visual hierarchy (why size, contrast, and spacing work the way they do)
- The systematic methodology for building scalable component libraries (Atomic Design)
- The technical implementation using design tokens, CSS variables, and modern frameworks
- The accessibility standards (WCAG 2.1/2.2) that make interfaces usable for everyone
- The governance patterns that keep design systems maintainable at scale
Weâll build everything from first principles, using TechHub Enterpriseâa complete B2B platform with authentication, blogging, comments, notifications, and project managementâas our comprehensive case study.
By the end, you wonât just know what design systems are. Youâll understand why they work the way they do, rooted in human psychology and cognitive science.
Part 1: The Psychology of Visual Perception
Before we write a single line of code, we need to understand how human perception works. These arenât design opinionsâtheyâre scientific principles discovered through decades of research.
1.1 Gestalt Principles: How the Brain Groups Information
In the 1920s, German psychologists Max Wertheimer, Kurt Koffka, and Wolfgang KĂśhler discovered something remarkable: the human brain doesnât see individual elements. It automatically organizes visual information into meaningful patterns.
These principles, collectively called Gestalt psychology (âGestaltâ means âunified wholeâ in German), explain why certain designs feel intuitive while others feel chaotic.
Principle 1: Proximity (Law of Nearness)
The Science: Objects close to each other are perceived as related, even if they look different.
Why It Matters: Proximity is the strongest grouping principle. It can override other visual cues like color or shape.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!-- Visual Grouping Through Proximity -->
<!-- POOR PROXIMITY: Elements equally spaced -->
<div style="display: flex; gap: 20px;">
<div>Name:</div>
<div><input /></div>
<div>Email:</div>
<div><input /></div>
</div>
<!-- Brain perceives: Four separate, unrelated items -->
<!-- GOOD PROXIMITY: Related elements grouped -->
<div style="display: flex; flex-direction: column; gap: 30px;">
<div style="display: flex; flex-direction: column; gap: 8px;">
<label>Name:</label>
<input />
</div>
<div style="display: flex; flex-direction: column; gap: 8px;">
<label>Email:</label>
<input />
</div>
</div>
<!-- Brain perceives: Two clear form fields -->
CSS Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Using spacing tokens to create proximity groups */
.form-field {
display: flex;
flex-direction: column;
gap: var(--spacing-2); /* 8px - tight coupling */
margin-bottom: var(--spacing-6); /* 24px - separation between groups */
}
.form-field__label {
/* Visually bound to input below through proximity */
}
.form-field__input {
/* Perceived as part of label above */
}
Real Example: Login Form
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<form class="login-form">
<!-- Group 1: Email field (label + input closely spaced) -->
<div class="form-group">
<label>Email Address</label>
<input type="email" />
<span class="helper-text">We'll never share your email</span>
</div>
<!-- Larger gap indicates new group -->
<!-- Group 2: Password field -->
<div class="form-group">
<label>Password</label>
<input type="password" />
</div>
<!-- Even larger gap before actions -->
<!-- Group 3: Actions -->
<div class="form-actions">
<button type="submit">Sign In</button>
<a href="/forgot">Forgot password?</a>
</div>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.form-group {
display: flex;
flex-direction: column;
gap: var(--spacing-2); /* 8px - Elements within group */
margin-bottom: var(--spacing-6); /* 24px - Separation between groups */
}
.form-group__helper {
margin-top: var(--spacing-1); /* 4px - Still part of group */
font-size: var(--text-xs);
color: var(--color-gray-500);
}
.form-actions {
margin-top: var(--spacing-8); /* 32px - Clear separation from fields */
display: flex;
gap: var(--spacing-4); /* 16px - Related actions */
}
Principle 2: Similarity (Law of Resemblance)
The Science: Elements sharing visual characteristics (shape, color, size, orientation) are perceived as related or belonging to the same group.
Why It Matters: Users learn patterns. When all clickable buttons share the same blue color, users immediately recognize future blue elements as interactive.
Real Example: Button Variants
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* Primary buttons - Similar appearance signals similar function */
.btn-primary,
.btn-submit,
.btn-confirm {
background: var(--color-primary-600);
color: var(--color-gray-50);
border-radius: var(--radius-md);
/* Users learn: Blue filled = main action */
}
/* Secondary buttons - Different appearance = different importance */
.btn-secondary,
.btn-cancel {
background: transparent;
border: 2px solid var(--color-primary-600);
color: var(--color-primary-600);
/* Users learn: Outlined = alternative action */
}
/* Danger buttons - Red signals destructive action */
.btn-danger,
.btn-delete {
background: var(--color-error);
color: var(--color-gray-50);
/* Users learn: Red = be careful */
}
Consistency Creates Predictability:
1
2
3
4
5
6
7
8
9
10
11
12
<!-- Throughout the application, users see patterns -->
<!-- Blog Post Editor -->
<button class="btn-primary">Publish Post</button>
<button class="btn-secondary">Save Draft</button>
<button class="btn-danger">Delete Post</button>
<!-- Comment System -->
<button class="btn-primary">Post Comment</button>
<button class="btn-secondary">Cancel</button>
<!-- User learns: Primary (blue filled) = main action, everywhere -->
Principle 3: Continuity (Law of Good Continuation)
The Science: The eye naturally follows lines, curves, and paths. Elements arranged along a continuous line or curve are perceived as related.
Why It Matters: Guides users through interfaces naturally, creating âvisual flow.â
Real Example: Navigation Breadcrumbs
1
2
3
4
5
6
7
8
9
<nav aria-label="Breadcrumb" class="breadcrumb">
<a href="/">Home</a>
<span class="separator">âş</span>
<a href="/blog">Blog</a>
<span class="separator">âş</span>
<a href="/blog/design-systems">Design Systems</a>
<span class="separator">âş</span>
<span aria-current="page">Introduction</span>
</nav>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.breadcrumb {
display: flex;
align-items: center;
gap: var(--spacing-2);
/* Elements form a continuous horizontal line */
}
.breadcrumb a {
color: var(--color-primary-600);
text-decoration: none;
}
.separator {
color: var(--color-gray-400);
/* Visual continuation markers */
}
Timeline Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="timeline">
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">Account Created</div>
</div>
<div class="timeline-connector"></div>
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">Email Verified</div>
</div>
<div class="timeline-connector"></div>
<div class="timeline-item">
<div class="timeline-marker"></div>
<div class="timeline-content">Profile Completed</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.timeline {
position: relative;
padding-left: 40px;
}
/* Continuous vertical line guides the eye */
.timeline::before {
content: '';
position: absolute;
left: 15px;
top: 0;
bottom: 0;
width: 2px;
background: var(--color-gray-300);
/* Vertical continuity */
}
.timeline-marker {
position: absolute;
left: -25px;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--color-primary-600);
border: 2px solid var(--color-gray-50);
/* Points along the continuous line */
}
Principle 4: Closure (Law of Completeness)
The Science: The brain automatically completes incomplete shapes, filling in missing information to perceive a whole object.
Why It Matters: You donât need to fully enclose elementsâthe brain will âcloseâ the shape mentally, reducing visual clutter.
Real Example: Card Design
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Minimal card - brain completes the boundary */
.card-minimal {
padding: var(--spacing-4);
border-left: 4px solid var(--color-primary-600);
background: var(--color-gray-50);
/* No full border needed - brain perceives a complete card */
}
/* Loading skeleton - incomplete shapes suggest content */
.skeleton-text {
height: 16px;
background: linear-gradient(
90deg,
var(--color-gray-200) 0%,
var(--color-gray-300) 50%,
var(--color-gray-200) 100%
);
border-radius: var(--radius-sm);
/* Brain fills in "this will be text" */
}
.skeleton-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--color-gray-300);
/* Circular shape + position suggests "profile picture coming" */
}
Icon Design Using Closure:
1
2
3
4
5
6
<!-- Hamburger menu icon - three lines, brain sees "menu" -->
<button class="menu-toggle" aria-label="Open menu">
<span class="menu-line"></span>
<span class="menu-line"></span>
<span class="menu-line"></span>
</button>
Principle 5: Figure-Ground (Foreground-Background Separation)
The Science: The brain distinguishes objects (figure) from their surroundings (ground). Clear figure-ground relationships reduce cognitive load.
Why It Matters: Ambiguous figure-ground relationships confuse usersâthey canât tell whatâs interactive vs. decorative.
Real Example: Modal Dialogs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div class="modal-overlay">
<!-- Ground: Semi-transparent backdrop -->
<div class="modal-dialog">
<!-- Figure: Elevated, clear foreground -->
<h2>Confirm Deletion</h2>
<p>Are you sure you want to delete this post?</p>
<div class="modal-actions">
<button class="btn-danger">Delete</button>
<button class="btn-secondary">Cancel</button>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* Ground: Recedes into background */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6); /* Semi-transparent black */
backdrop-filter: blur(4px); /* Blurs background content */
z-index: var(--z-modal-backdrop);
}
/* Figure: Advances to foreground */
.modal-dialog {
position: relative;
background: var(--color-gray-50); /* Solid, opaque */
padding: var(--spacing-6);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-2xl); /* Strong shadow = elevation */
z-index: var(--z-modal);
/* Clear separation from ground */
}
Principle 6: Common Region (Law of Enclosure)
The Science: Elements within a defined boundary (border, background, container) are perceived as a group, even if they differ visually.
Why It Matters: The most powerful grouping tool. Overrides proximity and similarity.
Real Example: Card Components
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* Card creates a common region */
.card {
padding: var(--spacing-4);
background: var(--color-gray-50);
border: 1px solid var(--color-gray-300);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
}
/* Everything inside perceived as related, regardless of appearance */
.card__image {
/* Could be an image */
}
.card__title {
font-size: var(--text-xl);
color: var(--color-gray-900);
/* Different size/color from image */
}
.card__description {
font-size: var(--text-sm);
color: var(--color-gray-600);
/* Different from title */
}
.card__action {
/* Button with different styling */
}
/* Despite visual differences, the border groups them */
Dashboard Widget Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="dashboard">
<!-- Each widget is a common region -->
<div class="widget">
<h3 class="widget__title">Revenue This Month</h3>
<div class="widget__value">$42,350</div>
<div class="widget__change">+12.5%</div>
</div>
<div class="widget">
<h3 class="widget__title">Active Users</h3>
<div class="widget__value">1,240</div>
<div class="widget__change">+8.3%</div>
</div>
<!-- Clear regions = clear mental grouping -->
</div>
Principle 7: Symmetry (Law of Symmetrical Balance)
The Science: Symmetrical elements are perceived as unified, stable, and belonging together. Asymmetry draws attention and signals importance.
Real Example: Centered Login Forms vs. Asymmetric Dashboards
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Symmetrical login - signals stability and focus */
.login-container {
display: flex;
justify-content: center; /* Centered horizontally */
align-items: center; /* Centered vertically */
min-height: 100vh;
/* Perfect symmetry = calm, focused experience */
}
/* Asymmetric dashboard - signals information density */
.dashboard-layout {
display: grid;
grid-template-columns: 250px 1fr; /* Sidebar + main content */
/* Asymmetry = active, information-rich */
}
1.2 Cognitive Load Theory: Why Hierarchy Reduces Mental Effort
Cognitive Load Theory (developed by psychologist John Sweller) explains that humans have limited working memory capacity. When an interface overwhelms this capacity, users experience mental exhaustion.
Three Types of Cognitive Load:
- Intrinsic Load: The inherent complexity of the task
- Extraneous Load: Unnecessary mental effort caused by poor design â We control this
- Germane Load: Productive mental effort (learning, understanding)
Visual hierarchy reduces extraneous load by making information processing automatic rather than conscious.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!-- HIGH EXTRANEOUS LOAD: No hierarchy -->
<div>
<span>Welcome to TechHub</span>
<span>Dashboard</span>
<span>You have 3 new notifications</span>
<span>Recent Activity</span>
<span>Project Alpha updated 2 hours ago</span>
<span>Sarah Chen commented on your post</span>
</div>
<!-- User's brain: "I have to read everything to understand what's important" -->
<!-- LOW EXTRANEOUS LOAD: Clear hierarchy -->
<div class="dashboard">
<!-- Level 1: Primary - Scanned first -->
<h1 class="page-title">Dashboard</h1>
<!-- Level 2: Secondary - Scanned second -->
<p class="welcome-message">Welcome to TechHub</p>
<!-- Level 3: Alert - Draws attention -->
<div class="notification-badge">3 new notifications</div>
<!-- Level 4: Section header -->
<h2 class="section-title">Recent Activity</h2>
<!-- Level 5: Content items -->
<ul class="activity-list">
<li>Project Alpha updated 2 hours ago</li>
<li>Sarah Chen commented on your post</li>
</ul>
</div>
<!-- User's brain: "I immediately see: main heading, welcome, alert, section, items" -->
The 50-Millisecond Rule:
Research by Gitte Lindgaard (2006) found users form aesthetic judgments in 50ms. In that time, the brain is performing:
- Pattern recognition (Gestalt principles activate automatically)
- Hierarchy scanning (largest, highest-contrast elements first)
- Familiarity matching (âHave I seen this pattern before?â)
Your design systemâs job: make these 50ms work in your favor.
Part 2: Visual Hierarchy â The Eight Foundational Principles
Visual hierarchy is the arrangement of elements to communicate their order of importance. Itâs not subjective aestheticsâitâs applied cognitive psychology.
2.1 The Eight Core Principles
Principle 1: Size & Scale (Visual Weight)
The Science: Larger objects command more attention. This is called the size-importance correlationâour brains evolved to notice larger objects first (potential threats/opportunities in nature).
Typographic Scale (Modular Scale Ratio: 1.25)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* Hierarchical type scale */
:root {
--text-xs: 0.75rem; /* 12px - Metadata, timestamps */
--text-sm: 0.875rem; /* 14px - Helper text, captions */
--text-base: 1rem; /* 16px - Body text (baseline) */
--text-lg: 1.125rem; /* 18px - Emphasized body */
--text-xl: 1.25rem; /* 20px - Subheadings */
--text-2xl: 1.5rem; /* 24px - Section headings */
--text-3xl: 1.875rem; /* 30px - Page headings */
--text-4xl: 2.25rem; /* 36px - Hero headings */
--text-5xl: 3rem; /* 48px - Display headings */
}
/* Blog post hierarchy using scale */
.post-title {
font-size: var(--text-4xl); /* 36px - PRIMARY focus */
font-weight: var(--font-bold);
line-height: var(--leading-tight);
margin-bottom: var(--spacing-4);
}
.post-subtitle {
font-size: var(--text-xl); /* 20px - SECONDARY */
font-weight: var(--font-medium);
color: var(--color-gray-700);
margin-bottom: var(--spacing-6);
}
.post-content {
font-size: var(--text-base); /* 16px - CONTENT */
line-height: var(--leading-relaxed);
}
.post-metadata {
font-size: var(--text-sm); /* 14px - METADATA */
color: var(--color-gray-500);
}
Why 1.25 ratio? It creates noticeable but harmonious size jumps. Each level is 25% larger than the previous, which the eye registers as a clear hierarchy step.
Principle 2: Color & Contrast (Attention Direction)
The Science: High-contrast elements draw attention first. The Weber-Fechner Law states that the noticeable difference in a stimulus is proportional to the magnitude of the original stimulus.
Practical Translation: Dark text on light background (or vice versa) = high contrast = noticed first.
WCAG 2.1 Standards (Precise Requirements):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* WCAG AA Requirements */
/* Normal text (< 18pt or < 14pt bold) */
.text-normal {
color: var(--color-gray-900); /* #1A202C */
background: var(--color-gray-50); /* #FFFFFF */
/* Contrast ratio: 16.1:1 â (exceeds 4.5:1 minimum) */
}
/* Large text (⼠18pt or ⼠14pt bold) */
.text-large {
color: var(--color-gray-700); /* #2D3748 */
background: var(--color-gray-50);
/* Contrast ratio: 10.7:1 â (exceeds 3:1 minimum) */
}
/* UI Components (WCAG 2.1 addition) */
.button-primary {
background: var(--color-primary-600); /* #2C5282 */
border: 2px solid var(--color-primary-700);
/* Component contrast: 3.2:1 â (exceeds 3:1 minimum) */
}
/* WCAG AAA Requirements (Enhanced) */
.text-enhanced {
color: var(--color-gray-900);
background: var(--color-gray-50);
/* Contrast ratio: 16.1:1 â (exceeds 7:1 minimum for normal text) */
}
Color Hierarchy Implementation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* Primary CTA - Highest contrast, most attention */
.cta-primary {
background: var(--color-primary-600);
color: var(--color-gray-50);
/* Contrast: 7.2:1 - Passes WCAG AAA */
}
/* Secondary CTA - Medium contrast */
.cta-secondary {
background: transparent;
border: 2px solid var(--color-primary-600);
color: var(--color-primary-600);
/* Reduced visual weight through less contrast */
}
/* Tertiary/Ghost - Minimal contrast until hover */
.cta-ghost {
background: transparent;
color: var(--color-primary-600);
/* Lowest hierarchy */
}
.cta-ghost:hover {
background: var(--color-primary-50);
/* Gains contrast on interaction */
}
Semantic Color System:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* Intent-based color tokens */
:root {
--color-success: #38A169; /* Green - positive actions */
--color-warning: #D69E2E; /* Amber - caution */
--color-error: #E53E3E; /* Red - destructive/errors */
--color-info: #3182CE; /* Blue - informational */
}
/* Notification hierarchy through color */
.notification--success {
border-left: 4px solid var(--color-success);
background: #F0FFF4; /* Light green tint */
/* Success = green = positive association */
}
.notification--error {
border-left: 4px solid var(--color-error);
background: #FFF5F5; /* Light red tint */
/* Error = red = universal warning signal */
}
Principle 3: Whitespace (Negative Space)
The Science: The Law of Proximity (Gestalt) â elements close together = related; far apart = separate. Whitespace is how you control proximity.
8-Point Grid System (Material Design Standard):
1
2
3
4
5
6
7
8
9
10
11
:root {
/* Base unit: 8px */
--spacing-1: 0.25rem; /* 4px - Micro spacing */
--spacing-2: 0.5rem; /* 8px - Base unit */
--spacing-3: 0.75rem; /* 12px - Tight groups */
--spacing-4: 1rem; /* 16px - Standard spacing */
--spacing-6: 1.5rem; /* 24px - Section spacing */
--spacing-8: 2rem; /* 32px - Major sections */
--spacing-12: 3rem; /* 48px - Page sections */
--spacing-16: 4rem; /* 64px - Hero spacing */
}
Why 8px? Most screen densities are divisible by 8, ensuring sharp rendering. Also creates a rhythm thatâs intuitive.
Hierarchy Through Spacing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<article class="blog-post">
<!-- Tight spacing = closely related -->
<h1 class="post__title">Understanding Design Systems</h1>
<p class="post__subtitle">A comprehensive guide for beginners</p>
<!-- Gap: 12px (--spacing-3) - Title and subtitle are related -->
<div class="post__meta">
<span>By Alex Chen</span>
<span>March 15, 2024</span>
</div>
<!-- Gap: 32px (--spacing-8) - Meta separated from title group -->
<div class="post__content">
<p>First paragraph...</p>
<!-- Gap: 16px (--spacing-4) - Paragraphs are separate thoughts -->
<p>Second paragraph...</p>
</div>
<!-- Gap: 48px (--spacing-12) - Content separated from next section -->
<section class="post__comments">
<h2>Comments</h2>
<!-- New major section -->
</section>
</article>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.blog-post {
max-width: 720px;
margin: 0 auto;
padding: var(--spacing-8);
}
.post__title {
margin-bottom: var(--spacing-3); /* 12px - Tight coupling with subtitle */
}
.post__subtitle {
margin-bottom: var(--spacing-2); /* 8px - Still part of title group */
}
.post__meta {
margin-bottom: var(--spacing-8); /* 32px - Clear separation from content */
display: flex;
gap: var(--spacing-4);
}
.post__content p {
margin-bottom: var(--spacing-4); /* 16px - Standard paragraph spacing */
}
.post__content {
margin-bottom: var(--spacing-12); /* 48px - Major section break */
}
Visual Rhythm Pattern:
1
2
3
4
Tight (8-12px) â Elements within a component
Standard (16-24px) â Between components
Wide (32-48px) â Between sections
Extra Wide (64px+) â Between major page areas
Principle 4: Typography (Weight, Style, Family)
The Science: Typographic hierarchy uses weight, style, and font choice to create visual differentiation without relying solely on size.
Weight Hierarchy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
:root {
--font-regular: 400; /* Body text */
--font-medium: 500; /* Subtle emphasis */
--font-semibold: 600; /* Subheadings, labels */
--font-bold: 700; /* Headings */
--font-extrabold: 800; /* Display headings (rare) */
}
/* Hierarchy through weight */
.heading-primary {
font-weight: var(--font-bold); /* 700 */
/* Heavy weight = important */
}
.heading-secondary {
font-weight: var(--font-semibold); /* 600 */
/* Medium weight = less important than primary */
}
.body-text {
font-weight: var(--font-regular); /* 400 */
/* Light weight = content */
}
.emphasized {
font-weight: var(--font-medium); /* 500 */
/* Slight emphasis within body text */
}
Line Height (Leading):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
:root {
--leading-none: 1; /* 100% - Tight display text */
--leading-tight: 1.25; /* 125% - Headings */
--leading-snug: 1.375; /* 137.5% - UI text */
--leading-normal: 1.5; /* 150% - Body text */
--leading-relaxed: 1.75; /* 175% - Long-form reading */
--leading-loose: 2; /* 200% - Very relaxed (rare) */
}
.display-heading {
font-size: var(--text-4xl);
line-height: var(--leading-tight); /* 1.25 - Headings need less space */
letter-spacing: -0.02em; /* Negative tracking for large text */
}
.blog-content {
font-size: var(--text-base);
line-height: var(--leading-relaxed); /* 1.75 - Comfortable reading */
letter-spacing: 0;
}
Why different line heights? Larger text needs less line spacing (already has vertical space). Smaller text, especially in long-form content, needs more line height for readability.
Principle 5: Position & Layout (F-Pattern, Z-Pattern)
The Science: Eye-tracking studies by Nielsen Norman Group discovered predictable scanning patterns:
F-Pattern: Used for text-heavy content (articles, search results)
- Eyes move horizontally across top
- Drop down vertically on left side
- Scan horizontally again (shorter)
- Results in an âFâ shape heat map
Z-Pattern: Used for sparse content (landing pages, ads)
- Top-left â Top-right
- Diagonal to bottom-left
- Bottom-left â Bottom-right
- Results in a âZâ shape
F-Pattern Implementation (Blog Post):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<article class="article-layout">
<!-- TOP HORIZONTAL BAR - Scanned first -->
<header class="article-header">
<h1>The Complete Guide to Design Systems</h1>
<p class="subtitle">Everything you need to know</p>
</header>
<!-- LEFT EDGE - Scanned second (vertical) -->
<div class="article-body">
<!-- Each paragraph's first few words get attention -->
<p><strong>Design systems</strong> are the foundation...</p>
<p><strong>Visual hierarchy</strong> determines what...</p>
<p><strong>Components</strong> are reusable building...</p>
</div>
<!-- RIGHT SIDEBAR - Least attention (falls outside F) -->
<aside class="article-sidebar">
<div class="related-posts">Related Articles</div>
</aside>
</article>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.article-layout {
display: grid;
grid-template-columns: 1fr 300px; /* Content + sidebar */
gap: var(--spacing-8);
max-width: 1200px;
margin: 0 auto;
}
/* Optimize for F-pattern */
.article-header {
grid-column: 1 / -1; /* Spans full width - top horizontal bar */
}
.article-body {
/* Left column - main scanning area */
}
.article-sidebar {
/* Right column - peripheral vision only */
}
/* Make first words of paragraphs stand out */
.article-body p strong:first-child {
font-weight: var(--font-semibold);
color: var(--color-gray-900);
}
Z-Pattern Implementation (Landing Page):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="hero-section">
<!-- TOP-LEFT: Logo (first fixation) -->
<div class="hero-header">
<img src="logo.svg" alt="TechHub" class="logo" />
<!-- TOP-RIGHT: CTA (second fixation) -->
<button class="cta-primary">Get Started</button>
</div>
<!-- CENTER: Main message (diagonal path) -->
<h1 class="hero-title">Build Better Products Faster</h1>
<p class="hero-subtitle">Enterprise design system platform</p>
<!-- BOTTOM-RIGHT: Secondary CTA (final fixation) -->
<div class="hero-actions">
<button class="cta-primary">Start Free Trial</button>
<button class="cta-secondary">Watch Demo</button>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.hero-section {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: var(--spacing-8);
}
.hero-header {
display: flex;
justify-content: space-between; /* Logo left, CTA right */
align-items: center;
}
.hero-title {
font-size: var(--text-5xl);
text-align: center;
margin-top: auto; /* Pushes to vertical center */
}
.hero-actions {
display: flex;
justify-content: flex-end; /* Aligns to bottom-right */
gap: var(--spacing-4);
margin-top: auto;
}
Principle 6: Depth & Elevation (Material Design Z-Axis)
The Science: The physical world has depth. Objects closer to us appear more important. Material Designâs elevation system applies this to digital interfaces.
Elevation Scale (Density-Independent Pixels):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
:root {
/* Elevation through shadows */
--elevation-0: none; /* Flat surface */
--elevation-1: 0 1px 3px rgba(0,0,0,0.12); /* Cards, slight lift */
--elevation-2: 0 3px 6px rgba(0,0,0,0.15); /* Raised buttons */
--elevation-3: 0 10px 20px rgba(0,0,0,0.15); /* Dropdowns */
--elevation-4: 0 15px 25px rgba(0,0,0,0.15); /* Navigation drawers */
--elevation-5: 0 20px 40px rgba(0,0,0,0.15); /* Modal dialogs */
/* Resting elevations (default states) */
--z-flat: 0;
--z-raised: 1;
--z-overlay: 2;
--z-dropdown: 3;
--z-sticky: 4;
--z-modal: 5;
}
Component Elevation Hierarchy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Flat - No elevation */
.page-background {
box-shadow: var(--elevation-0);
/* Base layer - no depth */
}
/* Raised - Slight elevation (1dp) */
.card {
box-shadow: var(--elevation-1);
transition: box-shadow var(--duration-base) var(--easing-out);
}
.card:hover {
box-shadow: var(--elevation-2);
/* Lifts on hover - interactive feedback */
}
/* Floating - Medium elevation (8dp) */
.floating-action-button {
box-shadow: var(--elevation-3);
/* Always elevated - signals primary action */
}
/* Modal - High elevation (24dp) */
.modal {
box-shadow: var(--elevation-5);
/* Highest elevation - demands attention */
}
Depth Creates Hierarchy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- Layered interface showing depth hierarchy -->
<!-- Layer 0: Page background -->
<div class="page-container">
<!-- Layer 1: Content cards -->
<div class="card">
<h3>Project Alpha</h3>
<p>Status: In Progress</p>
<!-- Layer 2: Button (raised above card) -->
<button class="btn-raised">View Details</button>
</div>
<!-- Layer 3: Floating action button (above all content) -->
<button class="fab">+</button>
<!-- Layer 4: Modal (when opened - above everything) -->
<div class="modal">
<h2>Add New Project</h2>
</div>
</div>
Motion Reinforces Elevation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.card {
transform: translateY(0);
box-shadow: var(--elevation-1);
transition: transform var(--duration-base) var(--easing-out),
box-shadow var(--duration-base) var(--easing-out);
}
.card:hover {
transform: translateY(-4px); /* Physically lifts */
box-shadow: var(--elevation-2);
/* Higher elevation = moves faster (closer to user) */
}
.card:active {
transform: translateY(-1px); /* Presses down */
box-shadow: var(--elevation-1);
}
Principle 7: Alignment (Grid Systems)
The Science: Law of Common Fate (Gestalt) â elements aligned along a common axis are perceived as related.
12-Column Grid (Material Design/Bootstrap Standard):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: var(--spacing-6);
max-width: 1200px;
margin: 0 auto;
}
/* Span different column widths */
.sidebar {
grid-column: span 3; /* 3 columns = 25% width */
}
.main-content {
grid-column: span 9; /* 9 columns = 75% width */
}
/* Feature grid */
.feature-card {
grid-column: span 4; /* 4 columns = 33.33% width */
}
Alignment Creates Visual Order:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- Misaligned - chaotic -->
<div class="poorly-aligned">
<h1>Welcome</h1>
<p style="margin-left: 10px;">Description here</p>
<button style="margin-left: 25px;">Click Me</button>
</div>
<!-- Different left edges = feels disorganized -->
<!-- Well-aligned - orderly -->
<div class="well-aligned">
<h1>Welcome</h1>
<p>Description here</p>
<button>Click Me</button>
</div>
<!-- Common left edge = feels intentional -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.well-aligned {
display: flex;
flex-direction: column;
align-items: flex-start; /* All align to left edge */
gap: var(--spacing-4);
}
/* Or center-aligned for symmetrical layouts */
.center-aligned {
display: flex;
flex-direction: column;
align-items: center; /* All align to center axis */
text-align: center;
}
Principle 8: Repetition & Rhythm (Pattern Recognition)
The Science: The brain is a pattern-recognition machine. Repeated elements become predictable, reducing cognitive load.
Establishing Rhythm:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- Repeated card pattern -->
<div class="card-grid">
<div class="card">
<div class="card__header">Project Alpha</div>
<div class="card__body">Description...</div>
<div class="card__footer">Updated 2h ago</div>
</div>
<div class="card">
<div class="card__header">Project Beta</div>
<div class="card__body">Description...</div>
<div class="card__footer">Updated 5h ago</div>
</div>
<div class="card">
<div class="card__header">Project Gamma</div>
<div class="card__body">Description...</div>
<div class="card__footer">Updated 1d ago</div>
</div>
</div>
<!-- Repeated structure = user learns the pattern instantly -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: var(--spacing-6);
/* Consistent gaps create rhythm */
}
.card {
/* Consistent internal structure */
display: flex;
flex-direction: column;
padding: var(--spacing-4);
border-radius: var(--radius-md);
background: var(--color-gray-50);
}
.card__header {
font-size: var(--text-lg);
font-weight: var(--font-semibold);
margin-bottom: var(--spacing-3);
/* Same across all cards */
}
.card__body {
flex: 1; /* Grows to fill space */
margin-bottom: var(--spacing-3);
}
.card__footer {
font-size: var(--text-sm);
color: var(--color-gray-500);
/* Consistent metadata styling */
}
Rhythm in Spacing:
1
2
3
4
5
6
7
8
9
10
11
12
/* Vertical rhythm using consistent multipliers of base unit */
.content-flow > * + * {
margin-top: var(--spacing-4); /* Base rhythm: 16px */
}
.content-flow > h2 + * {
margin-top: var(--spacing-6); /* Headings get more space: 24px */
}
.content-flow > h1 + * {
margin-top: var(--spacing-8); /* Page titles get most: 32px */
}
Part 3: Design Tokens â The Atomic Foundation
Design tokens are named entities that store visual design attributes. Theyâre the single source of truth for all design decisions.
3.1 What Are Design Tokens? (Technical Definition)
Think of design tokens as design constants or variables that can be consumed across platforms (web, iOS, Android, etc.).
1
2
3
4
5
6
7
8
// Conceptual representation
const designTokens = {
// Instead of using #2C5282 directly everywhere...
colorPrimary600: '#2C5282',
// ...you reference the token name
// If brand changes, update once, changes everywhere
};
Why Tokens Matter:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* â WITHOUT TOKENS: Hard-coded values */
.button-primary {
background: #2C5282;
color: #FFFFFF;
padding: 12px 16px;
border-radius: 8px;
}
.card-header {
background: #2C5282;
color: #FFFFFF;
}
.link-active {
color: #2C5282;
}
/* Problem: If brand blue changes, find/replace 30+ files */
/* â
WITH TOKENS: Named references */
.button-primary {
background: var(--color-primary-600);
color: var(--color-gray-50);
padding: var(--spacing-3) var(--spacing-4);
border-radius: var(--radius-md);
}
.card-header {
background: var(--color-primary-600);
color: var(--color-gray-50);
}
.link-active {
color: var(--color-primary-600);
}
/* Solution: Change one value in tokens.css, updates everywhere */
3.2 Token Tier System (Global â Alias â Component)
Three-Tier Token Architecture:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* ============================================
TIER 1: GLOBAL/PRIMITIVE TOKENS
- Raw values
- Never change based on context
============================================ */
:root {
/* Color primitives */
--color-blue-900: #0A2540;
--color-blue-600: #2C5282;
--color-blue-100: #EBF8FF;
--color-gray-900: #1A202C;
--color-gray-50: #FFFFFF;
--color-green-600: #38A169;
--color-red-600: #E53E3E;
/* Spacing primitives */
--spacing-2: 0.5rem; /* 8px */
--spacing-4: 1rem; /* 16px */
--spacing-6: 1.5rem; /* 24px */
}
/* ============================================
TIER 2: SEMANTIC/ALIAS TOKENS
- Reference primitives
- Add meaning/context
============================================ */
:root {
/* Brand colors */
--color-brand-primary: var(--color-blue-600);
--color-brand-secondary: var(--color-blue-900);
/* Semantic colors */
--color-success: var(--color-green-600);
--color-error: var(--color-red-600);
/* Text colors */
--color-text-primary: var(--color-gray-900);
--color-text-inverse: var(--color-gray-50);
/* Spacing semantic */
--spacing-component-padding: var(--spacing-4);
--spacing-section-gap: var(--spacing-6);
}
/* ============================================
TIER 3: COMPONENT-SPECIFIC TOKENS
- Reference semantic tokens
- Component context
============================================ */
:root {
/* Button tokens */
--button-primary-bg: var(--color-brand-primary);
--button-primary-text: var(--color-text-inverse);
--button-padding-y: var(--spacing-3);
--button-padding-x: var(--spacing-4);
/* Card tokens */
--card-background: var(--color-gray-50);
--card-padding: var(--spacing-component-padding);
--card-border-radius: var(--radius-md);
}
Why Three Tiers?
- Global tokens = âwhat colors existâ
- Semantic tokens = âwhat this color meansâ
- Component tokens = âwhat this component usesâ
Theme Switching Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* Light theme (default) */
:root {
--color-background: var(--color-gray-50);
--color-text: var(--color-gray-900);
--color-border: var(--color-gray-300);
}
/* Dark theme */
[data-theme="dark"] {
/* Change semantic tokens, components update automatically */
--color-background: var(--color-gray-900);
--color-text: var(--color-gray-50);
--color-border: var(--color-gray-700);
}
/* Components use semantic tokens */
.card {
background: var(--color-background);
color: var(--color-text);
border: 1px solid var(--color-border);
/* Adapts to theme automatically */
}
3.3 Complete Token System
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/* /styles/tokens.css - Complete Design Token System */
:root {
/* ===== COLOR TOKENS ===== */
/* Brand Palette (10-shade scale) */
--color-primary-50: #EBF8FF;
--color-primary-100: #BEE3F8;
--color-primary-200: #90CDF4;
--color-primary-300: #63B3ED;
--color-primary-400: #4299E1;
--color-primary-500: #3182CE; /* Base brand color */
--color-primary-600: #2C5282; /* Primary buttons */
--color-primary-700: #1A365D; /* Hover states */
--color-primary-800: #123456;
--color-primary-900: #0A2540;
/* Neutral Palette */
--color-gray-50: #FFFFFF;
--color-gray-100: #F7FAFC;
--color-gray-200: #EDF2F7;
--color-gray-300: #E2E8F0;
--color-gray-400: #CBD5E0;
--color-gray-500: #A0AEC0;
--color-gray-600: #718096;
--color-gray-700: #4A5568;
--color-gray-800: #2D3748;
--color-gray-900: #1A202C;
/* Semantic Colors */
--color-success-light: #9AE6B4;
--color-success: #38A169;
--color-success-dark: #276749;
--color-warning-light: #FAF089;
--color-warning: #D69E2E;
--color-warning-dark: #B7791F;
--color-error-light: #FC8181;
--color-error: #E53E3E;
--color-error-dark: #C53030;
--color-info-light: #90CDF4;
--color-info: #3182CE;
--color-info-dark: #2C5282;
/* ===== TYPOGRAPHY TOKENS ===== */
/* Font Families */
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-serif: 'Georgia', 'Times New Roman', serif;
--font-mono: 'Fira Code', 'Courier New', Consolas, monospace;
/* Font Sizes (Modular scale 1.25) */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 3.75rem; /* 60px */
/* Font Weights */
--font-thin: 100;
--font-extralight: 200;
--font-light: 300;
--font-regular: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
--font-extrabold: 800;
--font-black: 900;
/* Line Heights */
--leading-none: 1;
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
--leading-loose: 2;
/* Letter Spacing */
--tracking-tighter: -0.05em;
--tracking-tight: -0.025em;
--tracking-normal: 0;
--tracking-wide: 0.025em;
--tracking-wider: 0.05em;
--tracking-widest: 0.1em;
/* ===== SPACING TOKENS (8pt grid) ===== */
--spacing-px: 1px;
--spacing-0: 0;
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
--spacing-5: 1.25rem; /* 20px */
--spacing-6: 1.5rem; /* 24px */
--spacing-7: 1.75rem; /* 28px */
--spacing-8: 2rem; /* 32px */
--spacing-10: 2.5rem; /* 40px */
--spacing-12: 3rem; /* 48px */
--spacing-16: 4rem; /* 64px */
--spacing-20: 5rem; /* 80px */
--spacing-24: 6rem; /* 96px */
--spacing-32: 8rem; /* 128px */
/* ===== SIZING TOKENS ===== */
/* Container widths */
--container-xs: 20rem; /* 320px */
--container-sm: 24rem; /* 384px */
--container-md: 28rem; /* 448px */
--container-lg: 32rem; /* 512px */
--container-xl: 36rem; /* 576px */
--container-2xl: 42rem; /* 672px */
--container-3xl: 48rem; /* 768px */
--container-4xl: 56rem; /* 896px */
--container-5xl: 64rem; /* 1024px */
--container-6xl: 72rem; /* 1152px */
--container-7xl: 80rem; /* 1280px */
/* ===== BORDER TOKENS ===== */
/* Border Widths */
--border-0: 0;
--border-1: 1px;
--border-2: 2px;
--border-4: 4px;
--border-8: 8px;
/* Border Radius */
--radius-none: 0;
--radius-sm: 0.125rem; /* 2px */
--radius-base: 0.25rem; /* 4px */
--radius-md: 0.5rem; /* 8px */
--radius-lg: 0.75rem; /* 12px */
--radius-xl: 1rem; /* 16px */
--radius-2xl: 1.5rem; /* 24px */
--radius-3xl: 2rem; /* 32px */
--radius-full: 9999px; /* Circular */
/* ===== SHADOW TOKENS (Elevation) ===== */
--shadow-none: none;
--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
--shadow-base: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
--shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
--shadow-2xl: 0 30px 60px -15px rgba(0, 0, 0, 0.3);
/* Inner Shadows */
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05);
/* ===== ANIMATION TOKENS ===== */
/* Duration */
--duration-75: 75ms;
--duration-100: 100ms;
--duration-150: 150ms;
--duration-200: 200ms;
--duration-300: 300ms;
--duration-500: 500ms;
--duration-700: 700ms;
--duration-1000: 1000ms;
/* Easing Functions */
--ease-linear: linear;
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
--ease-elastic: cubic-bezier(0.68, -0.6, 0.32, 1.6);
/* ===== Z-INDEX TOKENS ===== */
--z-0: 0;
--z-10: 10;
--z-20: 20;
--z-30: 30;
--z-40: 40;
--z-50: 50;
--z-dropdown: 1000;
--z-sticky: 1020;
--z-fixed: 1030;
--z-modal-backdrop: 1040;
--z-modal: 1050;
--z-popover: 1060;
--z-tooltip: 1070;
/* ===== OPACITY TOKENS ===== */
--opacity-0: 0;
--opacity-5: 0.05;
--opacity-10: 0.1;
--opacity-20: 0.2;
--opacity-30: 0.3;
--opacity-40: 0.4;
--opacity-50: 0.5;
--opacity-60: 0.6;
--opacity-70: 0.7;
--opacity-80: 0.8;
--opacity-90: 0.9;
--opacity-100: 1;
}
Part 4: Atomic Design â Building Systems Methodically
In 2013, Brad Frost introduced Atomic Design: a methodology for creating design systems inspired by chemistry. Instead of designing full pages, you build a system of reusable components that progressively combine into complete interfaces.
4.1 The Five Stages of Atomic Design
graph TB
A[Atoms] --> B[Molecules]
B --> C[Organisms]
C --> D[Templates]
D --> E[Pages]
A1["⢠Buttons<br/>⢠Inputs<br/>⢠Labels<br/>⢠Icons"] -.-> A
B1["⢠Search bar<br/>⢠Form field<br/>⢠Nav item"] -.-> B
C1["⢠Header<br/>⢠Card list<br/>⢠Comment thread"] -.-> C
D1["⢠Blog layout<br/>⢠Dashboard grid<br/>⢠Login page"] -.-> D
E1["⢠Actual content<br/>⢠Real data<br/>⢠Final UI"] -.-> E
style A fill:#fff9c4,stroke:#f57f17
style B fill:#c8e6c9,stroke:#388e3c
style C fill:#b3e5fc,stroke:#0277bd
style D fill:#d1c4e9,stroke:#512da8
style E fill:#f8bbd0,stroke:#c2185b
Stage 1: Atoms
Definition: The smallest functional building blocks. HTML elements that canât be broken down further without losing functionality.
Examples:
<button><input><label><h1>through<h6><p>- Icons
- Color swatches
- Font choices
Code Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- ATOM: Button -->
<button class="btn">Click Me</button>
<!-- ATOM: Input -->
<input type="text" class="input" />
<!-- ATOM: Label -->
<label class="label">Email Address</label>
<!-- ATOM: Heading -->
<h1 class="heading-1">Page Title</h1>
<!-- ATOM: Icon -->
<svg class="icon" width="20" height="20">
<path d="M..." />
</svg>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* Atom Styles - Single Responsibility */
.btn {
/* Base button atom */
padding: var(--spacing-3) var(--spacing-4);
border: none;
border-radius: var(--radius-md);
font-size: var(--text-base);
font-weight: var(--font-semibold);
cursor: pointer;
transition: all var(--duration-150) var(--ease-out);
}
.input {
/* Base input atom */
padding: var(--spacing-3);
border: 1px solid var(--color-gray-300);
border-radius: var(--radius-md);
font-size: var(--text-base);
}
.label {
/* Base label atom */
display: block;
font-size: var(--text-sm);
font-weight: var(--font-medium);
color: var(--color-gray-700);
}
Why Atoms Matter:
- Single Responsibility: Each atom does one thing well
- Reusability: Used across multiple molecules
- Consistency: Same button styling everywhere
- Testability: Easy to test in isolation
Stage 2: Molecules
Definition: Groups of atoms bonded together to form functional units. Simple components with a specific purpose.
Examples:
- Search bar = label + input + button
- Form field = label + input + error message
- Navigation item = icon + text + badge
Code Example: Search Molecule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- MOLECULE: Search Bar -->
<form class="search-bar">
<!-- Atoms combined -->
<label for="search" class="label visually-hidden">Search</label>
<input
type="search"
id="search"
class="input search-bar__input"
placeholder="Search posts..."
/>
<button type="submit" class="btn btn--primary search-bar__button">
<svg class="icon"><!-- Search icon --></svg>
Search
</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.search-bar {
display: flex;
gap: var(--spacing-2);
max-width: 500px;
/* Molecule combines atoms with specific layout */
}
.search-bar__input {
flex: 1;
/* Uses base input atom styles, adds specific behavior */
}
.search-bar__button {
/* Uses base button atom styles */
display: flex;
align-items: center;
gap: var(--spacing-2);
}
.visually-hidden {
/* Accessibility pattern */
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
}
More Molecule Examples:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- MOLECULE: Form Field -->
<div class="form-field">
<label for="email" class="label">Email Address</label>
<input
type="email"
id="email"
class="input"
placeholder="you@company.com"
/>
<span class="form-field__helper">We'll never share your email</span>
</div>
<!-- MOLECULE: Avatar with Name -->
<div class="user-badge">
<img src="avatar.jpg" alt="Alex Chen" class="avatar" />
<div class="user-badge__info">
<span class="user-badge__name">Alex Chen</span>
<span class="user-badge__role">Engineering</span>
</div>
</div>
<!-- MOLECULE: Stat Card -->
<div class="stat-card">
<span class="stat-card__label">Page Views</span>
<span class="stat-card__value">1,240</span>
<span class="stat-card__change">+12.5%</span>
</div>
Single Responsibility Principle:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// â
GOOD: Molecule with single purpose
function SearchBar({ onSearch }) {
return (
<form className="search-bar" onSubmit={onSearch}>
<label htmlFor="search" className="visually-hidden">Search</label>
<input type="search" id="search" />
<button type="submit">Search</button>
</form>
);
}
// â BAD: Molecule doing too much
function SearchBarWithResultsAndFiltersAndPagination() {
// Too complex - this is an organism, not a molecule
}
Stage 3: Organisms
Definition: Complex UI components composed of groups of molecules and/or atoms. Form distinct sections of an interface.
Examples:
- Header = logo + navigation + search + user menu
- Product card = image + title + description + price + buttons
- Comment thread = multiple comment molecules + reply forms
- Blog post list = multiple post card organisms
Code Example: Site Header Organism
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- ORGANISM: Site Header -->
<header class="site-header">
<!-- Molecule: Logo -->
<div class="site-header__logo">
<img src="logo.svg" alt="TechHub" class="logo" />
</div>
<!-- Molecule: Primary Navigation -->
<nav class="site-header__nav" aria-label="Primary navigation">
<a href="/dashboard" class="nav-item">Dashboard</a>
<a href="/blog" class="nav-item">Blog</a>
<a href="/projects" class="nav-item">Projects</a>
</nav>
<!-- Molecule: Search Bar -->
<form class="site-header__search">
<input type="search" placeholder="Search..." />
<button type="submit">Search</button>
</form>
<!-- Molecule: User Menu -->
<div class="site-header__user">
<button class="notification-bell">
<span class="badge">3</span>
</button>
<div class="user-menu">
<img src="avatar.jpg" alt="User" class="avatar" />
<span>Alex Chen</span>
</div>
</div>
</header>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.site-header {
display: flex;
align-items: center;
gap: var(--spacing-6);
padding: var(--spacing-4) var(--spacing-6);
background: var(--color-gray-50);
border-bottom: 1px solid var(--color-gray-300);
box-shadow: var(--shadow-sm);
/* Organism combines multiple molecules into cohesive section */
}
.site-header__logo {
/* Logo molecule */
}
.site-header__nav {
flex: 1;
display: flex;
gap: var(--spacing-4);
/* Navigation molecule */
}
.site-header__search {
/* Search molecule */
}
.site-header__user {
display: flex;
align-items: center;
gap: var(--spacing-3);
/* User menu molecule */
}
React Organism Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// ORGANISM: BlogPostCard
const BlogPostCard = ({ post }) => {
return (
<article className="blog-post-card">
{/* Atom: Image */}
<img
src={post.coverImage}
alt={post.title}
className="blog-post-card__image"
/>
{/* Molecule: Post Meta */}
<div className="blog-post-card__meta">
<span className="category-badge">{post.category}</span>
<time dateTime={post.date}>{formatDate(post.date)}</time>
</div>
{/* Atoms: Title & Description */}
<h2 className="blog-post-card__title">{post.title}</h2>
<p className="blog-post-card__excerpt">{post.excerpt}</p>
{/* Molecule: Author Info */}
<div className="blog-post-card__author">
<img src={post.author.avatar} alt={post.author.name} />
<span>{post.author.name}</span>
</div>
{/* Atom: CTA Button */}
<button className="btn btn--primary">Read More</button>
</article>
);
};
Stage 4: Templates
Definition: Page-level objects that place organisms into a layout. Focus on content structure, not actual content. Often start as wireframes.
Examples:
- Blog post template (header + sidebar + content area + comments)
- Dashboard template (sidebar + main grid + widgets)
- Login template (centered form on branded background)
Template Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!-- TEMPLATE: Blog Post Layout -->
<div class="template-blog-post">
<!-- Organism: Header -->
<header class="template-blog-post__header">
[Header Organism Placeholder]
</header>
<div class="template-blog-post__container">
<!-- Main content area -->
<main class="template-blog-post__main">
<!-- Article organism placeholder -->
<article class="article-content">
<h1>[Article Title]</h1>
<div class="article-meta">[Author] ⢠[Date] ⢠[Read Time]</div>
<div class="article-body">
[Article Content Lorem Ipsum...]
</div>
</article>
<!-- Comments organism placeholder -->
<section class="comments-section">
<h2>[X Comments]</h2>
[Comment Thread Organism]
</section>
</main>
<!-- Sidebar -->
<aside class="template-blog-post__sidebar">
<!-- Related posts organism -->
<div class="related-posts">
<h3>[Related Posts]</h3>
[Post Cards...]
</div>
<!-- Author bio organism -->
<div class="author-bio">
[Author Card]
</div>
</aside>
</div>
<!-- Organism: Footer -->
<footer class="template-blog-post__footer">
[Footer Organism Placeholder]
</footer>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.template-blog-post {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.template-blog-post__header {
/* Sticky header */
position: sticky;
top: 0;
z-index: var(--z-sticky);
}
.template-blog-post__container {
flex: 1;
display: grid;
grid-template-columns: 1fr 300px; /* Main + sidebar */
gap: var(--spacing-8);
max-width: var(--container-6xl);
margin: 0 auto;
padding: var(--spacing-8);
}
.template-blog-post__main {
/* Main content column */
}
.template-blog-post__sidebar {
/* Sidebar column */
}
.template-blog-post__footer {
/* Site footer */
}
/* Responsive: Stack on mobile */
@media (max-width: 768px) {
.template-blog-post__container {
grid-template-columns: 1fr;
}
}
Templates Focus on:
- Layout structure
- Content areas and proportions
- Responsive behavior
- Placeholder content
Stage 5: Pages
Definition: Specific instances of templates with real, representative content. This is the final UI users see.
Page vs. Template:
- Template: âBlog post layout with placeholder contentâ
- Page: âHow to Build Design Systemsâ actual article with real text, images, comments
Why Pages Matter:
- Test System Resilience: Does layout break with long titles? Short descriptions? No author image?
- Reveal Edge Cases: What if comment has no replies? What if article has 50 tags?
- Stakeholder Review: Clients/teams naturally focus on pages (concrete) rather than atoms (abstract)
Page Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// PAGE: Specific Blog Post
function BlogPostPage_DesignSystemsGuide() {
const post = {
title: "Design Systems Demystified: The Complete Technical Guide",
subtitle: "Master design tokens, Gestalt principles, and Atomic Design",
author: {
name: "Alex Chen",
role: "Engineering Team",
avatar: "/avatars/alex-chen.jpg"
},
date: "2024-03-15T10:00:00Z",
readTime: "25 min read",
category: "Frontend Development",
tags: ["Design Systems", "CSS", "React", "Atomic Design"],
coverImage: "/images/design-systems-banner.jpg",
content: `
<p>When you build enterprise applicationsâplatforms with authentication,
blogging, comments, real-time notifications...</p>
<!-- Full actual content -->
`,
comments: [
{
id: "1",
author: "Sarah Martinez",
avatar: "/avatars/sarah.jpg",
content: "This is exactly what I needed! The Gestalt principles...",
timestamp: "2024-03-15T11:30:00Z",
likes: 12,
replies: [
{
id: "2",
author: "Alex Chen",
role: "Author",
content: "Glad it helped! Let me know if...",
timestamp: "2024-03-15T12:00:00Z"
}
]
}
// More real comments...
],
relatedPosts: [
{
title: "Building Accessible Components",
excerpt: "WCAG 2.1 standards explained...",
slug: "accessible-components"
}
// More related posts...
]
};
return (
<BlogPostTemplate post={post} />
);
}
Testing with Pages:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Test: What if title is extremely long?
const edgeCase1 = {
title: "Understanding the Comprehensive Implementation of Enterprise-Grade Design Systems in Modern Full-Stack Web Applications with React, TypeScript, and Tailwind CSS",
// Does layout break?
};
// Test: What if there are no comments?
const edgeCase2 = {
comments: [],
// Does empty state show correctly?
};
// Test: What if author has no avatar?
const edgeCase3 = {
author: {
name: "John Doe",
avatar: null // Fallback to initials?
}
};
4.2 The Power of Atomic Design: Traversing Between Abstract and Concrete
Brad Frostâs Key Insight:
âOne of the biggest advantages atomic design provides is the ability to quickly traverse between abstract and concrete.â
What this means:
1
2
3
4
5
6
ABSTRACT (Atoms)
â
Can zoom out to see system-wide patterns
Can zoom in to fix specific implementation
â
CONCRETE (Pages)
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Spot a problem on a page
Page: "Login button looks wrong on mobile"
// Trace to organism
Organism: LoginForm component
// Trace to molecule
Molecule: Form actions group
// Trace to atom
Atom: Primary button
// Fix at atom level
.btn-primary {
/* Add min-width for mobile */
min-width: 120px;
}
// Fix automatically propagates up
Atom â Molecule â Organism â Template â ALL Pages
// Every button in every form on every page updates
Part 5: Building the TechHub Enterprise Platform
Letâs apply everything weâve learned by building a complete enterprise platform with authentication, blogging, comments, notifications, and project management.
5.1 System Architecture Overview
graph TB
subgraph "Design Foundation"
A[Design Tokens<br/>CSS Variables]
B[Gestalt Principles<br/>Cognitive Psychology]
end
subgraph "Atomic Design System"
C[Atoms<br/>Button, Input, Label]
D[Molecules<br/>Form Field, Search Bar]
E[Organisms<br/>Header, Comment Thread]
F[Templates<br/>Layouts & Structure]
G[Pages<br/>Final UI]
end
subgraph "Features"
H[Authentication]
I[Blog Engine]
J[Comment System]
K[Notifications]
L[Project Management]
end
A --> C
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
G --> I
G --> J
G --> K
G --> L
style A fill:#fff9c4
style B fill:#c8e6c9
style C fill:#b3e5fc
style G fill:#f8bbd0
5.2 Component Inventory (Atomic Breakdown)
ATOMS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Button Atom
export const Button = ({
variant = 'primary',
size = 'md',
children,
...props
}) => {
return (
<button
className={`btn btn--${variant} btn--${size}`}
{...props}
>
{children}
</button>
);
};
// Input Atom
export const Input = ({
type = 'text',
...props
}) => {
return (
<input
className="input"
type={type}
{...props}
/>
);
};
// Label Atom
export const Label = ({ children, htmlFor }) => {
return (
<label className="label" htmlFor={htmlFor}>
{children}
</label>
);
};
// Avatar Atom
export const Avatar = ({ src, alt, size = 'md', fallback }) => {
const [imgError, setImgError] = useState(false);
if (imgError || !src) {
return (
<div className={`avatar avatar--${size} avatar--fallback`}>
{fallback}
</div>
);
}
return (
<img
src={src}
alt={alt}
className={`avatar avatar--${size}`}
onError={() => setImgError(true)}
/>
);
};
// Badge Atom
export const Badge = ({ children, variant = 'default' }) => {
return (
<span className={`badge badge--${variant}`}>
{children}
</span>
);
};
MOLECULES
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Form Field Molecule (Label + Input + Helper/Error)
export const FormField = ({
label,
id,
error,
helperText,
required,
...inputProps
}) => {
return (
<div className="form-field">
<Label htmlFor={id}>
{label}
{required && <span className="required-indicator">*</span>}
</Label>
<Input
id={id}
aria-invalid={error ? 'true' : 'false'}
aria-describedby={error ? `${id}-error` : helperText ? `${id}-helper` : undefined}
{...inputProps}
/>
{error && (
<span id={`${id}-error`} className="form-field__error" role="alert">
{error}
</span>
)}
{!error && helperText && (
<span id={`${id}-helper`} className="form-field__helper">
{helperText}
</span>
)}
</div>
);
};
// User Badge Molecule (Avatar + Name + Role)
export const UserBadge = ({ user }) => {
return (
<div className="user-badge">
<Avatar
src={user.avatar}
alt={user.name}
fallback={user.name.charAt(0)}
/>
<div className="user-badge__info">
<span className="user-badge__name">{user.name}</span>
{user.role && (
<span className="user-badge__role">{user.role}</span>
)}
</div>
</div>
);
};
// Notification Card Molecule
export const NotificationCard = ({ notification, onDismiss }) => {
const icons = {
success: 'â',
error: 'â',
warning: 'â ',
info: 'âš'
};
return (
<div className={`notification notification--${notification.type}`}>
<span className="notification__icon">
{icons[notification.type]}
</span>
<div className="notification__content">
<h4 className="notification__title">{notification.title}</h4>
{notification.message && (
<p className="notification__message">{notification.message}</p>
)}
</div>
<button
className="notification__close"
onClick={onDismiss}
aria-label="Dismiss notification"
>
Ă
</button>
</div>
);
};
ORGANISMS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Comment Organism (Complex, recursive structure)
export const Comment = ({
comment,
depth = 0,
onReply,
onLike,
onReport
}) => {
const [showReplyForm, setShowReplyForm] = useState(false);
const maxDepth = 3;
return (
<div className={`comment ${depth > 0 ? 'comment--nested' : ''}`}>
<div className="comment__main">
{/* Avatar Atom */}
<Avatar
src={comment.author.avatar}
alt={comment.author.name}
size="md"
fallback={comment.author.name.charAt(0)}
/>
<div className="comment__content">
{/* Header with author info */}
<div className="comment__header">
<span className="comment__author">{comment.author.name}</span>
{comment.authorRole && (
<Badge variant={comment.authorRole.toLowerCase()}>
{comment.authorRole}
</Badge>
)}
<time className="comment__timestamp">
{formatDistanceToNow(new Date(comment.timestamp))} ago
</time>
</div>
{/* Comment text */}
<div className="comment__body">
<p>{comment.content}</p>
</div>
{/* Actions */}
<div className="comment__actions">
<button
className={`comment__action ${comment.isLiked ? 'active' : ''}`}
onClick={() => onLike(comment.id)}
>
⼠{comment.likes > 0 ? comment.likes : 'Like'}
</button>
{depth < maxDepth && (
<button
className="comment__action"
onClick={() => setShowReplyForm(!showReplyForm)}
>
Reply
</button>
)}
<button
className="comment__action comment__action--danger"
onClick={() => onReport(comment.id)}
>
Report
</button>
</div>
{/* Reply form */}
{showReplyForm && (
<div className="comment__reply-form">
<CommentForm
onSubmit={(data) => {
onReply(comment.id, data);
setShowReplyForm(false);
}}
onCancel={() => setShowReplyForm(false)}
placeholder={`Reply to ${comment.author.name}...`}
/>
</div>
)}
</div>
</div>
{/* Recursive nested replies */}
{comment.replies && comment.replies.length > 0 && (
<div className="comment__replies">
{comment.replies.map(reply => (
<Comment
key={reply.id}
comment={reply}
depth={depth + 1}
onReply={onReply}
onLike={onLike}
onReport={onReport}
/>
))}
</div>
)}
</div>
);
};
// Header Organism (Site navigation)
export const SiteHeader = ({ user, notifications }) => {
const [showNotifications, setShowNotifications] = useState(false);
const [showUserMenu, setShowUserMenu] = useState(false);
const unreadCount = notifications.filter(n => !n.read).length;
return (
<header className="site-header">
{/* Logo */}
<div className="site-header__logo">
<Link to="/">
<img src="/logo.svg" alt="TechHub" />
</Link>
</div>
{/* Primary Navigation */}
<nav className="site-header__nav">
<NavLink to="/dashboard" className="nav-link">Dashboard</NavLink>
<NavLink to="/blog" className="nav-link">Blog</NavLink>
<NavLink to="/projects" className="nav-link">Projects</NavLink>
</nav>
{/* Search Bar Molecule */}
<SearchBar className="site-header__search" />
{/* User Actions */}
<div className="site-header__actions">
{/* Notifications */}
<div className="notification-dropdown">
<button
className="icon-button"
onClick={() => setShowNotifications(!showNotifications)}
aria-label={`Notifications (${unreadCount} unread)`}
>
đ
{unreadCount > 0 && (
<span className="badge badge--notification">{unreadCount}</span>
)}
</button>
{showNotifications && (
<div className="dropdown-menu">
<h3>Notifications</h3>
{notifications.map(notification => (
<NotificationCard key={notification.id} notification={notification} />
))}
</div>
)}
</div>
{/* User Menu */}
<div className="user-menu-dropdown">
<button
className="user-menu-trigger"
onClick={() => setShowUserMenu(!showUserMenu)}
>
<UserBadge user={user} />
</button>
{showUserMenu && (
<div className="dropdown-menu">
<Link to="/profile">Profile</Link>
<Link to="/settings">Settings</Link>
<button onClick={handleLogout}>Logout</button>
</div>
)}
</div>
</div>
</header>
);
};
5.3 Complete Feature: Authentication Flow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// TEMPLATE: Authentication Layout
export const AuthTemplate = ({ children, title, subtitle }) => {
return (
<div className="auth-template">
{/* Background with gradient */}
<div className="auth-template__background" />
<div className="auth-template__container">
{/* Logo */}
<img src="/logo.svg" alt="TechHub" className="auth-template__logo" />
{/* Title */}
<h1 className="auth-template__title">{title}</h1>
{subtitle && (
<p className="auth-template__subtitle">{subtitle}</p>
)}
{/* Content (Form) */}
<div className="auth-template__content">
{children}
</div}
</div>
</div>
);
};
// PAGE: Login
export function LoginPage() {
const navigate = useNavigate();
const [formData, setFormData] = useState({ email: '', password: '' });
const [errors, setErrors] = useState({});
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
// Validation
const newErrors = {};
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = 'Please enter a valid email address';
}
if (!formData.password) {
newErrors.password = 'Password is required';
} else if (formData.password.length < 8) {
newErrors.password = 'Password must be at least 8 characters';
}
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
// Submit
setIsLoading(true);
try {
await login(formData);
navigate('/dashboard');
} catch (error) {
setErrors({ form: error.message });
} finally {
setIsLoading(false);
}
};
return (
<AuthTemplate
title="Welcome Back to TechHub"
subtitle="Sign in to access your dashboard"
>
<form onSubmit={handleSubmit} className="auth-form">
{/* Form-level error */}
{errors.form && (
<NotificationCard
notification=
/>
)}
{/* Email Field Molecule */}
<FormField
label="Email Address"
id="email"
type="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
error={errors.email}
helperText="We'll never share your email"
required
/>
{/* Password Field Molecule */}
<FormField
label="Password"
id="password"
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
error={errors.password}
required
/>
{/* Remember Me + Forgot Password */}
<div className="auth-form__options">
<label className="checkbox">
<input type="checkbox" />
<span>Remember me</span>
</label>
<Link to="/forgot-password" className="link">
Forgot password?
</Link>
</div>
{/* Submit Button Atom */}
<Button
type="submit"
variant="primary"
size="lg"
disabled={isLoading}
fullWidth
>
{isLoading ? 'Signing in...' : 'Sign In'}
</Button>
</form>
{/* Sign up link */}
<p className="auth-template__footer">
Don't have an account? <Link to="/signup">Sign up</Link>
</p>
</AuthTemplate>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/* AUTH TEMPLATE STYLES */
.auth-template {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.auth-template__background {
position: absolute;
inset: 0;
background: linear-gradient(
135deg,
var(--color-primary-700) 0%,
var(--color-primary-500) 100%
);
z-index: 0;
}
.auth-template__container {
position: relative;
z-index: 1;
width: 100%;
max-width: 440px;
padding: var(--spacing-8);
background: var(--color-gray-50);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-2xl);
}
.auth-template__logo {
display: block;
width: 64px;
height: 64px;
margin: 0 auto var(--spacing-6);
}
.auth-template__title {
font-size: var(--text-3xl);
font-weight: var(--font-bold);
text-align: center;
color: var(--color-gray-900);
margin-bottom: var(--spacing-2);
}
.auth-template__subtitle {
font-size: var(--text-base);
text-align: center;
color: var(--color-gray-700);
margin-bottom: var(--spacing-8);
}
.auth-form {
display: flex;
flex-direction: column;
gap: var(--spacing-6);
}
.auth-form__options {
display: flex;
justify-content: space-between;
align-items: center;
font-size: var(--text-sm);
}
.auth-template__footer {
text-align: center;
margin-top: var(--spacing-6);
font-size: var(--text-sm);
color: var(--color-gray-700);
}
Part 6: Accessibility & Inclusive Design (WCAG 2.1/2.2 Standards)
Accessibility isnât optionalâitâs a fundamental requirement. WCAG (Web Content Accessibility Guidelines) provides testable criteria for accessible interfaces.
6.1 WCAG Contrast Requirements (Precise Standards)
Level AA (Minimum Legal Requirement - Most Jurisdictions)
Normal Text:
- Requirement: 4.5:1 minimum contrast ratio
- Definition: Text smaller than 18pt (24px) or smaller than 14pt bold (18.66px bold)
Large Text:
- Requirement: 3:1 minimum contrast ratio
- Definition: Text 18pt (24px) or larger, OR 14pt bold (18.66px bold) or larger
UI Components (WCAG 2.1 Addition):
- Requirement: 3:1 minimum contrast ratio
- Applies to: Form inputs, buttons, focus indicators, icons
- Against: Adjacent colors
Level AAA (Enhanced - Recommended)
Normal Text: 7:1 minimum Large Text: 4.5:1 minimum
Testing Tools:
1
2
3
4
5
6
7
# Install WCAG contrast checker
npm install wcag-contrast
# Or use online tools:
# - WebAIM Contrast Checker
# - Accessible Colors
# - Stark (Figma plugin)
Implementation Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* â PASSES AA for normal text */
.text-on-white {
color: var(--color-gray-900); /* #1A202C */
background: var(--color-gray-50); /* #FFFFFF */
/* Contrast: 16.1:1 (far exceeds 4.5:1) */
}
/* â PASSES AA for large text */
.large-text-on-primary {
font-size: var(--text-2xl); /* 24px = large text */
color: var(--color-gray-50);
background: var(--color-primary-600);
/* Contrast: 4.8:1 (exceeds 3:1 minimum) */
}
/* â FAILS AA */
.light-gray-text {
color: #999999; /* Light gray */
background: #FFFFFF;
/* Contrast: 2.8:1 (below 4.5:1 minimum) */
}
/* â FIX: Darken text */
.accessible-gray-text {
color: var(--color-gray-700); /* #4A5568 */
background: var(--color-gray-50);
/* Contrast: 10.7:1 (passes AAA!) */
}
6.2 Keyboard Navigation Requirements
All interactive elements must be:
- Focusable via Tab key
- Activatable via Enter or Space
- Visibly focused with clear indicator
Focus Indicator Standards:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/* WCAG 2.2 Enhanced Focus Indicator */
:focus-visible {
outline: 2px solid var(--color-primary-500);
outline-offset: 2px;
/* Contrast: 3:1 minimum against background */
}
/* Remove default outline (only when replacing with custom) */
:focus:not(:focus-visible) {
outline: none;
}
/* Button focus */
.btn:focus-visible {
outline: 2px solid var(--color-primary-500);
outline-offset: 2px;
box-shadow: 0 0 0 4px rgba(49, 130, 206, 0.2);
/* Multiple indicators = better visibility */
}
/* Input focus */
.input:focus {
border-color: var(--color-primary-500);
box-shadow: 0 0 0 3px rgba(49, 130, 206, 0.1);
/* Focus ring + border color change */
}
Keyboard Navigation Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Modal Dialog with Keyboard Navigation
export function Modal({ isOpen, onClose, children }) {
const modalRef = useRef(null);
// Trap focus inside modal
useEffect(() => {
if (!isOpen) return;
const focusableElements = modalRef.current.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
// Focus first element when opened
firstElement?.focus();
// Handle Tab key
const handleTabKey = (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
// Shift+Tab: Going backwards
if (document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
}
} else {
// Tab: Going forwards
if (document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
};
// Handle Escape key
const handleEscapeKey = (e) => {
if (e.key === 'Escape') {
onClose();
}
};
document.addEventListener('keydown', handleTabKey);
document.addEventListener('keydown', handleEscapeKey);
return () => {
document.removeEventListener('keydown', handleTabKey);
document.removeEventListener('keydown', handleEscapeKey);
};
}, [isOpen, onClose]);
if (!isOpen) return null;
return (
<div className="modal-overlay" onClick={onClose}>
<div
ref={modalRef}
className="modal"
role="dialog"
aria-modal="true"
onClick={(e) => e.stopPropagation()}
>
{children}
</div>
</div>
);
}
6.3 Screen Reader Support (ARIA)
Semantic HTML First:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- â GOOD: Semantic HTML -->
<nav>
<ul>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
<!-- â BAD: Div soup -->
<div class="nav">
<div class="nav-item" onclick="navigate('/dashboard')">Dashboard</div>
<div class="nav-item" onclick="navigate('/blog')">Blog</div>
</div>
ARIA When Semantic HTML Isnât Enough:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Dropdown Menu with ARIA
export function Dropdown({ trigger, items }) {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);
return (
<div ref={dropdownRef} className="dropdown">
{/* Trigger button */}
<button
className="dropdown__trigger"
aria-haspopup="true"
aria-expanded={isOpen}
onClick={() => setIsOpen(!isOpen)}
>
{trigger}
</button>
{/* Dropdown menu */}
{isOpen && (
<ul
className="dropdown__menu"
role="menu"
aria-orientation="vertical"
>
{items.map((item, index) => (
<li key={index} role="none">
<button
role="menuitem"
onClick={() => {
item.onClick();
setIsOpen(false);
}}
>
{item.label}
</button>
</li>
))}
</ul>
)}
</div>
);
}
// Form with Error Announcements
export function FormField({ label, id, error, ...props }) {
return (
<div className="form-field">
<label htmlFor={id}>{label}</label>
<input
id={id}
aria-invalid={error ? 'true' : 'false'}
aria-describedby={error ? `${id}-error` : undefined}
{...props}
/>
{error && (
<span
id={`${id}-error`}
className="form-field__error"
role="alert"
aria-live="polite"
>
{error}
</span>
)}
</div>
);
}
// Loading State Announcement
export function LoadingButton({ isLoading, children, ...props }) {
return (
<button
{...props}
aria-busy={isLoading}
disabled={isLoading}
>
{isLoading && (
<span className="spinner" aria-hidden="true" />
)}
<span className={isLoading ? 'visually-hidden' : undefined}>
{children}
</span>
{isLoading && (
<span aria-live="polite" aria-atomic="true">
Loading...
</span>
)}
</button>
);
}
6.4 Accessibility Checklist (Per Component)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
## Component Accessibility Checklist
Before marking a component "done":
### Keyboard
- [ ] Focusable if interactive (Tab reaches it)
- [ ] Activatable via Enter/Space
- [ ] Focus indicator visible (2px outline, 2px offset minimum)
- [ ] Tab order logical
- [ ] Escape closes dialogs/dropdowns
- [ ] Arrow keys navigate within component (where applicable)
### Screen Readers
- [ ] Semantic HTML used (`<button>`, `<nav>`, `<main>`, etc.)
- [ ] ARIA roles only when semantic HTML unavailable
- [ ] ARIA labels on icon-only buttons (`aria-label`)
- [ ] Form inputs have associated `<label>` (via `htmlFor`)
- [ ] Errors linked to inputs (`aria-describedby`)
- [ ] Status changes announced (`aria-live`)
- [ ] Hidden decorative elements (`aria-hidden="true"`)
### Color & Contrast
- [ ] Text contrast ⼠4.5:1 (normal) or ⼠3:1 (large)
- [ ] UI component contrast ⼠3:1 vs adjacent colors
- [ ] Focus indicator contrast ⼠3:1 vs background
- [ ] Information not conveyed by color alone
- [ ] Icons paired with text labels
### Visual & Motion
- [ ] Text resizable to 200% without breaking layout
- [ ] Component works without CSS (progressive enhancement)
- [ ] Animations respect `prefers-reduced-motion`
- [ ] No flashing content (â¤3 times/second)
### Testing
- [ ] Keyboard-only navigation tested
- [ ] Screen reader tested (NVDA/JAWS/VoiceOver)
- [ ] 200% zoom tested
- [ ] High contrast mode tested
- [ ] Automated tests pass (axe-core/Pa11y)
Automated Testing Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Using jest-axe for accessibility testing
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('Button component has no accessibility violations', async () => {
const { container } = render(
<Button variant="primary">Click me</Button>
);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
test('Form field announces errors to screen readers', async () => {
const { container } = render(
<FormField
label="Email"
id="email"
error="Please enter a valid email"
/>
);
const results = await axe(container);
expect(results).toHaveNoViolations();
// Check error is linked to input
const input = container.querySelector('#email');
const errorId = input.getAttribute('aria-describedby');
expect(container.querySelector(`#${errorId}`)).toHaveTextContent(
'Please enter a valid email'
);
});
Part 7: Documentation & Governance
7.1 Component Documentation Template
Every component needs comprehensive documentation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Button Component
## Overview
The Button component triggers actions or navigation. It comes in multiple variants to communicate hierarchy and intent.
## Atomic Classification
**Type:** Atom
**Category:** Interactive Element
**Dependencies:** None (base component)
## When to Use
### â Use buttons for:
- Primary actions that change state (Submit, Save, Delete)
- Triggering operations (Send Email, Export Data)
- Opening modals or dialogs
- Form submissions
### â Don't use buttons for:
- Navigation between pages â use `<Link>` component
- Opening external URLs â use `<a>` tag
- Purely decorative elements
## Variants
### Primary
**Purpose:** Main call-to-action
**Rule:** Maximum ONE per visible screen section
**Examples:** "Sign In", "Publish Post", "Create Project"
```jsx
<Button variant="primary">Sign In</Button>
```
### Secondary
**Purpose:** Alternative or less critical actions
**Examples:** "Cancel", "Go Back", "Save Draft"
```jsx
<Button variant="secondary">Cancel</Button>
```
### Danger
**Purpose:** Destructive actions that cannot be easily undone
**Examples:** "Delete Account", "Remove Post", "Revoke Access"
```jsx
<Button variant="danger">Delete Account</Button>
```
### Ghost
**Purpose:** Tertiary actions, low visual weight
**Examples:** "View Details", "Learn More", "Skip"
```jsx
<Button variant="ghost">View Details</Button>
```
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `variant` | `'primary' \| 'secondary' \| 'danger' \| 'ghost'` | `'primary'` | Visual style variant |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
| `disabled` | `boolean` | `false` | Disables the button |
| `loading` | `boolean` | `false` | Shows loading spinner |
| `fullWidth` | `boolean` | `false` | Makes button full width |
| `icon` | `ReactNode` | `undefined` | Optional icon element |
| `onClick` | `function` | - | Click event handler |
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML button type |
## Usage Examples
```jsx
// Basic primary button
<Button variant="primary" onClick={handleSubmit}>
Submit Form
</Button>
// With loading state
<Button variant="primary" loading={isSubmitting}>
{isSubmitting ? 'Creating...' : 'Create Account'}
</Button>
// With icon
<Button variant="primary" icon={<PlusIcon />}>
Add New
</Button>
// Full width
<Button variant="primary" fullWidth>
Continue
</Button>
// Disabled state
<Button variant="primary" disabled={!isFormValid}>
Submit
</Button>
```
## Accessibility
### Keyboard
- **Focusable:** Yes (Tab key)
- **Activatable:** Enter or Space key
- **Focus Indicator:** 2px blue outline with 2px offset
### Screen Readers
- Button label announced clearly
- Loading state announced via `aria-busy="true"`
- Disabled state announced automatically
### Color Contrast
- **Primary:** 7.2:1 (Exceeds WCAG AAA)
- **Secondary:** 4.8:1 (Exceeds WCAG AA)
- **Danger:** 6.1:1 (Exceeds WCAG AAA)
- **Ghost:** 4.5:1 (Meets WCAG AA)
### Focus Indicator
- Contrast ratio: 3.5:1 against background
- Visible on all variants
- 2px thickness, 2px offset
## Design Tokens Used
```css
/* Primary variant */
--button-primary-bg: var(--color-primary-600);
--button-primary-text: var(--color-gray-50);
--button-primary-hover: var(--color-primary-700);
/* Spacing */
--button-padding-sm: var(--spacing-2) var(--spacing-3);
--button-padding-md: var(--spacing-3) var(--spacing-4);
--button-padding-lg: var(--spacing-4) var(--spacing-6);
/* Typography */
--button-font-size: var(--text-base);
--button-font-weight: var(--font-semibold);
/* Border radius */
--button-radius: var(--radius-md);
/* Shadows */
--button-shadow: var(--shadow-sm);
--button-shadow-hover: var(--shadow-md);
```
## Figma Component
**Library:** TechHub Design System
**Component:** `Button/Primary`, `Button/Secondary`, etc.
**Variants:** Size (sm, md, lg), State (default, hover, active, disabled, loading)
## Related Components
- **IconButton:** For icon-only actions
- **Link:** For navigation
- **ButtonGroup:** For multiple related buttons
## Changelog
**v3.0.0** - Added `loading` prop with spinner animation
**v2.1.0** - Added `icon` prop support
**v2.0.0** - Redesigned with new design tokens, improved accessibility
**v1.0.0** - Initial release
7.2 Contribution Guidelines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# Contributing to TechHub Design System
## Before You Start
1. **Search first:** Check if component already exists
2. **Ask in Slack:** Post in #design-system channel
3. **Consider composition:** Can existing components be combined?
## Proposal Process
### Step 1: Create RFC (Request for Comments)
Use the RFC template:
```markdown
## Component Name
SearchableCombobox
## Problem Statement
Users need to filter long lists (500+ items) with search capability.
## Why Existing Components Don't Work
- Current Dropdown: No search functionality
- Current Input: No dropdown selection
- Current Select: Doesn't scale to large lists
## Use Cases
1. Country selector (195 options)
2. Technology tag selector (1000+ options)
3. User mention system (@username)
## Proposed API
\`\`\`jsx
<Combobox
items={countries}
onSelect={handleSelect}
searchable
placeholder="Select country..."
/>
\`\`\`
## Mockups
[Link to Figma prototype]
## Affected Teams
Frontend, Design, Accessibility
## Open Questions
- Virtualization for large lists?
- Multi-select variant needed?
Step 2: Design System Review
Weekly review meeting checks:
- Solves genuine, recurring problem
- Canât be achieved with existing components
- Follows design system principles
- Has documented use cases
Step 3: Build & Document
Designer Responsibilities:
- Create Figma component with all states
- Define design tokens used
- Document usage guidelines
- Provide accessibility specifications
- Create visual examples
Developer Responsibilities:
- Build component following coding standards
- Write PropTypes/TypeScript definitions
- Add Storybook stories
- Write unit tests (>80% coverage)
- Add integration tests
- Document props and usage
- Test accessibility (axe-core)
Step 4: Code Review Checklist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## Code Review Checklist
### Functionality
- [ ] Component works as documented
- [ ] All props work correctly
- [ ] No console errors or warnings
- [ ] Edge cases handled (empty states, long text, etc.)
### Code Quality
- [ ] Follows naming conventions
- [ ] No hardcoded values (uses design tokens)
- [ ] PropTypes/TypeScript types defined
- [ ] Proper error handling
- [ ] No unnecessary re-renders (React.memo where appropriate)
### Testing
- [ ] Unit tests pass
- [ ] Coverage >80%
- [ ] Integration tests for complex interactions
- [ ] Visual regression tests (Chromatic/Percy)
### Accessibility
- [ ] Keyboard navigation works
- [ ] Screen reader tested
- [ ] Focus management correct
- [ ] ARIA attributes appropriate
- [ ] Color contrast passes WCAG AA
- [ ] Automated tests pass (axe-core)
### Documentation
- [ ] Component documentation complete
- [ ] Props documented
- [ ] Usage examples provided
- [ ] Storybook stories added
- [ ] Changelog updated
### Design Review
- [ ] Matches Figma specification
- [ ] Uses correct design tokens
- [ ] Responsive behavior correct
- [ ] States (hover, active, disabled) implemented
Coding Standards
File Structure
1
2
3
4
5
6
7
8
components/
ComponentName/
ComponentName.jsx # Main component
ComponentName.module.css # Styles (CSS Modules)
ComponentName.test.jsx # Unit tests
ComponentName.stories.jsx # Storybook stories
index.js # Re-export
README.md # Documentation
Naming Conventions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Components: PascalCase
Button, SearchBar, UserProfile
// Props: camelCase
onClick, isDisabled, maxLength
// CSS classes: BEM
.component__element--modifier
// CSS variables: kebab-case
--color-primary-600, --spacing-md
// Files: Match component name
Button.jsx, Button.module.css
Component Template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React from 'react';
import PropTypes from 'prop-types';
import styles from './ComponentName.module.css';
/**
* Component description
*
* @component
* @example
* <ComponentName prop="value" />
*/
export const ComponentName = ({
prop1,
prop2,
children,
...restProps
}) => {
return (
<div className={styles.component} {...restProps}>
{children}
</div>
);
};
ComponentName.propTypes = {
/** Prop description */
prop1: PropTypes.string.isRequired,
/** Another prop */
prop2: PropTypes.bool,
/** Child elements */
children: PropTypes.node
};
ComponentName.defaultProps = {
prop2: false
};
export default ComponentName;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
### 7.3 Versioning Strategy
```markdown
# Design System Versioning
We follow **Semantic Versioning (SemVer)**: MAJOR.MINOR.PATCH
## Version Numbers
### MAJOR (3.x.x)
Breaking changes:
- Removed components
- Renamed props (breaking API)
- Changed design tokens names
- Removed CSS classes
**Migration guide required**
### MINOR (x.4.x)
New features (backwards compatible):
- New components
- New component variants
- Additional props (with defaults)
- New design tokens
**No migration needed**
### PATCH (x.x.1)
Bug fixes and documentation:
- Bug fixes
- Documentation updates
- Internal refactoring
- Performance improvements
**No changes required**
## Release Process
1. **Branch:** `release/v3.0.0`
2. **Update:** CHANGELOG.md
3. **Test:** Full test suite + manual QA
4. **Review:** Design + Engineering leads
5. **Tag:** `v3.0.0`
6. **Publish:** npm + Storybook
7. **Announce:** Slack + email
8. **Document:** Migration guide (if major)
## Changelog Format
```markdown
# Changelog
## [3.0.0] - 2024-03-15
### Breaking Changes
- **Button:** Removed `size="xs"` variant (use `size="sm"` instead)
- **Input:** Renamed `error` prop to `errorMessage` for consistency
- **Tokens:** Renamed `--color-brand` to `--color-primary-600`
### Added
- **SearchableCombobox:** New component for large filterable lists
- **Button:** Added `loading` prop with spinner animation
- **Tokens:** Added elevation scale (--shadow-xs through --shadow-2xl)
### Changed
- **Card:** Improved shadow on hover (--shadow-sm â --shadow-md)
- **FormField:** Error messages now use role="alert"
### Fixed
- **Dropdown:** Fixed keyboard navigation on nested menus
- **Modal:** Fixed focus trap when multiple modals open
### Deprecated
- **OldButton:** Use new `Button` component instead (will be removed in v4.0.0)
## [2.5.0] - 2024-02-01
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
---
## Part 8: Advanced Topics & Best Practices
### 8.1 Performance Optimization
```jsx
// Code Splitting (Lazy Loading)
import React, { lazy, Suspense } from 'react';
// Only load heavy components when needed
const CommentThread = lazy(() => import('./CommentThread'));
const RichTextEditor = lazy(() => import('./RichTextEditor'));
const DataVisualization = lazy(() => import('./DataVisualization'));
function BlogPost() {
return (
<article>
<h1>Post Title</h1>
<div className="content">...</div>
{/* Lazy load comments */}
<Suspense fallback={<LoadingSpinner />}>
<CommentThread postId="123" />
</Suspense>
</article>
);
}
// CSS Code Splitting
// Import only what you need
import './Button.module.css'; // â Component-scoped
// NOT: import './all-styles.css'; // â Everything at once
// Tree Shaking (Remove Unused Code)
// Named imports enable tree shaking
import { Button, Input } from '@techhub/design-system'; // â
// NOT: import * as DS from '@techhub/design-system'; // â
// Memoization
import React, { memo, useMemo, useCallback } from 'react';
// Prevent unnecessary re-renders
const ExpensiveComponent = memo(({ data }) => {
const processedData = useMemo(
() => heavyCalculation(data),
[data] // Only recalculate when data changes
);
return <div>{processedData}</div>;
});
// Prevent function recreation
function Parent() {
const handleClick = useCallback(() => {
// Handle click
}, []); // Function stable across renders
return <Child onClick={handleClick} />;
}
8.2 Responsive Design Patterns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/* Mobile-First Approach */
/* Base styles (mobile) */
.card {
padding: var(--spacing-4);
grid-template-columns: 1fr;
}
/* Tablet and up */
@media (min-width: 768px) {
.card {
padding: var(--spacing-6);
grid-template-columns: repeat(2, 1fr);
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.card {
padding: var(--spacing-8);
grid-template-columns: repeat(3, 1fr);
}
}
/* Container Queries (Modern Approach) */
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.widget {
padding: var(--spacing-4);
}
/* When sidebar is wide enough */
@container sidebar (min-width: 400px) {
.widget {
display: grid;
grid-template-columns: auto 1fr;
}
}
/* Responsive Typography */
:root {
--text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
/* Scales from 16px to 18px based on viewport */
}
8.3 Common Pitfalls & Solutions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
## Common Design System Mistakes
### â Mistake 1: Over-Engineering Too Early
**Problem:** Building 50 components before you have 5 pages
**Solution:** Start small
- Build components as you need them
- Extract patterns after you've used them 3+ times
- Resist premature abstraction
### â Mistake 2: Hardcoded Values Everywhere
**Problem:**
\`\`\`css
.button {
padding: 12px 16px; /* Hardcoded */
color: #2C5282; /* Hardcoded */
}
\`\`\`
**Solution:** Use tokens
\`\`\`css
.button {
padding: var(--spacing-3) var(--spacing-4);
color: var(--color-primary-600);
}
\`\`\`
### â Mistake 3: Inconsistent Naming
**Problem:**
- `Button`, `submit-button`, `BtnPrimary`, `button_secondary`
**Solution:** Pick one convention (PascalCase for components)
- `Button`, `SubmitButton`, `ButtonPrimary`, `ButtonSecondary`
### â Mistake 4: No Component Documentation
**Problem:** "How do I use this?"
**Solution:** Document everything
- Props and their types
- Usage examples
- When to use / when not to use
- Accessibility notes
### â Mistake 5: Ignoring Accessibility
**Problem:** Build first, accessibility later (never happens)
**Solution:** Accessibility from day 1
- Keyboard navigation
- Screen reader support
- Color contrast
- Focus indicators
Further Reading & Resources
To deepen your understanding of design systems and continue your learning journey, weâve curated authoritative resources organized by topic. Each resource has been selected for its practical value and alignment with the principles covered in this guide.
Foundation: Design System Philosophy & Structure
DesignSystems.com
Publisher: Figma What It Is: The definitive design systems publication featuring in-depth guides, case studies, and industry insights from leading practitioners. This is your go-to resource for understanding how companies like Spotify, Airbnb, and Adobe approach design systems at scale.
Why It Matters: Figmaâs design systems hub provides real-world perspectives from teams whoâve built and maintained systems in production. Youâll learn not just theory, but practical lessons from failures and successes across the industry.
Best For: Understanding the strategic and organizational aspects of design systems beyond just the technical implementation.
Color Theory & Application
Design Systems Color Guides
Focus: Color palette creation, accessibility compliance, semantic color systems
Key Topics:
- Building accessible color palettes that meet WCAG standards
- Creating semantic color tokens (success, warning, error, info)
- Brand color integration with UI requirements
- Color contrast testing methodologies
- Dark mode and theme switching strategies
Why Read This: Color is one of the first design decisions youâll make, and getting it wrong affects everything downstream. This guide walks you through creating color systems that are both beautiful and accessible, with practical examples of how to handle edge cases like brand colors that donât meet contrast requirements.
Applies to Document Sections: Part 1 (Visual Hierarchy - Principle 2), Part 3 (Design Tokens - Color System)
Typography Systems
Design Systems Typography Guides
Contributors: Dan Mall, Sebastiano Guerriero
Key Topics:
- Choosing typefaces for screen readability
- Creating modular type scales with mathematical ratios
- Font loading performance optimization
- Responsive typography strategies
- Canonical presets vs. semantic naming
Featured Approach: Dan Mallâs numeric preset systemâinstead of naming type styles âHeading 1â or âBody Large,â use neutral numbers (Type 1, Type 2, etc.) that can be mapped to any component. This prevents semantic confusion and makes systems more flexible.
Why Read This: Typography accounts for 85-90% of what users see on screen. This guide teaches you how to create harmonious type systems using CSS custom properties and modular scales, ensuring readability across devices while maintaining visual hierarchy.
Applies to Document Sections: Part 2 (Visual Hierarchy - Principle 4: Typography), Part 3 (Design Tokens - Typography Tokens)
Layout, Spacing & Grid Systems
Design Systems Space, Grids, and Layouts
Focus: Spatial systems, grid structures, responsive layouts
Key Topics:
- 8-point grid systems and why they matter
- Spacing token architecture
- 12-column grid vs. flexbox vs. CSS grid
- Responsive layout patterns
- Container queries and modern layout techniques
Why Read This: Spacing and grids create the invisible structure that makes interfaces feel organized. This guide explains how to create systematic spacing scales (like our 8pt grid) and when to use different layout methodologies.
Practical Value: Youâll learn why spacing-4 (16px) feels more natural than 15px, and how to create spacing systems that work harmoniously across breakpoints.
Applies to Document Sections: Part 2 (Visual Hierarchy - Principle 3: Whitespace, Principle 7: Alignment), Part 3 (Design Tokens - Spacing System)
Iconography & Visual Language
Design Systems Iconography Guide
Focus: Icon design, consistency, accessibility
Key Topics:
- Icon size and spacing standards
- Stroke width consistency
- Semantic vs. decorative icons
- Icon accessibility (ARIA labels, alt text)
- Building vs. buying icon libraries
Why Read This: Icons are visual atoms in your design system. Inconsistent icon styling (mixing outlined and filled icons, varying stroke weights) creates visual noise that undermines hierarchy.
Key Insight: This guide teaches you when icons need text labels (always for primary actions), when they can stand alone (common actions like search or close), and how to ensure theyâre accessible to screen readers.
Applies to Document Sections: Part 4 (Atomic Design - Atoms), Part 6 (Accessibility - Screen Reader Support)
Content Strategy & Microcopy
Guide to Content Strategy in Design Systems
Focus: Content patterns, microcopy, voice and tone
Key Topics:
- Standardizing button labels (Delete vs. Remove vs. Discard)
- Error message patterns and tone
- Empty state content guidelines
- Tooltip and help text strategies
- When to inject personality vs. stay neutral
Critical Question Answered: How do you decide between âDelete,â âRemove,â and âDiscardâ? This guide provides frameworks for making these content decisions systematically rather than case-by-case.
Why Read This: Technical teams often overlook content strategy, but inconsistent microcopy (âSign Inâ vs. âLog Inâ vs. âLoginâ) creates cognitive friction. This guide shows you how to document content patterns alongside visual components.
Practical Example: Should error messages say âWe couldnât process your requestâ or âYour request couldnât be processedâ? Learn how to define voice (first person vs. passive) at the system level.
Applies to Document Sections: Part 7 (Documentation & Governance - Component Documentation)
Utility-First CSS & Tailwind Approach
Tailwind CSS Plus
What It Is: Production-ready UI component library and templates built by the creators of Tailwind CSS
Key Topics:
- Utility-first CSS methodology
- Component composition with Tailwind
- Design token implementation via tailwind.config.js
- Pre-built component examples (500+ components)
- React/Next.js integration patterns
Philosophy: Instead of writing custom CSS for every component, compose interfaces using pre-defined utility classes. Design tokens are defined in configuration, generating thousands of utility classes automatically.
Critical Perspective: While this guide teaches token-based systems with CSS custom properties, Tailwind offers an alternative approach. Understanding both methodologies helps you choose the right tool for your context.
Comparison:
- CSS Custom Properties (this guide): Semantic naming, runtime theming, design-tool friendly
- Tailwind Utilities: Faster development, constraint-based, requires build step
When to Use Tailwind:
- Rapid prototyping with established constraints
- Teams comfortable with utility-first methodology
- Projects prioritizing development speed over design tool integration
When to Use Custom Properties:
- Complex theming requirements (multiple themes)
- Close designer-developer collaboration via Figma
- Need for runtime dynamic styling
Why Explore Both: Modern design systems increasingly use hybrid approachesâTailwind for rapid development, custom properties for dynamic theming.
Applies to Document Sections: Part 3 (Design Tokens), Part 8 (Advanced Topics - Alternative Approaches)
Practical Application Order
Recommended Reading Path for Beginners:
- Start Here: DesignSystems.com - Get the big picture
- Then: Color Guides - Build your palette
- Next: Typography Guides - Create your type scale
- After: Space & Grids - Establish spatial rhythm
- Then: Iconography - Standardize visual elements
- Finally: Content Strategy - Define your voice
- Explore: Tailwind CSS Plus - See alternative approaches
For Experienced Developers:
Start with Tailwind CSS Plus to understand utility-first approaches, then compare against the token-based methodology in this guide. Understanding both paradigms makes you a more versatile systems architect.
Additional Learning Resources
Books
- Atomic Design by Brad Frost - The foundational methodology
- Refactoring UI by Adam Wathan & Steve Schoger - Practical design decisions
- Design Systems Handbook by Marco Suarez, Jina Anne, Katie Sylor-Miller, Diana Mounter, Roy Stanfield
Documentation Systems
- Material Design 3 - Googleâs comprehensive design language
- Apple Human Interface Guidelines - Platform-specific design patterns
- Shopify Polaris - E-commerce-focused design system
- IBM Carbon - Enterprise design system with extensive code examples
Tools & Communities
- Figma Community - Thousands of design system files to study
- Design Systems Slack - Active community of practitioners
- Storybook - Component documentation and testing
- Style Dictionary - Design token transformation tool
Conclusion: Building Sustainable Design Systems
Key Takeaways
- Psychology First
- Gestalt principles explain why designs feel intuitive
- Cognitive load theory guides hierarchy decisions
- 50ms first impressions matterâmake them count
- Design Tokens Are Foundation
- Three-tier system (global â semantic â component)
- Single source of truth for all design decisions
- Enable theming, consistency, and scale
- Visual Hierarchy Is Science
- Eight principles: Size, Color, Whitespace, Typography, Position, Depth, Alignment, Repetition
- Material Design elevation system adds dimension
- F/Z patterns guide natural eye movement
- Atomic Design Provides Structure
- Atoms â Molecules â Organisms â Templates â Pages
- Traverse between abstract and concrete
- Focus on composition over categorization
- Accessibility Is Non-Negotiable
- WCAG AA minimum: 4.5:1 text, 3:1 UI components
- Keyboard navigation mandatory
- Screen readers need semantic HTML + ARIA
- Documentation Enables Scale
- Every component needs âwhen to useâ guidance
- Code examples reduce implementation time
- Accessibility standards baked in from start
- Governance Maintains Quality
- RFC process prevents duplication
- Code review ensures standards
- Semantic versioning communicates changes
Your Next Steps
Week 1: Study Existing Systems
- Analyze Material Design, Apple HIG, Shopify Polaris
- Identify their token systems, component hierarchies
- Notice how they apply Gestalt principles
Week 2: Audit a Real Product
- Pick any website (GitHub, Airbnb, Stripe)
- Extract their design tokens (colors, spacing, typography)
- Identify inconsistencies and missing patterns
Week 3: Build a Mini System
- Create 5 atoms (Button, Input, Label, Avatar, Badge)
- Combine into 3 molecules (FormField, UserCard, SearchBar)
- Build 1 organism (Header with navigation)
- Define 20 design tokens to support them
Week 4: Implement in Code
- Convert your Figma components to React/Vue
- Use CSS custom properties for tokens
- Add Storybook for documentation
- Write accessibility tests
Month 2: Scale Up
- Add more components as you need them
- Extract patterns after 3rd use (Rule of Three)
- Document everything
- Get feedback from other developers
Resources for Continued Learning
Books:
- Atomic Design by Brad Frost
- Refactoring UI by Adam Wathan & Steve Schoger
- The Design of Everyday Things by Don Norman
Online:
- Material Design Guidelines
- Apple Human Interface Guidelines
- Shopify Polaris
- Brad Frostâs Blog
- Nielsen Norman Group Articles
Tools:
- Design: Figma, Sketch
- Development: React, Vue, Svelte
- Documentation: Storybook, Docusaurus
- Testing: Jest, Testing Library, axe-core
- Accessibility: WAVE, Lighthouse, Stark
Appendix A: Complete Token Reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* Complete TechHub Design Token System v3.0 */
:root {
/* ============================================
COLOR SYSTEM
============================================ */
/* Primary Brand (Blue) */
--color-primary-50: #EBF8FF;
--color-primary-100: #BEE3F8;
--color-primary-200: #90CDF4;
--color-primary-300: #63B3ED;
--color-primary-400: #4299E1;
--color-primary-500: #3182CE;
--color-primary-600: #2C5282;
--color-primary-700: #1A365D;
--color-primary-800: #123456;
--color-primary-900: #0A2540;
/* Neutral Grays */
--color-gray-50: #FFFFFF;
--color-gray-100: #F7FAFC;
--color-gray-200: #EDF2F7;
--color-gray-300: #E2E8F0;
--color-gray-400: #CBD5E0;
--color-gray-500: #A0AEC0;
--color-gray-600: #718096;
--color-gray-700: #4A5568;
--color-gray-800: #2D3748;
--color-gray-900: #1A202C;
/* Semantic Status Colors */
--color-success: #38A169;
--color-success-light: #9AE6B4;
--color-success-dark: #276749;
--color-warning: #D69E2E;
--color-warning-light: #FAF089;
--color-warning-dark: #B7791F;
--color-error: #E53E3E;
--color-error-light: #FC8181;
--color-error-dark: #C53030;
--color-info: #3182CE;
--color-info-light: #90CDF4;
--color-info-dark: #2C5282;
/* ============================================
TYPOGRAPHY
============================================ */
/* Font Families */
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-serif: 'Georgia', 'Times New Roman', serif;
--font-mono: 'Fira Code', 'Courier New', Consolas, monospace;
/* Font Sizes (1.25 modular scale) */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--text-5xl: 3rem; /* 48px */
--text-6xl: 3.75rem; /* 60px */
/* Font Weights */
--font-regular: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
--font-extrabold: 800;
/* Line Heights */
--leading-none: 1;
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.75;
--leading-loose: 2;
/* Letter Spacing */
--tracking-tighter: -0.05em;
--tracking-tight: -0.025em;
--tracking-normal: 0;
--tracking-wide: 0.025em;
--tracking-wider: 0.05em;
--tracking-widest: 0.1em;
/* ============================================
SPACING (8pt grid)
============================================ */
--spacing-0: 0;
--spacing-px: 1px;
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
--spacing-5: 1.25rem; /* 20px */
--spacing-6: 1.5rem; /* 24px */
--spacing-8: 2rem; /* 32px */
--spacing-10: 2.5rem; /* 40px */
--spacing-12: 3rem; /* 48px */
--spacing-16: 4rem; /* 64px */
--spacing-20: 5rem; /* 80px */
--spacing-24: 6rem; /* 96px */
--spacing-32: 8rem; /* 128px */
/* ============================================
BORDERS
============================================ */
--border-width-0: 0;
--border-width-1: 1px;
--border-width-2: 2px;
--border-width-4: 4px;
--radius-none: 0;
--radius-sm: 0.125rem; /* 2px */
--radius-base: 0.25rem; /* 4px */
--radius-md: 0.5rem; /* 8px */
--radius-lg: 0.75rem; /* 12px */
--radius-xl: 1rem; /* 16px */
--radius-2xl: 1.5rem; /* 24px */
--radius-full: 9999px;
/* ============================================
SHADOWS (Elevation)
============================================ */
--shadow-none: none;
--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
--shadow-base: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
--shadow-md: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
--shadow-2xl: 0 30px 60px -15px rgba(0, 0, 0, 0.3);
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05);
/* ============================================
ANIMATION
============================================ */
--duration-75: 75ms;
--duration-100: 100ms;
--duration-150: 150ms;
--duration-200: 200ms;
--duration-300: 300ms;
--duration-500: 500ms;
--duration-700: 700ms;
--duration-1000: 1000ms;
--ease-linear: linear;
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
/* ============================================
Z-INDEX
============================================ */
--z-0: 0;
--z-10: 10;
--z-20: 20;
--z-30: 30;
--z-40: 40;
--z-50: 50;
--z-dropdown: 1000;
--z-sticky: 1020;
--z-fixed: 1030;
--z-modal-backdrop: 1040;
--z-modal: 1050;
--z-popover: 1060;
--z-tooltip: 1070;
}
Further Reading & Resources
Now that youâve built a solid foundation in design systems, these curated resources will help you deepen your expertise and stay current with industry best practices.
Essential Design System Foundations
đ DesignSystems.com
By Figma
A comprehensive publication covering the full spectrum of design systems workâfrom foundational principles to operational governance. Features in-depth articles on design-developer collaboration, component architecture, and real-world case studies from companies like Spotify and Credit Karma. Essential reading for understanding how industry-leading teams structure and maintain their systems at scale.
What youâll learn: Cross-functional collaboration patterns, scaling strategies, governance frameworks, and community-driven approaches to system building.
Recommended after: Completing Parts 1-4 of this guide (Psychology, Visual Hierarchy, Design Tokens, Atomic Design).
Design Foundation Guides (Study These in Order)
These specialized guides from DesignSystems.com dive deep into the core building blocks. Follow this recommended learning path:
1ď¸âŁ Space, Grids, and Layouts
Start here: Foundation of spatial systems
Master the principles behind spacing scales, grid systems (8pt, 12-column), and responsive layout patterns. This guide explains how to establish baseline grids that create visual rhythm and how column grids enable consistent layouts across breakpointsâthe spatial foundation everything else builds upon.
Core concepts covered:
- 8-point spacing systems (connects to Part 3.3 of this guide)
- 12-column grid architecture (connects to Part 2.1, Principle 7: Alignment)
- Responsive layout strategies
- Container queries and breakpoint management
Apply immediately to: Setting up your design token spacing scale and establishing grid systems for your first component library.
2ď¸âŁ Color Guides
Second priority: Color system architecture
Learn how to build accessible color palettes that scale from brand colors to semantic tokens. This guide covers color generation methodologies (tints/shades), semantic naming conventions, and ensuring WCAG compliance across your entire paletteânot just testing colors one-by-one.
Deep dives into:
- Building accessible color scales (connects to Part 6.1: WCAG Standards)
- Semantic color naming (connects to Part 3.2: Token Tier System)
- ColorBox and other palette generation tools
- Platform-specific color formats (iOS, Android, Web)
Key resource: Lyftâs Re-Approaching Color methodology for building accessible palettes at scale.
Apply immediately to: Expanding your design token color palette beyond basic brand colors to include comprehensive semantic and component-specific tokens.
3ď¸âŁ Typography Guides
Third step: Type system architecture
Comprehensive guidance on selecting typefaces, defining modular scales, establishing line heights and letter spacing, and creating responsive typography that adapts across devices. Goes beyond basic font choices to cover performance (web font loading), licensing, and fallback stacks.
Key topics:
- Modular typographic scales (connects to Part 2.1, Principle 1: Size & Scale)
- Line height and vertical rhythm (connects to Part 2.1, Principle 4)
- Responsive typography with
clamp()functions - Web font performance optimization
Apply immediately to: Refining your typographic scale and establishing comprehensive type tokens that account for different contexts (marketing vs. product, mobile vs. desktop).
4ď¸âŁ Iconography Guide
Fourth priority: Icon system structure
A complete framework for creating, organizing, naming, and using icons within design systems. Covers technical requirements (SVG optimization, accessibility, sizing), organizational strategies (categorization, naming conventions), and implementation patterns (icon components, dynamic coloring).
Essential for:
- SVG optimization and accessibility
- Icon naming conventions at scale (500+ icons)
- Implementation as React/Vue components
- Semantic vs. decorative icon usage (connects to Part 6.3: ARIA)
Apply immediately to: Building your first icon library with proper component wrappers, accessibility attributes (aria-hidden, aria-label), and consistent sizing tokens.
5ď¸âŁ Content Strategy in Design Systems
Advanced topic: Voice, tone, and microcopy
Often overlooked but critical: how to establish consistent voice, tone, and microcopy across components. Covers writing guidelines for button labels, error messages, empty states, and helper textâensuring your system communicates as consistently as it looks.
Covers:
- Voice and tone guidelines
- Component microcopy patterns (buttons, forms, notifications)
- Error message frameworks
- Internationalization (i18n) considerations
Apply immediately to: Documenting content patterns in your component library (e.g., âUse âSign Inâ not âLoginâ, use sentence case not title caseâ).
Advanced Implementation Resources
đ¨ Tailwind CSS Plus
Utility-first design system approach
While this guide teaches you to build systems from first principles, Tailwind represents an alternative philosophy: utility-first CSS. Studying Tailwindâs architecture teaches you how constraint-based systems work, how to design with composition over inheritance, and how modern build tools enable this approach.
Why study this:
- Constraint-based design (limited color/spacing options increase consistency)
- Utility class composition patterns
- JIT (Just-In-Time) compilation strategies
- Design token â CSS custom property â utility class pipeline
Best for: Understanding how opinionated frameworks enforce consistency and exploring whether a utility-first approach fits your teamâs workflow.
When to explore: After building your first token-based system and wanting to compare different architectural approaches.
How to Use These Resources Strategically
Beginner Path (Weeks 1-4):
- Complete Parts 1-5 of this guide (Psychology through TechHub Platform)
- Read Space, Grids, and Layouts guide â Implement 8pt spacing system
- Read Color guide â Expand to full semantic color palette
- Build 5 components using these foundations
Intermediate Path (Months 2-3):
- Read Typography guide â Refine type scale
- Read Iconography guide â Build icon component library
- Explore DesignSystems.com articles on governance and collaboration
- Implement contribution process from Part 7.2
Advanced Path (Ongoing):
- Read Content Strategy guide â Document voice and tone
- Study Tailwind Plus for alternative architectural patterns
- Follow DesignSystems.com for new articles (Schema conference talks)
- Contribute back to community (write about your learnings)
Staying Current
Subscribe to:
- DesignSystems.com Newsletter â Curated articles and conference talks
- Figma Design Systems Community â Open source system files to study
Annual Events:
- Schema by Figma â Design systems conference with talks archived on DesignSystems.com
- Clarity Conference â Design systems focused event
Weekly Reading:
- Browse new submissions on DesignSystems.com (updated regularly)
- Study component implementations from open-source systems (Material, Polaris, Carbon)
Remember: The best design system is the one your team actually uses. Start small, document everything, and iterate based on real usage patterns. These resources provide the deep expertise youâll grow intoânot everything at once.
Author: TechHub Engineering Team
Version: 2.0.0
Last Updated: May 2, 2026 License: MIT
Contributors: Design Systems Working Group
This comprehensive guide is part of the TechHub Engineering Blog series. For more technical deep-dives, visit techhub.dev/blog.
Special thanks to Brad Frost (Atomic Design), the Gestalt psychologists, Nielsen Norman Group, the W3C Accessibility Guidelines working group, and the Figma DesignSystems.com team for the foundational research that makes this guide possible.
