Design System
Design System
This document describes the Zudo Design System used in the Takazudo Modular project, including its architecture, spacing conventions, color system, and typography.
Token Preview: /dev/tokens/ — Visual reference of all available design tokens (colors, spacing, typography).
Design Philosophy
The Zudo Design System is built on three core strategies:
Tight Token Strategy
All Tailwind CSS defaults are disabled. Only the tokens defined in the Zudo Design System are available for use. This is achieved using Tailwind CSS v4’s Approach B: importing only tailwindcss/preflight and tailwindcss/utilities, skipping the default theme entirely. No wildcard resets are needed because the default theme is never loaded.
This ensures that:
- No default Tailwind utilities like
h-4,text-sm,bg-gray-500can be used - Only explicitly defined design tokens are available
- Design consistency is enforced at build time — invalid tokens cause build errors, not visual bugs
- Developers have a constrained vocabulary (e.g., 7 spacing steps per axis instead of 30+), preventing drift where different developers pick different values for the same purpose
Component-First Strategy
Since this project uses Astro (a component framework) with Tailwind CSS (a utility framework), all UI is expressed as components with utility classes. Custom CSS class names like .card or .btn-primary are never created for UI styling.
- Need a card? Create a
<Card>component with utility classes - Need a button variant? Use component props:
<Button variant="primary"> - Need a layout? Create a
<PageLayout>component
The component itself is the abstraction. Utility classes handle styling directly in the markup. No separate CSS files, no BEM naming, no CSS modules for UI components.
Exception: The design system itself defines custom utilities (via @utility) for patterns that can’t be expressed as single Tailwind utilities (text shadows, gradients, status badges). These live in sub-packages/design-system/utilities.css.
No CSS Modules
Do not use CSS modules (.module.css files). The component-first strategy with Tailwind utilities covers all standard styling needs, making CSS modules unnecessary.
For complex CSS that cannot be expressed as Tailwind utilities — such as keyframe animations, clip-paths, or intricate pseudo-element patterns — use plain CSS files with these conventions:
- Name the file descriptively (e.g.,
hamster-animation.css) - Prefix all class names with a unique component-specific prefix (e.g.,
.hamster-container,.hamster-wheel,.hamster-spoke) to avoid collisions - Import as a side effect in the component:
import './hamster-animation.css'
This keeps styling explicit and avoids the indirection that CSS modules introduce.
Three-Tier Color Architecture
Colors are organized into three tiers, each referencing only the tier above:
| Tier | Name | Purpose | Example |
|---|---|---|---|
| 1 | Palette | Raw color values in oklch color space | --zd-p0 through --zd-p15 |
| 2 | Semantic | What each color means in the design | --zd-semantic-bg, --zd-semantic-accent |
| 3 | Component | Scoped overrides for specific components | Status colors, alert backgrounds |
Components use semantic tokens. Semantic tokens point to palette colors. Palette holds the actual oklch values. This means changing a brand color updates everywhere — change --zd-semantic-accent to point to a different palette slot, and every accent-colored element updates.
Architecture
Source Files
The design system is a separate sub-package at sub-packages/design-system/ with three files:
| File | Purpose |
|---|---|
tokens.css | All --zd-* custom properties (palette, semantic colors, spacing, typography) |
theme.css | @theme block mapping --zd-* tokens to Tailwind theme variables |
utilities.css | Custom @utility definitions (text shadows, gradients, status badges) |
How It Works
/* tokens.css — Define raw values */
:root {
/* Tier 1: Palette */
--zd-p9: oklch(18% 0.01 50); /* background */
--zd-p5: oklch(65% 0.2 45); /* accent */
/* Tier 2: Semantic */
--zd-semantic-bg: var(--zd-p9);
--zd-semantic-accent: var(--zd-p5);
/* Spacing */
--zd-spacing-hgap-md: 40px;
}
/* theme.css — Map to Tailwind (Approach B, no resets needed) */
@theme {
--spacing-hgap-md: var(--zd-spacing-hgap-md);
--color-bg: var(--zd-semantic-bg);
--color-accent: var(--zd-semantic-accent);
}
Approach B means only tailwindcss/preflight and tailwindcss/utilities are imported — the default theme layer is never loaded. No --spacing-*: initial resets needed.
Using Design Tokens vs Arbitrary Values
1. Use Design Tokens First (Preferred)
Always try to use defined design tokens first:
// ✅ GOOD - Using design tokens
<div className="px-hgap-md py-vgap-sm bg-zd-black text-zd-white">
2. If No Token Matches
Option A: Consider Adding a Token
If this value will be reused or is semantically meaningful, add it to sub-packages/design-system/tokens.css and theme.css.
Option B: Use Arbitrary Values
Arbitrary values ARE allowed for one-off, specific cases:
// ✅ GOOD - Arbitrary values for specific needs
<div className="w-[85%] pt-[20px] px-[32px]">
<div className="max-w-[400px]">
When to Use Each
Use design tokens when:
- The value is reused across multiple components
- The value has semantic meaning (e.g., “standard button padding”)
- You want consistency across the design system
Use arbitrary values when:
- The value is unique to one specific component
- The value is mathematically calculated or component-specific
- Adding a token would create unnecessary abstraction
NEVER Use Numeric Tailwind Classes
Numeric classes like p-4, m-8, gap-2 are not available — the default Tailwind theme is not loaded:
// ❌ BAD - These don't exist (build error)
<div className="p-4 m-8 gap-2">
// ✅ GOOD - Use design tokens
<div className="p-vgap-xs m-vgap-sm gap-hgap-xs">
Layout Spacing
The Zudo Design System uses a semantic spacing system with hgap (horizontal gaps) and vgap (vertical gaps) instead of a single numeric scale. Each axis gets a limited scale from 2xs to 2xl.
Horizontal Gaps (hgap)
| Token | Value | Use Case |
|---|---|---|
hgap-2xs | 5px | Minimal horizontal spacing |
hgap-xs | 12px | Small gaps between elements |
hgap-sm | 20px | Default padding/margins |
hgap-md | 40px | Section spacing |
hgap-md-x2 | 80px | Large section spacing |
hgap-lg | 60px | Major layout divisions |
hgap-lg-x2 | 120px | Extra large divisions |
hgap-xl | 100px | Page margins |
hgap-2xl | 250px | Maximum spacing |
Vertical Gaps (vgap)
| Token | Value | Use Case |
|---|---|---|
vgap-2xs | 4px | Minimal vertical spacing |
vgap-xs | 8px | Tight vertical spacing |
vgap-sm | 20px | Default vertical gaps |
vgap-md | 35px | Section spacing |
vgap-lg | 50px | Major sections |
vgap-xl | 65px | Large vertical spacing |
vgap-2xl | 80px | Maximum vertical spacing |
Special Spacing
| Token | Value | Use Case |
|---|---|---|
0 | 0 | Zero spacing |
1px | 1px | Hairline spacing/borders |
Usage Patterns
// Vertical spacing
<div className="mt-vgap-md mb-vgap-lg py-vgap-sm gap-y-vgap-xs">
// Horizontal spacing
<div className="mx-hgap-md pl-hgap-sm px-hgap-xs gap-x-hgap-md">
// Container padding
<div className="px-hgap-sm py-vgap-md">
// Grid gaps
<div className="grid gap-hgap-xs gap-y-vgap-sm">
Color System
Tier 1: Palette (p0–p15)
Raw color values in oklch color space. These are the building blocks — not used directly in components.
| Token | oklch Value | Role |
|---|---|---|
p0 | oklch(17% 0.005 50) | Dark surface |
p1 | oklch(60% 0.2 10) | Danger/red |
p2 | oklch(65% 0.19 145) | Success/green |
p3 | oklch(75% 0.17 75) | Warning/yellow |
p4 | oklch(100% 0 0) | Info/link (pure white) |
p5 | oklch(65% 0.2 45) | Accent/primary |
p6 | oklch(52% 0.01 50) | Neutral/gray |
p7 | oklch(87% 0.01 60) | Light text (headings) |
p8 | oklch(70% 0.01 60) | Muted text |
p9 | oklch(18% 0.01 50) | Background |
p10 | oklch(22% 0.01 50) | Surface |
p11 | = p7 | Text primary |
p12 | oklch(82% 0.15 85) | Price/highlight |
p13 | oklch(50.5% 0.213 27.518) | Sold/special |
p14 | oklch(55% 0.18 45) | Accent hover |
p15 | oklch(75% 0.01 60) | Secondary text |
Tier 2: Semantic Colors
Semantic tokens that reference palette slots. These are what components use.
| Token | Maps To | Use Case |
|---|---|---|
bg | p9 | Page background |
fg | p11 | Main text |
surface | p10 | Cards, panels, elevated backgrounds |
muted | p8 | Secondary text, disabled elements |
accent / accent-hover | p5 / p14 | Links, CTAs, interactive elements |
link | p4 | Link color (white — dark theme) |
success | p2 | Success messages |
danger | p1 | Error messages |
warning | p3 | Warning messages |
info | p4 | Info messages |
price | p12 | Price displays |
sold | p13 | Sold indicators |
code-bg / code-fg | p0 / p7 | Code blocks |
Legacy Color Tokens
For backward compatibility, legacy --zd-color-* tokens are still available:
| Class | Legacy Token | Use Case |
|---|---|---|
bg-zd-black, text-zd-black | --zd-color-black | Backgrounds, primary text |
bg-zd-white, text-zd-white | --zd-color-white | Light backgrounds, body text |
text-zd-gray, bg-zd-gray | --zd-color-gray | Secondary elements |
bg-zd-gray2 | --zd-color-gray2 | Dark backgrounds |
text-zd-link | --zd-color-link | Links (white) |
bg-zd-active | --zd-color-active | Active/pressed states |
text-zd-notify | --zd-color-notify | Success messages |
text-zd-error | --zd-color-error | Error messages |
text-zd-warning | --zd-color-warning | Warning messages |
text-zd-price | --zd-color-price | Price displays |
text-zd-strong | --zd-color-strong | Emphasis |
text-zd-sold | --zd-color-sold | Sold status |
text-zd-outline | --zd-color-outline | Focus outlines |
Status Colors (Admin Interfaces)
| Class | Use Case |
|---|---|
bg-status-pending, text-status-pending | Pending state |
bg-status-notified, text-status-notified | Notified state |
bg-status-confirmed, text-status-confirmed | Confirmed state |
bg-status-fulfilled, text-status-fulfilled | Fulfilled state |
bg-status-cancelled, text-status-cancelled | Cancelled state |
Typography
Font Families
| Class | Stack |
|---|---|
font-noto | Noto Sans, Noto Sans JP, system-ui, … |
font-futura | Futura, Jost, Century Gothic, system-ui, … |
font-sans | Helvetica, Arial, system-ui, Noto Sans JP, … |
font-mono | Menlo, Monaco, Consolas, … |
Font Sizes with Integrated Line Heights
Each font size token includes a paired line height. Using text-base sets both font-size: 1.4rem and line-height: 1.7.
| Class | Size | Line Height |
|---|---|---|
text-xs | 1rem (10px) | 1.4 |
text-sm | 1.1rem (11px) | 1.5 |
text-base | 1.4rem (14px) | 1.7 |
text-lg | 1.6rem (16px) | 1.5 |
text-xl | 1.9rem (19px) | 1.4 |
text-2xl | 2.8rem (28px) | 1.35 |
text-3xl | 3.2rem (32px) | 1.3 |
text-4xl | 4rem (40px) | 1.3 |
text-5xl | 4.8rem (48px) | 1.3 |
Standalone Line Heights
For overriding the integrated line height:
| Class | Value |
|---|---|
leading-none | 1 |
leading-tight | 1.4 |
leading-snug | 1.6 |
leading-normal | 1.8 |
leading-relaxed | 1 |
leading-loose | 2.3 |
Font Weights
Standard weight classes: font-thin(100), font-extralight(200), font-light(300), font-normal(400), font-medium(500), font-semibold(600), font-bold(700), font-extrabold(800), font-black(900).
Breakpoints
| Prefix | Width | Use Case |
|---|---|---|
sm: | 580px | Small screens |
md: | 740px | Medium screens |
lg: | 980px | Large screens |
xl: | 1280px | Extra large screens |
2xl: | 1630px | Wide screens |
3xl: | 1800px | Ultra wide screens |
Additional Theme Tokens
Border Radius
| Class | Value |
|---|---|
rounded-xs | 0.125rem |
rounded-sm | 0.25rem |
rounded-md | 0.375rem |
rounded-lg | 0.5rem |
Box Shadows
Available: shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl, shadow-inner, shadow-none.
Width/Height Utilities
Available: w-full, h-full, min-w-0, min-h-0, min-h-screen, max-w-full, max-h-full, plus max-width scale (max-w-xs through max-w-7xl) and fractional widths (w-1/2, w-1/3, etc.).
Custom Utilities
Defined in sub-packages/design-system/utilities.css:
Text Shadows
<h1 className="text-shadow-md"> // Text shadow for readability on images
<span className="text-shadow-none"> // Remove text shadow
Status Badges (Admin)
<span className="status-pending">Pending</span>
<span className="status-notified">Notified</span>
<span className="status-fulfilled">Fulfilled</span>
Gradients
<div className="zd-gradient-black-to-transparent">
<div className="zd-gradient-white-to-transparent">
Clearfix
<div className="clearfix">
Common Patterns
Product Grid
<div className="min-h-screen bg-zd-black px-hgap-sm py-vgap-md">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-hgap-xs gap-y-vgap-sm">
<div className="bg-zd-gray2 p-hgap-xs">
<img className="mb-vgap-xs" />
<h3 className="text-zd-white text-lg mb-vgap-2xs">Product Name</h3>
<p className="text-zd-price text-xl">¥1,480</p>
</div>
</div>
</div>
Container Padding
// Page container
<div className="px-hgap-sm py-vgap-md">
// Card/Component padding
<div className="px-hgap-xs py-vgap-sm">
Section Margins
<section className="mt-vgap-lg mb-vgap-xl">
Migration Guide
When converting existing code to use the design system:
Before (Default Tailwind)
<div className="px-4 py-6 mt-8 mb-10">
<div className="gap-5">
After (Zudo Design System)
<div className="px-hgap-xs py-vgap-sm mt-vgap-sm mb-vgap-md">
<div className="gap-hgap-2xs">
Related Files
- Design system tokens:
sub-packages/design-system/tokens.css - Tailwind theme:
sub-packages/design-system/theme.css - Custom utilities:
sub-packages/design-system/utilities.css - CSS processing: Tailwind v4 via
@tailwindcss/vite+ lightningcss (configured inastro.config.ts)