@withmata/blueprints 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/audit/SKILL.md +4 -4
- package/.claude/skills/blueprint-catalog/SKILL.md +17 -7
- package/.claude/skills/copywrite/SKILL.md +187 -0
- package/.claude/skills/copywrite-landing/SKILL.md +489 -0
- package/.claude/skills/design-system/SKILL.md +970 -0
- package/.claude/skills/new-project/SKILL.md +168 -112
- package/.claude/skills/scaffold-auth/SKILL.md +9 -9
- package/.claude/skills/scaffold-db/SKILL.md +14 -14
- package/.claude/skills/scaffold-env/SKILL.md +4 -4
- package/.claude/skills/scaffold-foundation/SKILL.md +15 -15
- package/.claude/skills/scaffold-tailwind/SKILL.md +17 -3
- package/.claude/skills/scaffold-ui/SKILL.md +155 -36
- package/ENGINEERING.md +2 -2
- package/blueprints/discovery/design-system/BLUEPRINT.md +1479 -0
- package/blueprints/discovery/marketing-copywriting/BLUEPRINT.md +664 -0
- package/blueprints/features/auth-better-auth/BLUEPRINT.md +20 -22
- package/blueprints/features/db-drizzle-postgres/BLUEPRINT.md +12 -12
- package/blueprints/features/db-drizzle-postgres/files/db/src/example-entity.ts +1 -1
- package/blueprints/features/db-drizzle-postgres/files/db/src/scripts/seed.ts +1 -1
- package/blueprints/features/env-t3/BLUEPRINT.md +1 -1
- package/blueprints/features/tailwind-v4/BLUEPRINT.md +9 -2
- package/blueprints/features/tailwind-v4/files/tailwind-config/shared-styles.css +80 -1
- package/blueprints/features/ui-shared-components/BLUEPRINT.md +411 -78
- package/blueprints/features/ui-shared-components/files/ui/components/ui/alert-dialog.tsx +192 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/avatar.tsx +71 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/badge.tsx +52 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/breadcrumb.tsx +122 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/button.tsx +56 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/card-select.tsx +72 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/card.tsx +100 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/collapsible.tsx +34 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/combobox.tsx +301 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/dropdown-menu.tsx +264 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/empty-state.tsx +43 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/entity-select.tsx +110 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/field.tsx +237 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/form-field.tsx +217 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/input-group.tsx +161 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/input.tsx +20 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/label.tsx +20 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/org-switcher.tsx +114 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/page-header.tsx +45 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/pagination.tsx +52 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/pill-select.tsx +151 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/popover.tsx +41 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/search-input.tsx +49 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/select.tsx +205 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/selected-entity-card.tsx +47 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/separator.tsx +25 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/sidebar.tsx +389 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/status-filter.tsx +43 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/tag-input.tsx +131 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/textarea.tsx +18 -0
- package/blueprints/features/ui-shared-components/files/ui/components/ui/user-menu.tsx +149 -0
- package/blueprints/features/ui-shared-components/files/ui/components.json +11 -8
- package/blueprints/features/ui-shared-components/files/ui/package.json +20 -11
- package/blueprints/foundation/monorepo-turbo/BLUEPRINT.md +19 -20
- package/blueprints/foundation/monorepo-turbo/files/root/package.json +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/blueprints/features/tailwind-v4/files/tailwind-config/package.json +0 -20
- package/blueprints/foundation/monorepo-turbo/files/root/pnpm-workspace.yaml +0 -5
|
@@ -0,0 +1,1479 @@
|
|
|
1
|
+
# Design System Blueprint — Visual Identity & Tailwind Tokens
|
|
2
|
+
|
|
3
|
+
## Tier
|
|
4
|
+
|
|
5
|
+
Discovery — produces documentation and actionable CSS, not application code.
|
|
6
|
+
|
|
7
|
+
## Problem
|
|
8
|
+
|
|
9
|
+
Technical founders scaffolding projects with the blueprint system get functional, accessible UI components — but every project looks identical. The Tailwind v4 blueprint provides a solid token structure (31 semantic color tokens, radius scale, font variables) but fills them with generic shadcn defaults. Without a deliberate design system, products lack visual identity: the colors don't reflect the brand, the typography doesn't match the audience, the spacing and rounding don't communicate the right personality. This blueprint defines a product's visual identity through a structured design conversation and outputs actual Tailwind CSS that replaces the defaults — so when UI components render, they look like YOUR product, not a template.
|
|
10
|
+
|
|
11
|
+
## Status
|
|
12
|
+
|
|
13
|
+
Complete.
|
|
14
|
+
|
|
15
|
+
## Blueprint Dependencies
|
|
16
|
+
|
|
17
|
+
| Blueprint | Type | Why |
|
|
18
|
+
|-----------|------|-----|
|
|
19
|
+
| `discovery/product-discovery` | recommended | Provides product type, customer archetypes, brand personality, and competitive landscape. The design system is strongest when grounded in validated product research. Without it, context is gathered conversationally. |
|
|
20
|
+
| `discovery/marketing-copywriting` | recommended | Provides brand voice and tone. Helps align visual identity with how the product communicates — a playful brand voice shouldn't live inside a corporate-looking interface. |
|
|
21
|
+
|
|
22
|
+
## Output
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
docs/
|
|
26
|
+
└── design/
|
|
27
|
+
├── design-system.md # The "why" + "how to use" document
|
|
28
|
+
└── shared-styles.css # Actual Tailwind v4 CSS tokens
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The `shared-styles.css` is consumed by `/scaffold-tailwind` — if it exists when tailwind is scaffolded, it replaces the generic defaults. It follows the exact same CSS structure as the Tailwind v4 blueprint template: `@import` directives, `@custom-variant`, `@theme inline {}`, `@theme {}`, `:root {}`, `.dark {}`, and `@layer base {}`.
|
|
32
|
+
|
|
33
|
+
**File naming rules:**
|
|
34
|
+
- Output files go in `docs/design/` — this is the design system's source of truth
|
|
35
|
+
- `shared-styles.css` is a real, valid CSS file — not pseudocode or documentation
|
|
36
|
+
- `design-system.md` is the reference document explaining every decision
|
|
37
|
+
- Do NOT create files beyond what's specified above
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Process
|
|
42
|
+
|
|
43
|
+
This is a CONVERSATIONAL blueprint. Claude Code guides the user through a structured design session that produces a complete visual identity system and actionable Tailwind CSS tokens. The process adapts based on available context — product discovery docs, marketing copy docs, or direct conversation.
|
|
44
|
+
|
|
45
|
+
### Phase 1: Context Gathering
|
|
46
|
+
|
|
47
|
+
**Goal:** Understand the product, audience, and personality before making any visual decisions.
|
|
48
|
+
|
|
49
|
+
Design without context produces decoration. Design with context produces identity. This phase maps everything known about the product into design-relevant inputs.
|
|
50
|
+
|
|
51
|
+
#### Path 1: Product Docs Available (recommended)
|
|
52
|
+
|
|
53
|
+
Auto-read `.project-context.md` + `docs/product/` + `docs/pages/` if available. Map them to design inputs:
|
|
54
|
+
|
|
55
|
+
- **Product type** -> aesthetic direction
|
|
56
|
+
- SaaS dashboard -> structured, information-dense, calm backgrounds, clear hierarchy
|
|
57
|
+
- Consumer app -> bold personality, playful interactions, memorable colors
|
|
58
|
+
- Developer tool -> monospace accents, high contrast, minimal chrome, dark-mode-first
|
|
59
|
+
- Marketplace -> warm and trustworthy, card-heavy, image-friendly layouts
|
|
60
|
+
- Content/media -> editorial typography, generous whitespace, reading-optimized
|
|
61
|
+
- Enterprise B2B -> conservative palette, accessibility-first, dense but organized
|
|
62
|
+
|
|
63
|
+
- **Primary archetype** -> audience sensibility
|
|
64
|
+
- Technical users -> appreciate subtlety, dislike gratuitous decoration, value density
|
|
65
|
+
- Non-technical users -> need visual cues for hierarchy, prefer clear affordances
|
|
66
|
+
- Enterprise buyers -> expect polish, trust conservative palettes, notice rough edges
|
|
67
|
+
- Startup users -> tolerate experimentation, respond to personality, forgive imperfection
|
|
68
|
+
- Young audience -> expects modern aesthetics, dark mode, bold color, animation
|
|
69
|
+
- Mature audience -> values clarity, readable typography, restrained color, stability
|
|
70
|
+
|
|
71
|
+
- **Core pillars** -> what the design should communicate
|
|
72
|
+
- "Speed" -> sharp edges, minimal decoration, fast transitions, reduced visual weight
|
|
73
|
+
- "Trust" -> blue-shifted palette, consistent spacing, conservative rounding, ample whitespace
|
|
74
|
+
- "Simplicity" -> limited palette, generous spacing, large type, few shadows
|
|
75
|
+
- "Power" -> deep colors, dense layouts, detailed controls, visible complexity
|
|
76
|
+
- "Creativity" -> vibrant accents, asymmetry, unexpected color, playful rounding
|
|
77
|
+
- "Warmth" -> earth tones, soft rounding, friendly type, textured surfaces
|
|
78
|
+
|
|
79
|
+
- **Brand voice** (from marketing copy if available) -> visual tone alignment
|
|
80
|
+
- Casual/playful voice -> rounded corners, warm colors, bouncy animations
|
|
81
|
+
- Professional/authoritative voice -> sharp geometry, cool colors, subtle transitions
|
|
82
|
+
- Technical/precise voice -> monospace accents, systematic spacing, minimal decoration
|
|
83
|
+
- Friendly/approachable voice -> medium rounding, warm neutrals, soft shadows
|
|
84
|
+
|
|
85
|
+
After reading, summarize what you found:
|
|
86
|
+
- "From your product discovery, I can see your product is a [type], your primary audience is [archetype description], and your core pillars are [X, Y, Z]. This tells me the design should communicate [qualities]. I'll use that as the foundation for creative direction."
|
|
87
|
+
|
|
88
|
+
Then ask only what's missing:
|
|
89
|
+
- Do you have any visual references — screenshots, sites you admire, or brands whose look you'd want to echo?
|
|
90
|
+
- Are there any colors you know you want or know you want to avoid?
|
|
91
|
+
- Is there an existing brand identity (logo, brand colors) this needs to work with?
|
|
92
|
+
|
|
93
|
+
#### Path 2: No Product Docs Available
|
|
94
|
+
|
|
95
|
+
Gather context conversationally. Ask about these four dimensions:
|
|
96
|
+
|
|
97
|
+
**Product Identity:**
|
|
98
|
+
- What does your product do in one sentence?
|
|
99
|
+
- Who is your primary user? (Job title, company size, technical level)
|
|
100
|
+
- What 3 words should someone use to describe your product's personality?
|
|
101
|
+
- Is this a dashboard, consumer app, developer tool, marketplace, content site, or something else?
|
|
102
|
+
|
|
103
|
+
**Brand Constraints:**
|
|
104
|
+
- Do you have an existing logo or brand colors? (If yes, the design system works around them)
|
|
105
|
+
- Are there brands whose visual style you admire? (This reveals aesthetic preferences faster than abstract questions)
|
|
106
|
+
- Are there visual styles you actively dislike? (Equally valuable — narrows the space)
|
|
107
|
+
|
|
108
|
+
**Audience Expectations:**
|
|
109
|
+
- What tools/apps does your audience use daily? (Reveals their visual baseline)
|
|
110
|
+
- Is your audience more Notion or more Bloomberg Terminal? More Linear or more Salesforce?
|
|
111
|
+
- Are they using your product under pressure (speed matters) or reflectively (calm matters)?
|
|
112
|
+
|
|
113
|
+
**Practical Needs:**
|
|
114
|
+
- Does your product have a lot of data density? (Tables, charts, dashboards)
|
|
115
|
+
- Is dark mode critical for your audience? (Developers, designers, night-use)
|
|
116
|
+
- Will you have a marketing site that needs to look different from the app?
|
|
117
|
+
|
|
118
|
+
**Push back when:**
|
|
119
|
+
- Personality words are generic ("modern, clean, professional" — that describes everything)
|
|
120
|
+
- No user context ("it's for everyone" — no product is for everyone)
|
|
121
|
+
- Visual references are wildly contradictory (ask them to pick a direction)
|
|
122
|
+
- They want to "look like Apple" without understanding what that means structurally
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Phase 2: Creative Direction
|
|
127
|
+
|
|
128
|
+
**Goal:** Define a Creative North Star — a one-paragraph description of the visual identity that guides every subsequent decision.
|
|
129
|
+
|
|
130
|
+
**Announce framework:** "I'm going to propose 2-3 creative directions based on what we've discussed. Each direction is a coherent visual personality — not just colors, but a whole way of looking and feeling. Your job is to pick one, or tell me which elements from different directions to combine. This becomes the Creative North Star that guides every decision in the design system."
|
|
131
|
+
|
|
132
|
+
Propose 2-3 creative direction options based on context. Each direction includes:
|
|
133
|
+
- **A name** — something evocative that captures the mood
|
|
134
|
+
- **A North Star paragraph** — a vivid description of how the product should feel
|
|
135
|
+
- **A mood** — 3-5 adjective clusters
|
|
136
|
+
- **Why it fits** — specific reasoning tied to the product, audience, and pillars
|
|
137
|
+
|
|
138
|
+
Example directions (adapt these to the actual product — never use these verbatim):
|
|
139
|
+
|
|
140
|
+
**"Cognitive Sanctuary"**
|
|
141
|
+
> A space that feels calm and expansive. Soft backgrounds with breathing room between elements. Muted violet tinted with warmth. Typography that's generous but never sprawling. Shadows that suggest depth without drama. The product feels like a quiet library with perfect lighting — focused, restful, and deeply functional.
|
|
142
|
+
>
|
|
143
|
+
> *Mood:* soft, breathing, violet-tinted, unhurried, precise
|
|
144
|
+
> *Why:* Your audience is knowledge workers under constant cognitive pressure. The product should feel like relief — a sanctuary from noisy, demanding interfaces. The violet primary differentiates from the sea of blue SaaS tools while retaining professionalism.
|
|
145
|
+
|
|
146
|
+
**"Precision Engine"**
|
|
147
|
+
> Every pixel earns its place. Sharp edges, systematic spacing, and a navy-slate palette that communicates engineering discipline. Monospace accents in headers. Minimal shadows — hierarchy comes from weight and space, not decoration. The product feels like a precision instrument — powerful, exact, and confidence-inspiring.
|
|
148
|
+
>
|
|
149
|
+
> *Mood:* sharp, structured, navy/slate, disciplined, exact
|
|
150
|
+
> *Why:* Your audience is technical — they notice details, respect systems, and distrust gratuitous decoration. The sharp aesthetic mirrors the precision they bring to their own work. Navy differentiates from the startup-blue default while feeling established.
|
|
151
|
+
|
|
152
|
+
**"Warm Workshop"**
|
|
153
|
+
> A product that feels handcrafted rather than manufactured. Rounded corners, amber and earth tones, friendly typography that invites exploration. Shadows are soft and warm. Interactions have a slight bounce — nothing stiff. The product feels like walking into a well-organized workshop where everything has its place but nothing feels sterile.
|
|
154
|
+
>
|
|
155
|
+
> *Mood:* rounded, amber/earth, friendly, handcrafted, inviting
|
|
156
|
+
> *Why:* Your audience is non-technical and potentially intimidated by tools. Warmth reduces anxiety. The rounded, friendly aesthetic signals "this won't bite" — critical for adoption when users have a choice to avoid the tool entirely.
|
|
157
|
+
|
|
158
|
+
**User picks one or mixes elements.** Document the final Creative North Star.
|
|
159
|
+
|
|
160
|
+
**Explain WHY each direction fits (or doesn't fit) the product's audience.** This is educational — the user should understand how audience characteristics translate to visual decisions:
|
|
161
|
+
- Enterprise audience -> conservative palette, because enterprise buyers equate visual conservatism with stability and reliability
|
|
162
|
+
- Developer audience -> high information density, because developers are comfortable scanning dense UIs and frustrated by "dumbed-down" interfaces
|
|
163
|
+
- Consumer audience -> memorable primary color, because consumer products need brand recognition in a crowded market
|
|
164
|
+
- Young audience -> dark mode first, because younger users overwhelmingly prefer dark interfaces and associate them with modernity
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### Phase 3: Color System
|
|
169
|
+
|
|
170
|
+
**Goal:** Define every color token in the design system with oklch values, covering light mode, dark mode, and the reasoning behind each choice.
|
|
171
|
+
|
|
172
|
+
**Announce framework:** "I'm going to build the full color system now. We'll start with the primary color — the single most important decision — and build outward from there. Every color in the system will be in oklch, which is a perceptually uniform color space. That means: consistent vibrancy across the spectrum, better dark mode translations, and gradients that don't go muddy in the middle."
|
|
173
|
+
|
|
174
|
+
#### Primary Color Selection
|
|
175
|
+
|
|
176
|
+
Research: what colors do competitors and similar products use? This matters because:
|
|
177
|
+
- If every competitor uses blue, choosing blue makes you invisible in screenshots and reviews
|
|
178
|
+
- If the space expects blue (finance, enterprise), deviating too far signals "unserious"
|
|
179
|
+
- The right primary color balances audience expectation with competitive differentiation
|
|
180
|
+
|
|
181
|
+
Propose the primary color based on:
|
|
182
|
+
|
|
183
|
+
**Product personality:**
|
|
184
|
+
- Blue (hue ~240-260) -> trust, reliability, calm — universal enterprise default for a reason, but also the most overused
|
|
185
|
+
- Green (hue ~145-165) -> growth, health, nature, money — strong for fintech, health, sustainability
|
|
186
|
+
- Violet/purple (hue ~280-310) -> creativity, premium, imagination — differentiates from blue while retaining professionalism
|
|
187
|
+
- Orange (hue ~60-80) -> energy, warmth, urgency — bold and memorable, but can feel aggressive at high chroma
|
|
188
|
+
- Rose/pink (hue ~0-20) -> warmth, empathy, care — strong for health, community, consumer
|
|
189
|
+
- Teal (hue ~180-200) -> clarity, freshness, balance — modern alternative to blue
|
|
190
|
+
- Amber/gold (hue ~85-100) -> warmth, craft, quality — premium without being cold
|
|
191
|
+
|
|
192
|
+
**Audience expectations:**
|
|
193
|
+
- Enterprise expects blue/gray/green — deviating requires confidence and brand strength
|
|
194
|
+
- Consumer apps can be bold — personality matters more than convention
|
|
195
|
+
- Developer tools trend toward violet, teal, or desaturated palettes
|
|
196
|
+
- Health/wellness tends toward green, teal, or warm neutrals
|
|
197
|
+
|
|
198
|
+
**Competitive differentiation:**
|
|
199
|
+
- List the colors 3-5 direct competitors use
|
|
200
|
+
- Identify the gap — which hues are underrepresented?
|
|
201
|
+
- Propose a primary that occupies defensible visual territory
|
|
202
|
+
|
|
203
|
+
#### Full Palette Definition
|
|
204
|
+
|
|
205
|
+
Define all 31 semantic tokens in oklch. Explain the reasoning behind each group:
|
|
206
|
+
|
|
207
|
+
**Core tokens (6):**
|
|
208
|
+
- `--primary` + `--primary-foreground` — the brand color and text that sits on top of it
|
|
209
|
+
- `--secondary` + `--secondary-foreground` — complement or neutral, for supporting elements
|
|
210
|
+
- `--accent` + `--accent-foreground` — highlight color for emphasis, selection states, hover
|
|
211
|
+
|
|
212
|
+
*Why these three tiers:* Primary carries brand identity. Secondary provides visual rest — elements that need to be visible but shouldn't compete with primary. Accent is the "notice me" color used sparingly for interactive states and highlights. Without this hierarchy, everything screams at the same volume and nothing stands out.
|
|
213
|
+
|
|
214
|
+
**Feedback tokens (2):**
|
|
215
|
+
- `--destructive` — error and danger states. Red-shifted (hue ~20-30) regardless of brand, because red=danger is a universal human association. Adjust lightness to ensure WCAG AA contrast against both light and dark backgrounds.
|
|
216
|
+
|
|
217
|
+
*Why destructive is always red-adjacent:* Cultural universals in color semantics are rare, but red=danger/stop is one of them. Fighting this convention to match a brand palette creates confusion in critical moments (delete confirmations, error states, data loss warnings). Brand identity yields to safety signaling.
|
|
218
|
+
|
|
219
|
+
**Neutral tokens (6):**
|
|
220
|
+
- `--background` + `--foreground` — page-level backdrop and default text
|
|
221
|
+
- `--muted` + `--muted-foreground` — subdued backgrounds and secondary text
|
|
222
|
+
- `--card` + `--card-foreground` — surface for card components
|
|
223
|
+
|
|
224
|
+
*Why separate card from background:* Surface hierarchy. When a card sits on the page background, it needs to be visually distinct. In light mode, cards are often the same white as the background (differentiated by shadow or border). In dark mode, cards are typically one step lighter than the background. Having separate tokens enables this without conditional logic.
|
|
225
|
+
|
|
226
|
+
**Container tokens (4):**
|
|
227
|
+
- `--popover` + `--popover-foreground` — floating elements (dropdowns, tooltips, popovers)
|
|
228
|
+
- `--border` — lines separating elements
|
|
229
|
+
- `--input` — input field borders (often slightly different from general borders)
|
|
230
|
+
|
|
231
|
+
*Why popover is separate from card:* Popovers float above the page and need stronger visual separation. In dark mode, popovers are often lighter than cards to signal elevation. Separate tokens let you fine-tune this hierarchy.
|
|
232
|
+
|
|
233
|
+
**Interactive tokens (1):**
|
|
234
|
+
- `--ring` — focus ring color for keyboard navigation accessibility
|
|
235
|
+
|
|
236
|
+
*Why ring exists as a separate token:* Focus rings serve a specific accessibility purpose — they must be visible against ANY background in the application. A dedicated token lets you choose a ring color with guaranteed contrast, independent of the brand palette.
|
|
237
|
+
|
|
238
|
+
**Sidebar tokens (8):**
|
|
239
|
+
- `--sidebar`, `--sidebar-foreground` — sidebar background and text
|
|
240
|
+
- `--sidebar-primary`, `--sidebar-primary-foreground` — active item in sidebar
|
|
241
|
+
- `--sidebar-accent`, `--sidebar-accent-foreground` — hover/selected states
|
|
242
|
+
- `--sidebar-border` — sidebar divider lines
|
|
243
|
+
- `--sidebar-ring` — focus ring within sidebar context
|
|
244
|
+
|
|
245
|
+
*Why sidebar gets its own tokens:* Sidebars often have a different visual treatment than the main content area — slightly darker in light mode, slightly lighter in dark mode, or tinted with the brand color. Separate tokens enable sidebar-as-distinct-zone without CSS hacks.
|
|
246
|
+
|
|
247
|
+
**Chart tokens (5):**
|
|
248
|
+
- `--chart-1` through `--chart-5` — data visualization colors
|
|
249
|
+
|
|
250
|
+
*Why 5 chart colors:* Most data visualizations use 3-5 series. Beyond 5, colors become hard to distinguish and the chart needs a different approach (labels, patterns). These 5 should be harmonized with the primary color but distinct enough for accessibility. A good approach: spread across 60-120 degrees of hue from the primary, maintaining consistent lightness and chroma.
|
|
251
|
+
|
|
252
|
+
**Radius token (1):**
|
|
253
|
+
- `--radius` — the base radius from which all other radii are calculated
|
|
254
|
+
|
|
255
|
+
*Why a base radius:* The radius scale in `@theme inline` calculates `--radius-sm` through `--radius-4xl` from this single value. Changing `--radius` from `0.625rem` to `1rem` transforms the entire application from moderate to round. One variable, total control.
|
|
256
|
+
|
|
257
|
+
#### Dark Mode Strategy
|
|
258
|
+
|
|
259
|
+
Dark mode is NOT "just invert the lightness." Every color needs deliberate adjustment:
|
|
260
|
+
|
|
261
|
+
**Background strategy:**
|
|
262
|
+
- Dark background should be around L=0.12-0.18 in oklch — true black (L=0) causes eye strain and makes cards invisible
|
|
263
|
+
- Card surfaces 1-2 steps lighter (L=0.18-0.24) for visible elevation
|
|
264
|
+
- Popover surfaces another step lighter — floating elements must feel elevated
|
|
265
|
+
|
|
266
|
+
**Color adjustments for dark mode:**
|
|
267
|
+
- Primary color: reduce chroma slightly (saturated colors on dark backgrounds feel neon/electric), shift lightness up slightly for readability
|
|
268
|
+
- Muted foreground: increase lightness to ~0.65-0.72 (gray text on dark needs more contrast than gray text on light)
|
|
269
|
+
- Borders: use `oklch(1 0 0 / 10%)` (white at 10% opacity) for subtle, adaptive borders
|
|
270
|
+
- Input borders: slightly higher opacity (~15%) so input fields are clearly delineated
|
|
271
|
+
- Destructive: increase lightness (a dark red on a dark background is invisible)
|
|
272
|
+
|
|
273
|
+
**What NOT to do in dark mode:**
|
|
274
|
+
- Don't use pure black (`oklch(0 0 0)`) as background — it causes halation (text blooms) on OLED screens
|
|
275
|
+
- Don't keep the same chroma as light mode — saturated colors on dark backgrounds cause visual vibration
|
|
276
|
+
- Don't just flip lightness values — the relationship between surface layers matters more than individual values
|
|
277
|
+
- Don't forget sidebar tokens — a dark sidebar on a dark background becomes invisible without separate values
|
|
278
|
+
|
|
279
|
+
#### Surface Hierarchy Philosophy
|
|
280
|
+
|
|
281
|
+
Explain the "paper layers" approach:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
Layer 0: Page background (--background) — the base canvas
|
|
285
|
+
Layer 1: Content regions (--card) — cards, panels, content areas
|
|
286
|
+
Layer 2: Floating surfaces (--popover) — dropdowns, tooltips, modals
|
|
287
|
+
Layer 3: Elevated elements (sidebar, modals) — highest visual priority
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
In light mode, surfaces differentiate through shadow (Layer 1 has shadow-sm, Layer 2 has shadow-lg). In dark mode, surfaces differentiate through lightness stepping (each layer is 2-4% lighter than the one below). This dual strategy ensures hierarchy is clear in both modes.
|
|
291
|
+
|
|
292
|
+
#### Surface Layering Stack
|
|
293
|
+
|
|
294
|
+
Document an explicit visual layering model showing which surface sits where:
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
Layer 0 (deepest): background — Page canvas, the base everything rests on
|
|
298
|
+
Layer 1: sidebar — Persistent navigation surface
|
|
299
|
+
Layer 2: card — Content containers sitting on the page
|
|
300
|
+
Layer 3: popover — Floating elements (dropdowns, tooltips, selects)
|
|
301
|
+
Layer 4: overlay — Modal backdrop (semi-transparent)
|
|
302
|
+
Layer 5 (highest): dialog — Modal content surface with maximum elevation
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Separation strategies** (in order of preference):
|
|
306
|
+
1. **Tonal shifts** (preferred) — card on background creates natural contrast without explicit borders
|
|
307
|
+
2. **Shadows** (for floating elements) — popovers get shadow-lg, modals get shadow-xl
|
|
308
|
+
3. **Ghost borders** (accessibility fallback) — `ring-1 ring-foreground/10` when tonal shift alone isn't sufficient
|
|
309
|
+
|
|
310
|
+
This layering model must be applied consistently — a component should never use shadow elevation that doesn't match its layer position.
|
|
311
|
+
|
|
312
|
+
#### Evocative Color Naming
|
|
313
|
+
|
|
314
|
+
Every color token gets THREE identifiers: a **descriptive name** (evocative, memorable), the **functional role** (what it's used for), and the **exact value** (oklch). This serves both humans (the name creates emotional association) and AI agents (the functional role + value enables precise application).
|
|
315
|
+
|
|
316
|
+
Format in design-system.md:
|
|
317
|
+
```
|
|
318
|
+
| Token | Name | Light | Dark | Usage | Tailwind |
|
|
319
|
+
|-------|------|-------|------|-------|----------|
|
|
320
|
+
| primary | Deep Indigo | oklch(0.488 0.243 264) | oklch(0.42 0.18 266) | CTAs, links, active states | `bg-primary` |
|
|
321
|
+
| muted | Whisper Gray | oklch(0.97 0 0) | oklch(0.269 0 0) | Subtle backgrounds, inactive areas | `bg-muted` |
|
|
322
|
+
| destructive | Alert Terracotta | oklch(0.58 0.22 27) | oklch(0.704 0.191 22) | Errors, destructive actions | `bg-destructive` |
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Format in shared-styles.css (as comments):
|
|
326
|
+
```css
|
|
327
|
+
--primary: oklch(0.488 0.243 264.376); /* Deep Indigo — CTAs, active states */
|
|
328
|
+
--muted: oklch(0.97 0 0); /* Whisper Gray — subtle backgrounds */
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Naming convention: always **evocative adjective(s) + color family**. Never generic ("blue", "red"). Examples:
|
|
332
|
+
- "Deep Muted Teal-Navy" not "dark blue"
|
|
333
|
+
- "Warm Barely-There Cream" not "off-white"
|
|
334
|
+
- "Alert Terracotta" not "red"
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
### Phase 4: Typography
|
|
339
|
+
|
|
340
|
+
**Goal:** Select fonts that match the product personality and define the complete type scale.
|
|
341
|
+
|
|
342
|
+
**Announce framework:** "Typography is the most impactful design decision after color — it's on every screen, in every component, and it sets the tone before anyone reads a word. I'm going to recommend a font pairing (display + body, optionally + mono) and define the complete type scale with Tailwind v4 theme variables."
|
|
343
|
+
|
|
344
|
+
#### Font Research
|
|
345
|
+
|
|
346
|
+
Search for actual typefaces based on product personality and audience. Consider:
|
|
347
|
+
|
|
348
|
+
**Modern tech / SaaS:**
|
|
349
|
+
- Geist — the new standard for tech products (Next.js's house font), geometric but humanist, excellent at small sizes
|
|
350
|
+
- Satoshi — geometric sans with personality, stands out from Inter-sameness
|
|
351
|
+
- Cabinet Grotesk — bold and opinionated for display, clean at body sizes
|
|
352
|
+
- Inter — only recommend if it truly fits. It's the "safe choice" and makes everything look the same. When recommending Inter, be honest about why: "Inter is excellent technically but won't differentiate your product visually."
|
|
353
|
+
|
|
354
|
+
**Editorial / content-heavy:**
|
|
355
|
+
- Fraunces — a variable display serif with personality, great for headers paired with a clean sans body
|
|
356
|
+
- Newsreader — designed for long-form reading, excellent x-height
|
|
357
|
+
- Lora — workhorse serif with character, works at both display and body sizes
|
|
358
|
+
- Crimson Pro — elegant and readable, strong for premium content
|
|
359
|
+
|
|
360
|
+
**Friendly / approachable:**
|
|
361
|
+
- Plus Jakarta Sans — friendly geometry with good readability, slightly rounded terminals
|
|
362
|
+
- Nunito — rounded sans with warmth, approachable without being childish
|
|
363
|
+
- Quicksand — geometric with rounded terminals, distinctly friendly
|
|
364
|
+
- DM Sans — the structured friendly option, geometric but warm
|
|
365
|
+
|
|
366
|
+
**Premium / luxury:**
|
|
367
|
+
- Cormorant — a display serif with dramatic contrast, best paired with a simple sans
|
|
368
|
+
- Playfair Display — high-contrast serif, unmistakably editorial and premium
|
|
369
|
+
- EB Garamond — classic elegance, works at body sizes unlike most display serifs
|
|
370
|
+
|
|
371
|
+
**Developer / technical:**
|
|
372
|
+
- JetBrains Mono — excellent code font with ligatures, designed for extended reading
|
|
373
|
+
- Fira Code — the programmer favorite, with or without ligatures
|
|
374
|
+
- Berkeley Mono — premium monospace with character (not free)
|
|
375
|
+
- Geist Mono — pairs perfectly with Geist Sans (obviously)
|
|
376
|
+
|
|
377
|
+
#### Font Pairing Principles
|
|
378
|
+
|
|
379
|
+
Explain WHY the recommended pairing works:
|
|
380
|
+
|
|
381
|
+
- **Contrast creates interest** — pair a characterful display font with a neutral body font (or vice versa). Two fonts with similar personality feel redundant; two fonts with different personality create visual rhythm.
|
|
382
|
+
- **Shared structure creates harmony** — fonts should share structural DNA (x-height, stroke weight, proportions) even when their personality differs. A geometric display + geometric body feels more cohesive than geometric display + humanist body.
|
|
383
|
+
- **Body font carries the workload** — the body font appears in most UI text, so it must be readable at 14-16px, have a good set of weights (400, 500, 600, 700 minimum), and look clean at small sizes. Display fonts can be more expressive because they're used at larger sizes.
|
|
384
|
+
- **Mono is optional but valuable** — if the product shows any code, data, or tabular numbers, a dedicated mono font prevents the jarring fallback to system monospace. The mono font should share visual weight with the body font.
|
|
385
|
+
|
|
386
|
+
Propose the pairing with reasoning:
|
|
387
|
+
- "I recommend [Display] for headlines and [Body] for interface text because [specific reasoning tied to product personality and audience]. The [Display] font's [specific characteristic] communicates [quality], while [Body]'s [characteristic] ensures [practical benefit]."
|
|
388
|
+
|
|
389
|
+
#### Type Scale Definition
|
|
390
|
+
|
|
391
|
+
Define the complete scale using Tailwind v4 `@theme` variables. The scale maps to Tailwind's `text-*` utilities:
|
|
392
|
+
|
|
393
|
+
| Token | Default Value | Line Height | Usage | Tailwind Class |
|
|
394
|
+
|-------|---------------|-------------|-------|----------------|
|
|
395
|
+
| `--text-xs` | 0.75rem (12px) | 1rem | Fine print, captions, badges | `text-xs` |
|
|
396
|
+
| `--text-sm` | 0.875rem (14px) | 1.25rem | Secondary text, form labels, helper text | `text-sm` |
|
|
397
|
+
| `--text-base` | 1rem (16px) | 1.5rem | Body text, default paragraph | `text-base` |
|
|
398
|
+
| `--text-lg` | 1.125rem (18px) | 1.75rem | Emphasized body, section leads | `text-lg` |
|
|
399
|
+
| `--text-xl` | 1.25rem (20px) | 1.75rem | Card titles, small headings | `text-xl` |
|
|
400
|
+
| `--text-2xl` | 1.5rem (24px) | 2rem | Section headings | `text-2xl` |
|
|
401
|
+
| `--text-3xl` | 1.875rem (30px) | 2.25rem | Page headings | `text-3xl` |
|
|
402
|
+
| `--text-4xl` | 2.25rem (36px) | 2.5rem | Hero secondary | `text-4xl` |
|
|
403
|
+
| `--text-5xl` | 3rem (48px) | 1 | Hero headings | `text-5xl` |
|
|
404
|
+
| `--text-6xl` | 3.75rem (60px) | 1 | Display/marketing | `text-6xl` |
|
|
405
|
+
| `--text-7xl` | 4.5rem (72px) | 1 | Large display | `text-7xl` |
|
|
406
|
+
| `--text-8xl` | 6rem (96px) | 1 | Statement display | `text-8xl` |
|
|
407
|
+
| `--text-9xl` | 8rem (128px) | 1 | Extreme display | `text-9xl` |
|
|
408
|
+
|
|
409
|
+
Adjust the scale based on product needs:
|
|
410
|
+
- Data-dense products may tighten the scale (smaller increments) to fit more hierarchy into less space
|
|
411
|
+
- Marketing-heavy products may stretch the scale (larger display sizes) for dramatic headings
|
|
412
|
+
- Mobile-first products should verify the scale at 320px viewport width
|
|
413
|
+
|
|
414
|
+
**Weight scale:**
|
|
415
|
+
|
|
416
|
+
| Token | Value | Usage | Tailwind Class |
|
|
417
|
+
|-------|-------|-------|----------------|
|
|
418
|
+
| `--font-weight-thin` | 100 | Decorative display only | `font-thin` |
|
|
419
|
+
| `--font-weight-extralight` | 200 | Large display text | `font-extralight` |
|
|
420
|
+
| `--font-weight-light` | 300 | De-emphasized text | `font-light` |
|
|
421
|
+
| `--font-weight-normal` | 400 | Body text default | `font-normal` |
|
|
422
|
+
| `--font-weight-medium` | 500 | Labels, navigation items | `font-medium` |
|
|
423
|
+
| `--font-weight-semibold` | 600 | Headings, button text | `font-semibold` |
|
|
424
|
+
| `--font-weight-bold` | 700 | Strong emphasis, primary headings | `font-bold` |
|
|
425
|
+
| `--font-weight-extrabold` | 800 | Hero headings | `font-extrabold` |
|
|
426
|
+
| `--font-weight-black` | 900 | Display/marketing only | `font-black` |
|
|
427
|
+
|
|
428
|
+
**Tracking (letter spacing):**
|
|
429
|
+
|
|
430
|
+
| Token | Value | Usage |
|
|
431
|
+
|-------|-------|-------|
|
|
432
|
+
| `--tracking-tighter` | -0.05em | Large display headings (tighten at large sizes) |
|
|
433
|
+
| `--tracking-tight` | -0.025em | Headings, card titles |
|
|
434
|
+
| `--tracking-normal` | 0em | Body text |
|
|
435
|
+
| `--tracking-wide` | 0.025em | Uppercase labels, badges |
|
|
436
|
+
| `--tracking-wider` | 0.05em | Small uppercase text |
|
|
437
|
+
| `--tracking-widest` | 0.1em | Decorative uppercase, overlines |
|
|
438
|
+
|
|
439
|
+
**Leading (line height):**
|
|
440
|
+
|
|
441
|
+
| Token | Value | Usage |
|
|
442
|
+
|-------|-------|-------|
|
|
443
|
+
| `--leading-none` | 1 | Display headings (tight) |
|
|
444
|
+
| `--leading-tight` | 1.25 | Headings, short text |
|
|
445
|
+
| `--leading-snug` | 1.375 | Cards, compact layouts |
|
|
446
|
+
| `--leading-normal` | 1.5 | Body text default |
|
|
447
|
+
| `--leading-relaxed` | 1.625 | Long-form reading |
|
|
448
|
+
| `--leading-loose` | 2 | Wide-set text, open layouts |
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### Phase 5: Spacing, Rounding & Borders
|
|
453
|
+
|
|
454
|
+
**Goal:** Define the spatial personality — how much breathing room, how round the corners, and when lines appear.
|
|
455
|
+
|
|
456
|
+
#### Base Spacing Unit
|
|
457
|
+
|
|
458
|
+
The default `--spacing` in Tailwind v4 is `0.25rem` (4px). This means `p-4` = `1rem` (16px), `gap-6` = `1.5rem` (24px), etc. Adjusting `--spacing` scales the entire system:
|
|
459
|
+
|
|
460
|
+
- `0.25rem` (default) — standard density, works for most applications
|
|
461
|
+
- `0.2rem` — tighter, for data-dense dashboards where screen real estate matters
|
|
462
|
+
- `0.3rem` — looser, for marketing/content sites where breathing room is the priority
|
|
463
|
+
|
|
464
|
+
*Why base spacing matters:* When every spacing value derives from one unit, the system stays proportional as it scales. Changing `--spacing` from 0.25rem to 0.3rem increases whitespace everywhere uniformly — you don't get the inconsistency of ad-hoc padding adjustments where some elements feel cramped while others feel loose.
|
|
465
|
+
|
|
466
|
+
#### Rounding Personality
|
|
467
|
+
|
|
468
|
+
Define the base `--radius` and explain the personality it creates:
|
|
469
|
+
|
|
470
|
+
**Sharp (--radius: 0-0.25rem / 0-4px):**
|
|
471
|
+
- Components: `rounded-sm` (2px) for buttons, `rounded-md` (4px) for cards, `rounded-none` for tables
|
|
472
|
+
- Personality: corporate, serious, editorial, architectural
|
|
473
|
+
- Best for: enterprise B2B, fintech, legal, media
|
|
474
|
+
- Why: sharp corners communicate precision and formality. They say "we mean business" — there's no softness to hide behind. Editorial design has used sharp corners for centuries because they create clean grid alignment.
|
|
475
|
+
|
|
476
|
+
**Moderate (--radius: 0.375-0.625rem / 6-10px):**
|
|
477
|
+
- Components: `rounded-md` (6px) for buttons, `rounded-lg` (8px) for cards, `rounded-xl` (12px) for modals
|
|
478
|
+
- Personality: balanced, professional, contemporary, approachable-but-serious
|
|
479
|
+
- Best for: SaaS, productivity tools, developer platforms, general B2B
|
|
480
|
+
- Why: the sweet spot — professional enough for enterprise, friendly enough for startups. This is the default for a reason: it works for most products without making a strong statement in either direction.
|
|
481
|
+
|
|
482
|
+
**Round (--radius: 0.75-1rem / 12-16px):**
|
|
483
|
+
- Components: `rounded-xl` (12px) for buttons, `rounded-2xl` (16px) for cards, `rounded-3xl` (20px) for modals
|
|
484
|
+
- Personality: friendly, modern, approachable, consumer
|
|
485
|
+
- Best for: consumer apps, social platforms, health/wellness, education
|
|
486
|
+
- Why: rounded corners reduce visual tension. Psychologically, humans prefer curved shapes over angular ones (studies by Bar & Neta, 2006) because sharp corners trigger a threat response. Rounded corners signal safety and approachability.
|
|
487
|
+
|
|
488
|
+
**Full (--radius: 1.25-1.5rem / 20-24px, pill shapes for buttons):**
|
|
489
|
+
- Components: `rounded-full` for buttons, `rounded-3xl` (24px) for cards, `rounded-4xl` for containers
|
|
490
|
+
- Personality: playful, bold, consumer, distinctive
|
|
491
|
+
- Best for: lifestyle apps, creative tools, social apps targeting younger audiences
|
|
492
|
+
- Why: pill-shaped buttons and aggressively rounded cards are a strong visual statement. This says "we're different" — which is powerful when intentional but distracting when accidental. Only recommend for products where visual personality is a competitive advantage.
|
|
493
|
+
|
|
494
|
+
#### Component-Specific Radius Mapping
|
|
495
|
+
|
|
496
|
+
Not every component uses the same radius. Define which components get which:
|
|
497
|
+
|
|
498
|
+
| Component | Sharp | Moderate | Round | Full |
|
|
499
|
+
|-----------|-------|----------|-------|------|
|
|
500
|
+
| Buttons | `rounded-sm` | `rounded-lg` | `rounded-xl` | `rounded-full` |
|
|
501
|
+
| Input fields | `rounded-sm` | `rounded-md` | `rounded-lg` | `rounded-xl` |
|
|
502
|
+
| Cards | `rounded-md` | `rounded-lg` | `rounded-2xl` | `rounded-3xl` |
|
|
503
|
+
| Modals/Dialogs | `rounded-md` | `rounded-xl` | `rounded-2xl` | `rounded-3xl` |
|
|
504
|
+
| Badges/Tags | `rounded-sm` | `rounded-md` | `rounded-full` | `rounded-full` |
|
|
505
|
+
| Avatars | `rounded-md` | `rounded-full` | `rounded-full` | `rounded-full` |
|
|
506
|
+
| Tooltips | `rounded-sm` | `rounded-md` | `rounded-lg` | `rounded-xl` |
|
|
507
|
+
| Dropdowns | `rounded-md` | `rounded-lg` | `rounded-xl` | `rounded-2xl` |
|
|
508
|
+
|
|
509
|
+
*Why components scale differently:* Buttons and badges are small — aggressive rounding at small sizes creates pill shapes naturally. Cards and modals are large — the same radius value that looks rounded on a button looks barely curved on a card. The mapping ensures consistent perceived roundness across different-sized components.
|
|
510
|
+
|
|
511
|
+
#### Border Philosophy
|
|
512
|
+
|
|
513
|
+
Borders are the most overused visual element in UI design. Every line on screen competes for attention with the content it's supposed to frame. Define the product's border strategy:
|
|
514
|
+
|
|
515
|
+
**"No-line" approach (Google Material Design / Apple approach):**
|
|
516
|
+
- Boundaries between elements come from tonal shifts (background color differences) and shadows, not lines
|
|
517
|
+
- Cards separate from background through elevation (shadow) or surface color difference
|
|
518
|
+
- Sections separate through whitespace and heading hierarchy
|
|
519
|
+
- When to use: clean, modern, content-focused interfaces
|
|
520
|
+
- Why: lines are visual noise. Every border is a distraction from content. When you remove borders, you force the design to use spacing and color to create hierarchy — which results in a cleaner, more intentional layout.
|
|
521
|
+
|
|
522
|
+
**"Intentional lines" approach (GitHub / Linear approach):**
|
|
523
|
+
- Borders appear only when they serve a specific purpose: separating interactive elements (table rows), creating containment (input fields), or providing a visual stop (section dividers)
|
|
524
|
+
- Border color is very subtle (low opacity) to avoid competing with content
|
|
525
|
+
- When to use: information-dense interfaces where spatial separation alone isn't sufficient
|
|
526
|
+
- Why: in data-dense UIs, removing all borders creates visual soup — elements blend together. Intentional borders provide just enough structure without the visual weight of a fully-bordered design.
|
|
527
|
+
|
|
528
|
+
**"Ghost border" fallback for accessibility:**
|
|
529
|
+
- Even in no-line designs, add a very low opacity outline (2-3%) for accessibility
|
|
530
|
+
- This ensures that color-blind users and those with contrast sensitivity can still perceive boundaries
|
|
531
|
+
- Implementation: `border: 1px solid oklch(0 0 0 / 3%)` (light mode) or `border: 1px solid oklch(1 0 0 / 5%)` (dark mode)
|
|
532
|
+
- Why: the WCAG standard for non-text contrast (1.4.11) requires a 3:1 ratio for UI component boundaries. Ghost borders provide this without visible lines for most users.
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
### Phase 5.5: Layout & Responsive Behavior
|
|
537
|
+
|
|
538
|
+
Define how the design system adapts across viewport sizes.
|
|
539
|
+
|
|
540
|
+
**Grid System:**
|
|
541
|
+
- Container max-width (typically 1280px or 1440px for desktop)
|
|
542
|
+
- Column count (12-column for flexibility, or simpler 4/8 for constrained layouts)
|
|
543
|
+
- Gutter width (derived from base spacing unit — typically 1rem or 1.5rem)
|
|
544
|
+
- Content max-width for readability (65ch for prose, full-width for dashboards)
|
|
545
|
+
|
|
546
|
+
**Breakpoints:**
|
|
547
|
+
Define responsive thresholds aligned with Tailwind's defaults or custom:
|
|
548
|
+
- **Mobile:** < 640px (`sm`) — single column, full-width elements, stacked navigation
|
|
549
|
+
- **Tablet:** 640px – 1024px (`sm` to `lg`) — 2-column grids, sidebar may collapse
|
|
550
|
+
- **Desktop:** 1024px – 1440px (`lg` to `2xl`) — full layout, sidebar expanded, multi-column
|
|
551
|
+
- **Large:** > 1440px — content centered, max-width constrains, generous margins
|
|
552
|
+
|
|
553
|
+
**Touch Targets:**
|
|
554
|
+
- Minimum 44x44px (WCAG AA), recommended 48x48px
|
|
555
|
+
- Interactive elements must have sufficient spacing to prevent mis-taps
|
|
556
|
+
- On mobile, CTAs should be full-width and thumb-reachable
|
|
557
|
+
|
|
558
|
+
**Responsive Component Behaviors:**
|
|
559
|
+
Document how each major component type adapts:
|
|
560
|
+
|
|
561
|
+
| Component | Mobile | Tablet | Desktop |
|
|
562
|
+
|-----------|--------|--------|---------|
|
|
563
|
+
| Sidebar | Hidden (hamburger menu) | Icon-only collapsed | Full expanded |
|
|
564
|
+
| Modals/Dialogs | Full-screen with slide-up | Centered, max-w-lg | Centered, max-w-md/lg |
|
|
565
|
+
| Navigation | Bottom tab bar or hamburger | Horizontal, condensed | Full horizontal with labels |
|
|
566
|
+
| Card Grid | 1 column, full width | 2 columns | 3-4 columns |
|
|
567
|
+
| Tables | Horizontal scroll or card view | Horizontal scroll | Full table |
|
|
568
|
+
| CTAs | Full width, sticky bottom | Auto width | Auto width |
|
|
569
|
+
| Forms | Single column, stacked | Single column | Optional 2-column for short fields |
|
|
570
|
+
| Page Header | Stacked (title above action) | Side-by-side | Side-by-side |
|
|
571
|
+
|
|
572
|
+
**Whitespace Scaling:**
|
|
573
|
+
- Section margins increase with viewport: 2rem (mobile) → 4rem (tablet) → 6-8rem (desktop)
|
|
574
|
+
- Card padding scales: p-4 (mobile) → p-6 (desktop)
|
|
575
|
+
- Typography may shift: text-sm body (mobile) → text-base (desktop)
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
### Phase 6: Component Styling Guidelines
|
|
580
|
+
|
|
581
|
+
**Goal:** Define specific visual treatment for every major component type, ensuring consistency and eliminating "how should this look?" decisions during development.
|
|
582
|
+
|
|
583
|
+
**Announce framework:** "Now I'll define how each component type should look in your design system. This goes deeper than just colors and rounding — I'll specify hover states, focus behavior, spacing conventions, and how variants relate to each other. These guidelines ensure that anyone building components produces consistent results without needing to reference screenshots."
|
|
584
|
+
|
|
585
|
+
#### Buttons
|
|
586
|
+
|
|
587
|
+
Buttons are the primary interactive element. Their styling communicates interactivity, hierarchy, and state.
|
|
588
|
+
|
|
589
|
+
**Primary button:**
|
|
590
|
+
- Background: `bg-primary`, text: `text-primary-foreground`
|
|
591
|
+
- Gradient vs flat? Decision based on personality:
|
|
592
|
+
- Flat (single color) -> clean, professional, developer-friendly
|
|
593
|
+
- Subtle gradient (2-3% lightness shift top to bottom) -> adds depth without flashiness
|
|
594
|
+
- Bold gradient (cross-hue, e.g., primary to accent) -> playful, consumer, high-energy
|
|
595
|
+
- Hover: darken background 8-12% (e.g., `bg-primary/90` or adjust oklch lightness)
|
|
596
|
+
- Active (pressed): darken further, slight scale reduction (`scale-[0.98]`)
|
|
597
|
+
- Focus: visible focus ring using `--ring` token, 2px offset
|
|
598
|
+
- Disabled: 50% opacity, `cursor-not-allowed`
|
|
599
|
+
|
|
600
|
+
**Secondary button:**
|
|
601
|
+
- Background: `bg-secondary`, text: `text-secondary-foreground`
|
|
602
|
+
- Lower visual weight than primary — it should clearly be "not the main action"
|
|
603
|
+
- Hover: subtle background shift toward primary tint
|
|
604
|
+
- Border: optional 1px border for definition in no-line designs
|
|
605
|
+
|
|
606
|
+
**Ghost/outline button:**
|
|
607
|
+
- Background: transparent, border: 1px `border-border`
|
|
608
|
+
- Hover: `bg-accent` background fill (ghost becomes solid on hover)
|
|
609
|
+
- This is the "de-emphasized" action — use for secondary or tertiary actions
|
|
610
|
+
- The hover state transition should be fast (100-150ms) so it feels responsive
|
|
611
|
+
|
|
612
|
+
**Destructive button:**
|
|
613
|
+
- Background: `bg-destructive`, text: white
|
|
614
|
+
- Reserve for irreversible actions (delete, remove, cancel subscription)
|
|
615
|
+
- Never place next to a primary button at the same visual weight — the destructive action should be visually subordinate unless it IS the primary action (e.g., a delete confirmation modal)
|
|
616
|
+
|
|
617
|
+
**Size scale:**
|
|
618
|
+
|
|
619
|
+
| Size | Padding | Height | Font Size | Icon Size |
|
|
620
|
+
|------|---------|--------|-----------|-----------|
|
|
621
|
+
| sm | `px-3 py-1.5` | 32px | `text-sm` | 16px |
|
|
622
|
+
| default | `px-4 py-2` | 40px | `text-sm` | 18px |
|
|
623
|
+
| lg | `px-6 py-2.5` | 44px | `text-base` | 20px |
|
|
624
|
+
| icon | `p-2` | 40px | — | 20px |
|
|
625
|
+
|
|
626
|
+
**Icon alignment:** icons in buttons sit 8px from text (gap-2). Left-aligned icons are for actions ("Save", "Download"). Right-aligned icons are for navigation ("Next", "Open"). Icon-only buttons must have an `aria-label`.
|
|
627
|
+
|
|
628
|
+
#### Cards
|
|
629
|
+
|
|
630
|
+
Cards are the primary container for grouped content.
|
|
631
|
+
|
|
632
|
+
- Surface: `bg-card text-card-foreground`
|
|
633
|
+
- Shadow vs border: based on border philosophy (see Phase 5)
|
|
634
|
+
- Shadow approach: `shadow-sm` for default, `shadow-md` on hover (if interactive)
|
|
635
|
+
- Border approach: `border border-border` with `rounded-lg`
|
|
636
|
+
- Tonal approach: card is a step lighter/darker than background, no shadow or border
|
|
637
|
+
- Rounding: use the component-specific radius from Phase 5
|
|
638
|
+
- Padding: `p-6` default (24px). Header/content/footer: `px-6 py-4` for each section
|
|
639
|
+
- Interactive cards: add `hover:shadow-md transition-shadow` and `cursor-pointer`
|
|
640
|
+
- Header: `font-semibold text-lg` with `pb-2` or a bottom border for separation
|
|
641
|
+
- Footer: `pt-4` with optional top border, typically contains actions aligned right
|
|
642
|
+
|
|
643
|
+
#### Inputs
|
|
644
|
+
|
|
645
|
+
Inputs are used constantly — their styling affects the entire feel of forms.
|
|
646
|
+
|
|
647
|
+
- **Fill vs outline style:**
|
|
648
|
+
- Outline (default): `border border-input bg-transparent` — clean, traditional, works everywhere
|
|
649
|
+
- Fill: `bg-muted border-transparent` — modern, reduces visual noise, works well when there are many fields
|
|
650
|
+
- Choice depends on form density: outline for 1-3 fields, fill for long forms
|
|
651
|
+
|
|
652
|
+
- **Focus state:** the focus state is THE most important input styling decision. It tells users where they are.
|
|
653
|
+
- Ring approach: `focus:ring-2 ring-ring ring-offset-2` — clear, accessible, standard
|
|
654
|
+
- Border glow: `focus:border-primary focus:shadow-[0_0_0_3px_var(--primary)/15%]` — softer, modern
|
|
655
|
+
- Background shift: `focus:bg-accent` — subtle, minimal, clean
|
|
656
|
+
|
|
657
|
+
- **Label placement:**
|
|
658
|
+
- Above (default): label sits above the input with `mb-1.5` spacing. Best for most forms.
|
|
659
|
+
- Floating: label inside the input that floats up on focus. Visually elegant but creates accessibility issues — only use with careful ARIA labeling.
|
|
660
|
+
- Inline: label and input on the same line. Only for very short forms (login, search).
|
|
661
|
+
|
|
662
|
+
- **Error state:**
|
|
663
|
+
- Border: `border-destructive` replaces the normal border
|
|
664
|
+
- Text: error message below in `text-destructive text-sm`
|
|
665
|
+
- Background tint: optional `bg-destructive/5` for emphasis on the field itself
|
|
666
|
+
- Icon: optional error icon inside the input (right-aligned)
|
|
667
|
+
|
|
668
|
+
- **Placeholder:** `text-muted-foreground` — never use placeholder as a label replacement. Placeholder text disappears on input, which means users lose context after typing.
|
|
669
|
+
|
|
670
|
+
#### Modals/Dialogs
|
|
671
|
+
|
|
672
|
+
Modals interrupt the user's flow — they should feel important but not aggressive.
|
|
673
|
+
|
|
674
|
+
- **Backdrop:** `bg-black/50` with optional `backdrop-blur-sm`
|
|
675
|
+
- Higher blur (backdrop-blur-md) for a frosted glass effect — modern, premium
|
|
676
|
+
- Lower opacity (bg-black/30) for less interruption — maintains context awareness
|
|
677
|
+
- The backdrop click-to-dismiss behavior should match the border philosophy: dismissive (casual) vs protected (enterprise)
|
|
678
|
+
|
|
679
|
+
- **Shadow depth:** `shadow-xl` or `shadow-2xl` — modals are the highest elevation surface
|
|
680
|
+
- **Max width:** `max-w-md` (448px) for confirmations, `max-w-lg` (512px) for forms, `max-w-2xl` (672px) for complex content
|
|
681
|
+
- **Padding:** `p-6` for content, `px-6 py-4` for header and footer
|
|
682
|
+
- **Entry animation:** fade-in + subtle scale (0.95 -> 1.0) over 200ms with ease-out
|
|
683
|
+
- **Exit animation:** fade-out over 150ms — exits should be faster than entrances
|
|
684
|
+
|
|
685
|
+
#### Navigation/Sidebar
|
|
686
|
+
|
|
687
|
+
Navigation sets the persistent visual frame for the entire application.
|
|
688
|
+
|
|
689
|
+
- **Active state indicator:**
|
|
690
|
+
- Background fill: `bg-sidebar-accent text-sidebar-accent-foreground` — clear, works everywhere
|
|
691
|
+
- Left border: `border-l-2 border-sidebar-primary` — minimal, editorial
|
|
692
|
+
- Icon fill: active icon uses `text-sidebar-primary`, inactive uses `text-sidebar-foreground/70`
|
|
693
|
+
- Which to use depends on the sidebar width and information density
|
|
694
|
+
|
|
695
|
+
- **Collapsed behavior:**
|
|
696
|
+
- Icons only with tooltips on hover
|
|
697
|
+
- Active state still visible (icon color or background dot)
|
|
698
|
+
- Transition: 200ms ease for width change
|
|
699
|
+
|
|
700
|
+
- **Section headers:** `text-xs font-medium uppercase tracking-wide text-sidebar-foreground/50` — section headers should recede, not compete with navigation items
|
|
701
|
+
|
|
702
|
+
- **Hover state:** `bg-sidebar-accent/50` — a lighter version of the active background, signaling interactivity without implying selection
|
|
703
|
+
|
|
704
|
+
#### Badges/Tags
|
|
705
|
+
|
|
706
|
+
Small visual indicators with multiple semantic variants.
|
|
707
|
+
|
|
708
|
+
- Default: `bg-secondary text-secondary-foreground` — neutral, informational
|
|
709
|
+
- Primary: `bg-primary/10 text-primary` — branded, highlighted (uses transparent primary background so it adapts to surface)
|
|
710
|
+
- Destructive: `bg-destructive/10 text-destructive` — errors, overdue items
|
|
711
|
+
- Outline: `border border-border bg-transparent` — subtle, minimal
|
|
712
|
+
- Size: `px-2.5 py-0.5 text-xs` — badges should be compact
|
|
713
|
+
- Rounding: follow the component-specific radius from Phase 5
|
|
714
|
+
|
|
715
|
+
#### Tables
|
|
716
|
+
|
|
717
|
+
Data presentation with clear hierarchy and comfortable density.
|
|
718
|
+
|
|
719
|
+
- **Header row:** `bg-muted/50 font-medium text-muted-foreground text-sm` — headers should recede visually. They're labels, not content.
|
|
720
|
+
- **Row hover:** `hover:bg-muted/30` — subtle background shift confirms the row the user is looking at
|
|
721
|
+
- **Cell padding:** `px-4 py-3` — enough breathing room for readability without wasting space
|
|
722
|
+
- **Border strategy:**
|
|
723
|
+
- Full grid: every cell bordered — traditional, high-density, data-focused
|
|
724
|
+
- Rows only: horizontal borders between rows — cleaner, modern, easier to scan
|
|
725
|
+
- Minimal: no borders, rows separated by subtle background alternation (`even:bg-muted/20`) — cleanest, works when data is sparse
|
|
726
|
+
- Choose based on data density: more data = more structure needed
|
|
727
|
+
|
|
728
|
+
#### Forms
|
|
729
|
+
|
|
730
|
+
Form layouts combining inputs, labels, and error states into coherent groups.
|
|
731
|
+
|
|
732
|
+
- **Field group spacing:** `space-y-4` (16px) between fields — enough separation for clarity without excessive scrolling
|
|
733
|
+
- **Section spacing:** `space-y-8` (32px) between form sections — clear grouping
|
|
734
|
+
- **Error state flow:** error messages appear below the field with `mt-1.5 text-sm text-destructive`, pushing content down (not overlaying)
|
|
735
|
+
- **Help text:** `mt-1.5 text-sm text-muted-foreground` — same position as errors but neutral color
|
|
736
|
+
- **Required indicator:** red asterisk after label text `<span class="text-destructive">*</span>` — universal convention, don't reinvent this
|
|
737
|
+
- **Submit button placement:** right-aligned for single-column forms, full-width for mobile or card-embedded forms
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
### Phase 7: Shadows & Depth
|
|
742
|
+
|
|
743
|
+
**Goal:** Define the shadow scale that creates visual hierarchy — the perception of elements floating above or below others.
|
|
744
|
+
|
|
745
|
+
**Announce framework:** "Shadows create the illusion of depth. Used well, they communicate hierarchy instantly — users know a dropdown floats above a card without thinking about it. I'll define the full shadow scale with values tuned to your design personality."
|
|
746
|
+
|
|
747
|
+
#### Shadow Scale
|
|
748
|
+
|
|
749
|
+
Define `--shadow-xs` through `--shadow-2xl` in the `@theme {}` block:
|
|
750
|
+
|
|
751
|
+
**Ambient/diffused style (modern, subtle):**
|
|
752
|
+
```css
|
|
753
|
+
--shadow-xs: 0 1px 2px oklch(0 0 0 / 3%);
|
|
754
|
+
--shadow-sm: 0 1px 3px oklch(0 0 0 / 5%), 0 1px 2px oklch(0 0 0 / 3%);
|
|
755
|
+
--shadow: 0 4px 6px oklch(0 0 0 / 5%), 0 2px 4px oklch(0 0 0 / 3%);
|
|
756
|
+
--shadow-md: 0 6px 10px oklch(0 0 0 / 5%), 0 2px 4px oklch(0 0 0 / 2%);
|
|
757
|
+
--shadow-lg: 0 10px 15px oklch(0 0 0 / 5%), 0 4px 6px oklch(0 0 0 / 3%);
|
|
758
|
+
--shadow-xl: 0 20px 25px oklch(0 0 0 / 5%), 0 8px 10px oklch(0 0 0 / 2%);
|
|
759
|
+
--shadow-2xl: 0 25px 50px oklch(0 0 0 / 12%);
|
|
760
|
+
```
|
|
761
|
+
*When to use:* clean, professional, minimal designs. Low-opacity, large-spread shadows feel airy and modern.
|
|
762
|
+
|
|
763
|
+
**Sharp/dramatic style (bold, high-contrast):**
|
|
764
|
+
```css
|
|
765
|
+
--shadow-xs: 0 1px 2px oklch(0 0 0 / 8%);
|
|
766
|
+
--shadow-sm: 0 2px 4px oklch(0 0 0 / 10%);
|
|
767
|
+
--shadow: 0 4px 8px oklch(0 0 0 / 12%);
|
|
768
|
+
--shadow-md: 0 6px 12px oklch(0 0 0 / 12%);
|
|
769
|
+
--shadow-lg: 0 12px 24px oklch(0 0 0 / 15%);
|
|
770
|
+
--shadow-xl: 0 20px 40px oklch(0 0 0 / 15%);
|
|
771
|
+
--shadow-2xl: 0 25px 50px oklch(0 0 0 / 25%);
|
|
772
|
+
```
|
|
773
|
+
*When to use:* bold, high-personality designs. Higher opacity and tighter spread create more defined edges and stronger depth perception.
|
|
774
|
+
|
|
775
|
+
**Brand-tinted style (premium, distinctive):**
|
|
776
|
+
- Replace `oklch(0 0 0 / N%)` with tinted shadows using the primary hue at very low chroma
|
|
777
|
+
- Example: `oklch(0.3 0.02 264 / 8%)` instead of pure black
|
|
778
|
+
- *When to use:* premium products where every detail should reinforce the brand. The tint is subtle — most users won't consciously notice it, but it contributes to a cohesive feeling.
|
|
779
|
+
|
|
780
|
+
#### Shadow Usage Guide
|
|
781
|
+
|
|
782
|
+
| Shadow | Usage | Example Components |
|
|
783
|
+
|--------|-------|-------------------|
|
|
784
|
+
| `shadow-xs` | Barely perceptible depth | Inline buttons, tags pressed into surface |
|
|
785
|
+
| `shadow-sm` | Default card elevation | Cards at rest, container sections |
|
|
786
|
+
| `shadow` | Default interactive elevation | Buttons, input focus glow |
|
|
787
|
+
| `shadow-md` | Moderate emphasis | Hovered cards, active dropdowns |
|
|
788
|
+
| `shadow-lg` | Floating elements | Dropdown menus, popovers, tooltips |
|
|
789
|
+
| `shadow-xl` | High-priority floating | Modals, command palettes |
|
|
790
|
+
| `shadow-2xl` | Maximum emphasis | Full-page overlays, onboarding modals |
|
|
791
|
+
|
|
792
|
+
#### Inset Shadows
|
|
793
|
+
|
|
794
|
+
For elements that feel pressed into the surface (input fields, embedded panels):
|
|
795
|
+
```css
|
|
796
|
+
--shadow-inset: inset 0 2px 4px oklch(0 0 0 / 5%);
|
|
797
|
+
```
|
|
798
|
+
*Use sparingly.* Inset shadows create a "pressed" effect that works for input fields in fill style but looks odd on most other elements.
|
|
799
|
+
|
|
800
|
+
#### Glassmorphism Recipe (if applicable)
|
|
801
|
+
|
|
802
|
+
For products with a modern, layered aesthetic:
|
|
803
|
+
```css
|
|
804
|
+
backdrop-filter: blur(12px);
|
|
805
|
+
background: oklch(1 0 0 / 70%); /* light mode */
|
|
806
|
+
background: oklch(0.15 0 0 / 70%); /* dark mode */
|
|
807
|
+
border: 1px solid oklch(1 0 0 / 10%);
|
|
808
|
+
```
|
|
809
|
+
*When to use:* sparingly. Glassmorphism is visually striking but computationally expensive (backdrop-blur triggers compositing layers) and can create readability issues. Best for navigation bars, sidebars, or floating toolbars — NOT for content-heavy cards or modal backdrops.
|
|
810
|
+
|
|
811
|
+
---
|
|
812
|
+
|
|
813
|
+
### Phase 8: Animation & Motion
|
|
814
|
+
|
|
815
|
+
**Goal:** Define how things move — transition timing, easing curves, and keyframe animations that match the product personality.
|
|
816
|
+
|
|
817
|
+
**Announce framework:** "Motion is the personality of your interface in action. Fast, sharp transitions feel efficient and precise. Slow, bouncy transitions feel playful and friendly. I'll define the timing scale, easing curves, and custom animations, all as Tailwind @theme variables and @keyframes."
|
|
818
|
+
|
|
819
|
+
#### Transition Duration Scale
|
|
820
|
+
|
|
821
|
+
Define via `@theme {}`:
|
|
822
|
+
|
|
823
|
+
| Token | Value | Usage |
|
|
824
|
+
|-------|-------|-------|
|
|
825
|
+
| `--duration-fast` | 100ms | Hover states, color changes, micro-interactions |
|
|
826
|
+
| `--duration-normal` | 200ms | Focus states, small element transitions, toggles |
|
|
827
|
+
| `--duration-slow` | 300ms | Modal entrances, sidebar expansion, page transitions |
|
|
828
|
+
| `--duration-slower` | 500ms | Complex multi-step animations, onboarding sequences |
|
|
829
|
+
|
|
830
|
+
*Why these values:* Human perception research shows that transitions under 100ms feel instant, 100-300ms feel responsive, and over 300ms feel deliberate. The scale maps to interaction urgency: hover states need instant feedback (fast), modals can take a beat to establish presence (slow).
|
|
831
|
+
|
|
832
|
+
#### Custom Easing Curves
|
|
833
|
+
|
|
834
|
+
```css
|
|
835
|
+
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
836
|
+
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
837
|
+
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
838
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
839
|
+
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
840
|
+
--ease-smooth: cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
| Curve | Personality | When to Use |
|
|
844
|
+
|-------|-------------|-------------|
|
|
845
|
+
| `ease-out` | Professional, confident | Entrances — elements arrive confidently and settle |
|
|
846
|
+
| `ease-in-out` | Balanced, smooth | State transitions — toggles, color changes |
|
|
847
|
+
| `ease-in` | Departing, retreating | Exits — elements accelerate away (rarely used alone) |
|
|
848
|
+
| `ease-spring` | Playful, energetic | Fun interactions — toggle switches, badge appearance (only if personality fits) |
|
|
849
|
+
| `ease-bounce` | Very playful, attention-grabbing | Notification badges, celebration moments (use very sparingly) |
|
|
850
|
+
| `ease-smooth` | Subtle, refined | Default for most transitions — unnoticeable in the best way |
|
|
851
|
+
|
|
852
|
+
#### Custom @keyframes
|
|
853
|
+
|
|
854
|
+
Define these in the `@theme {}` block:
|
|
855
|
+
|
|
856
|
+
```css
|
|
857
|
+
@keyframes fade-in {
|
|
858
|
+
from { opacity: 0; }
|
|
859
|
+
to { opacity: 1; }
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
@keyframes fade-out {
|
|
863
|
+
from { opacity: 1; }
|
|
864
|
+
to { opacity: 0; }
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
@keyframes slide-up {
|
|
868
|
+
from { transform: translateY(8px); opacity: 0; }
|
|
869
|
+
to { transform: translateY(0); opacity: 1; }
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
@keyframes slide-down {
|
|
873
|
+
from { transform: translateY(-8px); opacity: 0; }
|
|
874
|
+
to { transform: translateY(0); opacity: 1; }
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
@keyframes slide-in-from-left {
|
|
878
|
+
from { transform: translateX(-100%); }
|
|
879
|
+
to { transform: translateX(0); }
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
@keyframes slide-in-from-right {
|
|
883
|
+
from { transform: translateX(100%); }
|
|
884
|
+
to { transform: translateX(0); }
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
@keyframes slide-in-from-top {
|
|
888
|
+
from { transform: translateY(-100%); }
|
|
889
|
+
to { transform: translateY(0); }
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
@keyframes slide-in-from-bottom {
|
|
893
|
+
from { transform: translateY(100%); }
|
|
894
|
+
to { transform: translateY(0); }
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
@keyframes scale-in {
|
|
898
|
+
from { transform: scale(0.95); opacity: 0; }
|
|
899
|
+
to { transform: scale(1); opacity: 1; }
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
@keyframes spin {
|
|
903
|
+
from { transform: rotate(0deg); }
|
|
904
|
+
to { transform: rotate(360deg); }
|
|
905
|
+
}
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
Map to animation utilities:
|
|
909
|
+
|
|
910
|
+
| Animation | Keyframe | Duration | Easing | Usage |
|
|
911
|
+
|-----------|----------|----------|--------|-------|
|
|
912
|
+
| `animate-fade-in` | `fade-in` | 200ms | ease-out | General element appearance |
|
|
913
|
+
| `animate-fade-out` | `fade-out` | 150ms | ease-in | General element disappearance |
|
|
914
|
+
| `animate-slide-up` | `slide-up` | 200ms | ease-out | Dropdown menus, tooltips from below |
|
|
915
|
+
| `animate-slide-down` | `slide-down` | 200ms | ease-out | Dropdown menus, tooltips from above |
|
|
916
|
+
| `animate-scale-in` | `scale-in` | 200ms | ease-out | Modals, popovers, dialog entrances |
|
|
917
|
+
| `animate-spin` | `spin` | 1000ms | linear | Loading spinners |
|
|
918
|
+
|
|
919
|
+
#### What Animates vs What Doesn't
|
|
920
|
+
|
|
921
|
+
**Always animate:**
|
|
922
|
+
- Modal/dialog entrances and exits
|
|
923
|
+
- Dropdown/popover appearance
|
|
924
|
+
- Focus ring transitions
|
|
925
|
+
- Hover state changes on interactive elements
|
|
926
|
+
- Sidebar collapse/expand
|
|
927
|
+
- Toast/notification entrances
|
|
928
|
+
|
|
929
|
+
**Never animate:**
|
|
930
|
+
- Page load (content should render instantly, not fade in piecemeal)
|
|
931
|
+
- Scrolling behavior (native scroll is always better than JS scroll animations)
|
|
932
|
+
- Text content changes (changing text should be instant, not crossfade)
|
|
933
|
+
- Error state appearance (errors need immediate attention, not a leisurely fade-in)
|
|
934
|
+
|
|
935
|
+
**Conditionally animate (based on product personality):**
|
|
936
|
+
- Card hover elevation changes (subtle lift effect)
|
|
937
|
+
- Button press feedback (scale down on click)
|
|
938
|
+
- Navigation transitions between routes
|
|
939
|
+
- Data visualization entrance (chart bars growing, lines drawing)
|
|
940
|
+
|
|
941
|
+
#### Motion Reduction Strategy
|
|
942
|
+
|
|
943
|
+
Always respect `prefers-reduced-motion`:
|
|
944
|
+
|
|
945
|
+
```css
|
|
946
|
+
@media (prefers-reduced-motion: reduce) {
|
|
947
|
+
*, *::before, *::after {
|
|
948
|
+
animation-duration: 0.01ms !important;
|
|
949
|
+
animation-iteration-count: 1 !important;
|
|
950
|
+
transition-duration: 0.01ms !important;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
*Why this matters:* Motion sensitivity affects approximately 35% of adults to some degree. Vestibular disorders, migraine sensitivity, and other conditions make animation physically uncomfortable. The `prefers-reduced-motion` media query respects the user's OS-level setting. Setting durations to near-zero (not zero) ensures completion callbacks still fire.
|
|
956
|
+
|
|
957
|
+
---
|
|
958
|
+
|
|
959
|
+
### Phase 9: Generate Outputs
|
|
960
|
+
|
|
961
|
+
**Goal:** Produce the two deliverables — the design system document and the actual CSS file.
|
|
962
|
+
|
|
963
|
+
#### Step 1: Write `docs/design/design-system.md`
|
|
964
|
+
|
|
965
|
+
The comprehensive reference document. Follows the structure defined in the Output Format section below. Every design decision is annotated with reasoning — this document is both a reference and a teaching tool.
|
|
966
|
+
|
|
967
|
+
#### Step 2: Write `docs/design/shared-styles.css`
|
|
968
|
+
|
|
969
|
+
The actual Tailwind v4 CSS file. Must match the template structure EXACTLY:
|
|
970
|
+
|
|
971
|
+
```css
|
|
972
|
+
@import "tailwindcss";
|
|
973
|
+
@import "tw-animate-css";
|
|
974
|
+
@import "shadcn/tailwind.css";
|
|
975
|
+
@import "tailwind-scrollbar-hide/v4";
|
|
976
|
+
|
|
977
|
+
@custom-variant dark (&:is(.dark *));
|
|
978
|
+
|
|
979
|
+
@theme inline {
|
|
980
|
+
/* Color token -> Tailwind utility mappings */
|
|
981
|
+
/* Radius scale */
|
|
982
|
+
/* Font family variables */
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
@theme {
|
|
986
|
+
/* Shadow scale */
|
|
987
|
+
/* Easing curves */
|
|
988
|
+
/* Animation definitions */
|
|
989
|
+
/* Typography overrides (if any) */
|
|
990
|
+
/* @keyframes */
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
:root {
|
|
994
|
+
/* All light mode CSS variables in oklch */
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.dark {
|
|
998
|
+
/* All dark mode CSS variables in oklch */
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
@layer base {
|
|
1002
|
+
* {
|
|
1003
|
+
@apply border-border outline-ring/50;
|
|
1004
|
+
}
|
|
1005
|
+
body {
|
|
1006
|
+
@apply bg-background text-foreground;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
This structure is non-negotiable — it must be a drop-in replacement for the Tailwind v4 blueprint's generic `shared-styles.css`.
|
|
1012
|
+
|
|
1013
|
+
#### Step 3: Update `.project-context.md`
|
|
1014
|
+
|
|
1015
|
+
Append the design system entry under `## Installed Blueprints` (or `## Product Discovery` if that section is more appropriate).
|
|
1016
|
+
|
|
1017
|
+
#### Step 4: Offer Sync (if applicable)
|
|
1018
|
+
|
|
1019
|
+
If `config/tailwind-config/shared-styles.css` (monorepo) or `src/styles/shared-styles.css` (single-repo) already exists from a previous tailwind scaffold, offer to sync immediately:
|
|
1020
|
+
|
|
1021
|
+
"I see you already have a tailwind config scaffolded. Would you like me to replace the generic tokens with your new design system tokens now? This will immediately update how all your components look."
|
|
1022
|
+
|
|
1023
|
+
#### Step 5: Suggest Component Improvements
|
|
1024
|
+
|
|
1025
|
+
Based on the design system decisions, suggest specific improvements to existing UI components:
|
|
1026
|
+
- "Your buttons would benefit from the rounded-xl radius we chose — the default rounded-md doesn't match the friendly personality."
|
|
1027
|
+
- "Consider adding a subtle hover:shadow-md to your cards — the current flat cards don't use the depth system we defined."
|
|
1028
|
+
- "Your sidebar should use the sidebar-specific tokens — right now it's using generic background colors."
|
|
1029
|
+
|
|
1030
|
+
---
|
|
1031
|
+
|
|
1032
|
+
## Output Format
|
|
1033
|
+
|
|
1034
|
+
### design-system.md Structure
|
|
1035
|
+
|
|
1036
|
+
```markdown
|
|
1037
|
+
# Design System — {Product Name}
|
|
1038
|
+
|
|
1039
|
+
## Creative North Star
|
|
1040
|
+
[One paragraph defining the visual identity — the "north star" that guides every decision]
|
|
1041
|
+
|
|
1042
|
+
## Color Philosophy
|
|
1043
|
+
|
|
1044
|
+
### Palette Rationale
|
|
1045
|
+
[Why these colors for this product/audience — competitive analysis, audience expectations, personality alignment]
|
|
1046
|
+
|
|
1047
|
+
### Surface Hierarchy
|
|
1048
|
+
[How surfaces layer: base -> container -> card -> elevated, with light/dark mode differences]
|
|
1049
|
+
|
|
1050
|
+
### Dark Mode Strategy
|
|
1051
|
+
[How colors adapt — not just invert. Chroma reduction, lightness stepping, border opacity]
|
|
1052
|
+
|
|
1053
|
+
### Color Reference
|
|
1054
|
+
| Token | Light Value | Dark Value | Usage | Tailwind Class |
|
|
1055
|
+
|-------|-------------|------------|-------|----------------|
|
|
1056
|
+
| --primary | oklch(...) | oklch(...) | Brand color, primary buttons | bg-primary |
|
|
1057
|
+
| ... | ... | ... | ... | ... |
|
|
1058
|
+
|
|
1059
|
+
## Typography
|
|
1060
|
+
|
|
1061
|
+
### Font Pairing
|
|
1062
|
+
[Display + body fonts with reasoning: why this pairing, what it communicates, how it serves the audience]
|
|
1063
|
+
|
|
1064
|
+
### Type Scale
|
|
1065
|
+
| Size | Value | Line Height | Usage | Tailwind Class |
|
|
1066
|
+
|------|-------|-------------|-------|----------------|
|
|
1067
|
+
| xs | 0.75rem | 1rem | Captions, badges | text-xs |
|
|
1068
|
+
| ... | ... | ... | ... | ... |
|
|
1069
|
+
|
|
1070
|
+
### Weight Scale
|
|
1071
|
+
| Weight | Value | Usage | Tailwind Class |
|
|
1072
|
+
|--------|-------|-------|----------------|
|
|
1073
|
+
| normal | 400 | Body text | font-normal |
|
|
1074
|
+
| ... | ... | ... | ... |
|
|
1075
|
+
|
|
1076
|
+
## Spacing & Rhythm
|
|
1077
|
+
|
|
1078
|
+
### Base Unit
|
|
1079
|
+
[What it is, why that value, how it scales]
|
|
1080
|
+
|
|
1081
|
+
### Spacing Conventions
|
|
1082
|
+
[When to use which spacing values — component padding, section gaps, page margins]
|
|
1083
|
+
|
|
1084
|
+
## Rounding
|
|
1085
|
+
|
|
1086
|
+
### Personality
|
|
1087
|
+
[Description of the rounding character and why it fits]
|
|
1088
|
+
|
|
1089
|
+
### Radius Scale
|
|
1090
|
+
| Token | Value | Usage | Tailwind Class |
|
|
1091
|
+
|-------|-------|-------|----------------|
|
|
1092
|
+
| --radius | Xrem | Base radius | -- |
|
|
1093
|
+
| sm | calc(base - 4px) | Small elements | rounded-sm |
|
|
1094
|
+
| ... | ... | ... | ... |
|
|
1095
|
+
|
|
1096
|
+
## Elevation & Depth
|
|
1097
|
+
|
|
1098
|
+
### Shadow Scale
|
|
1099
|
+
| Token | Value | Usage | Tailwind Class |
|
|
1100
|
+
|-------|-------|-------|----------------|
|
|
1101
|
+
| xs | ... | Tags, subtle depth | shadow-xs |
|
|
1102
|
+
| ... | ... | ... | ... |
|
|
1103
|
+
|
|
1104
|
+
### Border Philosophy
|
|
1105
|
+
[Lines vs tonal shifts vs shadows — when and why]
|
|
1106
|
+
|
|
1107
|
+
## Component Guidelines
|
|
1108
|
+
|
|
1109
|
+
### Buttons
|
|
1110
|
+
[Deep styling: variants, sizes, states, icon alignment, gradient/flat decision]
|
|
1111
|
+
|
|
1112
|
+
### Cards
|
|
1113
|
+
[Surface treatment, rounding, padding, hover behavior]
|
|
1114
|
+
|
|
1115
|
+
### Inputs
|
|
1116
|
+
[Fill vs outline, focus states, error states, label placement]
|
|
1117
|
+
|
|
1118
|
+
### Modals
|
|
1119
|
+
[Backdrop, shadow, animation, sizing]
|
|
1120
|
+
|
|
1121
|
+
### Navigation
|
|
1122
|
+
[Active states, collapsed behavior, section headers]
|
|
1123
|
+
|
|
1124
|
+
### Badges
|
|
1125
|
+
[Sizes, variants, color treatments]
|
|
1126
|
+
|
|
1127
|
+
### Tables
|
|
1128
|
+
[Header styling, row hover, cell padding, border strategy]
|
|
1129
|
+
|
|
1130
|
+
### Forms
|
|
1131
|
+
[Field spacing, error flow, help text, required indicators]
|
|
1132
|
+
|
|
1133
|
+
## Animation & Motion
|
|
1134
|
+
|
|
1135
|
+
### Duration Scale
|
|
1136
|
+
| Name | Value | Usage |
|
|
1137
|
+
|------|-------|-------|
|
|
1138
|
+
| fast | 100ms | Hover states |
|
|
1139
|
+
| ... | ... | ... |
|
|
1140
|
+
|
|
1141
|
+
### Easing Curves
|
|
1142
|
+
| Name | Value | Personality | Usage |
|
|
1143
|
+
|------|-------|-------------|-------|
|
|
1144
|
+
| ease-out | cubic-bezier(...) | Confident | Entrances |
|
|
1145
|
+
| ... | ... | ... | ... |
|
|
1146
|
+
|
|
1147
|
+
### Custom Animations
|
|
1148
|
+
[List of @keyframes with descriptions and usage guidance]
|
|
1149
|
+
|
|
1150
|
+
### Motion Reduction
|
|
1151
|
+
[prefers-reduced-motion strategy]
|
|
1152
|
+
|
|
1153
|
+
## Do's and Don'ts
|
|
1154
|
+
|
|
1155
|
+
### Do
|
|
1156
|
+
- Use semantic color tokens (`bg-primary`, `text-muted-foreground`) — never raw oklch or hex values in components
|
|
1157
|
+
- Test every screen in both light and dark mode before considering it done
|
|
1158
|
+
- Use `cn()` for all className composition — never concatenate strings
|
|
1159
|
+
- Reference the Creative North Star when making ambiguous design decisions
|
|
1160
|
+
- Use the shadow scale consistently: cards=shadow-sm, dropdowns=shadow-lg, modals=shadow-xl
|
|
1161
|
+
- Respect the surface layering stack — each layer gets the right elevation treatment
|
|
1162
|
+
- Use `data-slot` attributes on every component element for CSS targeting
|
|
1163
|
+
- Maintain generous whitespace — if a layout feels empty, leave it
|
|
1164
|
+
- Tint neutrals with the brand undertone — never use pure achromatic grays unless the design specifically calls for it
|
|
1165
|
+
- Use the translation table to communicate design intent in plain language
|
|
1166
|
+
|
|
1167
|
+
### Don't — Common AI Mistakes to Prevent
|
|
1168
|
+
- Never use `#000000` or pure black — use the `foreground` token (tinted dark)
|
|
1169
|
+
- Never use `#FFFFFF` directly — use the `background` token
|
|
1170
|
+
- Never use 1px solid borders to separate content sections — use tonal shifts, spacing, or ghost borders (`ring-1 ring-foreground/10`)
|
|
1171
|
+
- Never mix more than 2 typefaces on a single screen
|
|
1172
|
+
- Never center-align body text longer than 2 lines — left-align for readability
|
|
1173
|
+
- Never add shadows to elements resting on the same surface layer — shadows indicate floating
|
|
1174
|
+
- Never animate page-load content (causes layout shift) — reserve animation for user-triggered interactions
|
|
1175
|
+
- Never use generic Tailwind grays (`border-gray-200`, `bg-slate-100`) — always use semantic tokens (`border-border`, `bg-muted`)
|
|
1176
|
+
- Never create interactive elements without hover, focus, and active states
|
|
1177
|
+
- Never use `rounded-none` on interactive elements — minimum `rounded-sm`
|
|
1178
|
+
- Don't over-saturate — limit primary accent color to ~10-15% of visible screen area
|
|
1179
|
+
- Never skip the mobile viewport — every component must have a defined mobile behavior
|
|
1180
|
+
- Never hardcode breakpoint values — use Tailwind responsive prefixes (`sm:`, `md:`, `lg:`)
|
|
1181
|
+
|
|
1182
|
+
## How to Use
|
|
1183
|
+
|
|
1184
|
+
### Color Tokens in Code
|
|
1185
|
+
[Practical examples: bg-primary, text-muted-foreground, etc.]
|
|
1186
|
+
|
|
1187
|
+
### Typography in Code
|
|
1188
|
+
[Practical examples: text-lg font-semibold tracking-tight, etc.]
|
|
1189
|
+
|
|
1190
|
+
### Shadow Scale in Code
|
|
1191
|
+
[Practical examples: shadow-sm for cards, shadow-xl for modals]
|
|
1192
|
+
|
|
1193
|
+
### Radius in Code
|
|
1194
|
+
[Practical examples: rounded-lg for cards, rounded-4xl for buttons]
|
|
1195
|
+
|
|
1196
|
+
### Spacing in Code
|
|
1197
|
+
[Practical examples: p-4, gap-6, when to use which]
|
|
1198
|
+
|
|
1199
|
+
### Dark Mode
|
|
1200
|
+
[How class-based dark mode works, what to test, common mistakes]
|
|
1201
|
+
|
|
1202
|
+
### Quick Reference
|
|
1203
|
+
| What You Need | Token/Class | Example |
|
|
1204
|
+
|---------------|-------------|---------|
|
|
1205
|
+
| Brand color background | bg-primary | Primary buttons |
|
|
1206
|
+
| Subtle text | text-muted-foreground | Helper text, captions |
|
|
1207
|
+
| Card container | bg-card rounded-lg shadow-sm | Content cards |
|
|
1208
|
+
| Focus ring | ring-ring ring-2 ring-offset-2 | Keyboard focus |
|
|
1209
|
+
| ... | ... | ... |
|
|
1210
|
+
|
|
1211
|
+
### Design Language Translation
|
|
1212
|
+
|
|
1213
|
+
When communicating design intent (in reviews, in the design doc, or when prompting AI), use these translations between technical values and natural language:
|
|
1214
|
+
|
|
1215
|
+
| Technical (Tailwind) | Design Language | When to Use |
|
|
1216
|
+
|---------------------|-----------------|-------------|
|
|
1217
|
+
| `rounded-full` | Pill-shaped | Badges, tags, avatar containers |
|
|
1218
|
+
| `rounded-4xl` | Generously rounded | Buttons, search bars |
|
|
1219
|
+
| `rounded-2xl` | Softly rounded | Cards, modals |
|
|
1220
|
+
| `rounded-xl` | Gently curved | Dropdowns, popovers |
|
|
1221
|
+
| `rounded-lg` | Subtly rounded corners | Inputs, smaller containers |
|
|
1222
|
+
| `rounded-none` | Sharp, squared-off edges | Avoid on interactive elements |
|
|
1223
|
+
| `shadow-2xs` | Barely visible lift | Subtle card definition |
|
|
1224
|
+
| `shadow-sm` | Whisper-soft shadow | Resting cards |
|
|
1225
|
+
| `shadow-md` | Gentle elevation | Hovered cards |
|
|
1226
|
+
| `shadow-lg` | Noticeable depth | Dropdowns, popovers |
|
|
1227
|
+
| `shadow-xl` | Prominent floating | Modals, dialogs |
|
|
1228
|
+
| `shadow-2xl` | Dramatic elevation | Full-screen overlays |
|
|
1229
|
+
| `bg-input/30` | Subtle tinted fill | Input field backgrounds |
|
|
1230
|
+
| `ring-1 ring-foreground/10` | Ghost border | When tonal shift alone isn't enough |
|
|
1231
|
+
| `font-medium` | Confident but not heavy | Labels, navigation |
|
|
1232
|
+
| `font-semibold` | Emphatic, attention-grabbing | Headings, CTAs |
|
|
1233
|
+
| `font-bold` | Strong authority | Hero headlines |
|
|
1234
|
+
| `tracking-tight` | Compact, modern feel | Display text |
|
|
1235
|
+
| `tracking-wide` | Spacious, editorial | Uppercase labels |
|
|
1236
|
+
| `leading-relaxed` | Breathing room for readability | Long-form body text |
|
|
1237
|
+
| `leading-tight` | Dense, compact | Headlines, UI labels |
|
|
1238
|
+
| `text-muted-foreground` | Recessive, supportive | Descriptions, timestamps, metadata |
|
|
1239
|
+
| `animate-fade-in` | Gentle appearance | Page section reveals |
|
|
1240
|
+
| `animate-slide-up` | Rising entrance | Toast notifications, bottom sheets |
|
|
1241
|
+
| `ease-spring` | Bouncy, playful snap | Playful interactions |
|
|
1242
|
+
| `ease-smooth` | Refined, buttery | Professional transitions |
|
|
1243
|
+
|
|
1244
|
+
## Agent Context — Design System Quick Reference
|
|
1245
|
+
|
|
1246
|
+
*This section is formatted for AI agent consumption. When generating UI components, reference this section for quick token lookups and component recipes.*
|
|
1247
|
+
|
|
1248
|
+
### Color Map
|
|
1249
|
+
[Flat list of every token with oklch value + primary Tailwind class. One line per token. No explanations — just the mapping.]
|
|
1250
|
+
```
|
|
1251
|
+
- primary: oklch(0.488 0.243 264) → `bg-primary`, `text-primary`, `border-primary`
|
|
1252
|
+
- primary-foreground: oklch(0.97 0.014 254) → `text-primary-foreground`
|
|
1253
|
+
- background: oklch(1 0 0) → `bg-background`
|
|
1254
|
+
- foreground: oklch(0.145 0 0) → `text-foreground`
|
|
1255
|
+
[... all 31+ tokens]
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
### Component Recipes
|
|
1259
|
+
[Ready-to-paste Tailwind class combinations for common component patterns. These are the "golden paths" — the exact class strings that produce correct results.]
|
|
1260
|
+
```
|
|
1261
|
+
Primary Button: bg-primary text-primary-foreground rounded-4xl h-9 px-3 text-sm font-medium
|
|
1262
|
+
Secondary Button: bg-secondary text-secondary-foreground rounded-4xl h-9 px-3 text-sm font-medium
|
|
1263
|
+
Ghost Button: hover:bg-muted hover:text-foreground rounded-4xl h-9 px-3 text-sm font-medium
|
|
1264
|
+
Destructive Button: bg-destructive/10 text-destructive rounded-4xl h-9 px-3 text-sm font-medium
|
|
1265
|
+
Card: bg-card ring-1 ring-foreground/10 rounded-2xl p-6
|
|
1266
|
+
Card (compact): bg-card ring-1 ring-foreground/10 rounded-2xl p-4
|
|
1267
|
+
Input: bg-input/30 border-input rounded-4xl h-9 px-3 text-sm
|
|
1268
|
+
Badge: bg-primary text-primary-foreground rounded-4xl px-2 py-0.5 text-xs font-medium
|
|
1269
|
+
Separator: bg-border h-px w-full
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
### Spacing Cheat Sheet
|
|
1273
|
+
```
|
|
1274
|
+
Between form fields: gap-7
|
|
1275
|
+
Within a field (label→input→error): gap-1.5
|
|
1276
|
+
Between page sections: gap-12 or mt-12
|
|
1277
|
+
Card internal padding: p-6 (default), p-4 (compact)
|
|
1278
|
+
Page horizontal padding: px-6 (desktop), px-4 (mobile)
|
|
1279
|
+
Between cards in a grid: gap-4
|
|
1280
|
+
Between buttons in a row: gap-2
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
### Surface Layering
|
|
1284
|
+
```
|
|
1285
|
+
Page background: bg-background
|
|
1286
|
+
Sidebar: bg-sidebar
|
|
1287
|
+
Card on page: bg-card
|
|
1288
|
+
Input field: bg-input/30
|
|
1289
|
+
Popover/Dropdown: bg-popover + shadow-lg
|
|
1290
|
+
Modal backdrop: bg-black/50
|
|
1291
|
+
Modal content: bg-background + shadow-xl
|
|
1292
|
+
```
|
|
1293
|
+
|
|
1294
|
+
### Design Rules (for AI agents)
|
|
1295
|
+
```
|
|
1296
|
+
1. Always use cn() for className composition
|
|
1297
|
+
2. Always use semantic tokens — never raw colors
|
|
1298
|
+
3. Never use #000000 — use foreground token
|
|
1299
|
+
4. Borders: prefer ring-1 ring-foreground/10 over border
|
|
1300
|
+
5. Interactive elements: always include hover + focus states
|
|
1301
|
+
6. Shadow usage: cards=shadow-sm, dropdowns=shadow-lg, modals=shadow-xl
|
|
1302
|
+
7. Dark mode: test every component in both modes
|
|
1303
|
+
8. Mobile: every component must work at 320px width
|
|
1304
|
+
9. Typography: max 2 font families per screen
|
|
1305
|
+
10. Accent: limit primary color to ~10-15% of visible area
|
|
1306
|
+
```
|
|
1307
|
+
```
|
|
1308
|
+
|
|
1309
|
+
### shared-styles.css Structure
|
|
1310
|
+
|
|
1311
|
+
Must match the Tailwind v4 blueprint template structure exactly:
|
|
1312
|
+
|
|
1313
|
+
```css
|
|
1314
|
+
/* 1. Imports */
|
|
1315
|
+
@import "tailwindcss";
|
|
1316
|
+
@import "tw-animate-css";
|
|
1317
|
+
@import "shadcn/tailwind.css";
|
|
1318
|
+
@import "tailwind-scrollbar-hide/v4";
|
|
1319
|
+
|
|
1320
|
+
/* 2. Custom variant */
|
|
1321
|
+
@custom-variant dark (&:is(.dark *));
|
|
1322
|
+
|
|
1323
|
+
/* 3. Theme inline — semantic token -> Tailwind utility mappings */
|
|
1324
|
+
@theme inline {
|
|
1325
|
+
--color-background: var(--background);
|
|
1326
|
+
--color-foreground: var(--foreground);
|
|
1327
|
+
--font-sans: var(--font-sans);
|
|
1328
|
+
--font-mono: var(--font-mono);
|
|
1329
|
+
/* ... all 31+ color mappings ... */
|
|
1330
|
+
/* ... radius scale ... */
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/* 4. Theme — shadows, easing, animations, keyframes */
|
|
1334
|
+
@theme {
|
|
1335
|
+
--shadow-xs: ...;
|
|
1336
|
+
--shadow-sm: ...;
|
|
1337
|
+
/* ... full shadow scale ... */
|
|
1338
|
+
|
|
1339
|
+
--ease-smooth: cubic-bezier(...);
|
|
1340
|
+
--ease-spring: cubic-bezier(...);
|
|
1341
|
+
/* ... custom easing ... */
|
|
1342
|
+
|
|
1343
|
+
--animate-fade-in: fade-in 200ms ease-out;
|
|
1344
|
+
--animate-slide-up: slide-up 200ms ease-out;
|
|
1345
|
+
/* ... animation definitions ... */
|
|
1346
|
+
|
|
1347
|
+
@keyframes fade-in { ... }
|
|
1348
|
+
@keyframes slide-up { ... }
|
|
1349
|
+
@keyframes scale-in { ... }
|
|
1350
|
+
/* ... all keyframes ... */
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/* 5. Light mode variables */
|
|
1354
|
+
:root {
|
|
1355
|
+
--background: oklch(... ... ...);
|
|
1356
|
+
--foreground: oklch(... ... ...);
|
|
1357
|
+
--primary: oklch(... ... ...);
|
|
1358
|
+
/* ... all 31+ tokens ... */
|
|
1359
|
+
--radius: ...rem;
|
|
1360
|
+
/* ... font variables ... */
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
/* 6. Dark mode variables */
|
|
1364
|
+
.dark {
|
|
1365
|
+
--background: oklch(... ... ...);
|
|
1366
|
+
--foreground: oklch(... ... ...);
|
|
1367
|
+
--primary: oklch(... ... ...);
|
|
1368
|
+
/* ... all 31+ tokens ... */
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
/* 7. Base layer */
|
|
1372
|
+
@layer base {
|
|
1373
|
+
* {
|
|
1374
|
+
@apply border-border outline-ring/50;
|
|
1375
|
+
}
|
|
1376
|
+
body {
|
|
1377
|
+
@apply bg-background text-foreground;
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
```
|
|
1381
|
+
|
|
1382
|
+
---
|
|
1383
|
+
|
|
1384
|
+
## Maintenance Hooks
|
|
1385
|
+
|
|
1386
|
+
### Design System Hooks
|
|
1387
|
+
|
|
1388
|
+
| When you... | Then do... | Why |
|
|
1389
|
+
|---|---|---|
|
|
1390
|
+
| Change a color token in `docs/design/shared-styles.css` | Sync to `config/tailwind-config/shared-styles.css` (monorepo) or `src/styles/shared-styles.css` (single-repo) | Design source of truth must match deployed tokens |
|
|
1391
|
+
| Update light mode color | Update the corresponding dark mode value | Missing dark mode = broken in one mode |
|
|
1392
|
+
| Change font families | Ensure fonts are imported in the app layout (Google Fonts link or `@font-face`) | CSS variables reference fonts that must be loaded |
|
|
1393
|
+
| Add new CSS variables | Add corresponding entries to `@theme inline {}` | Tailwind utilities only work for mapped tokens |
|
|
1394
|
+
| Change the radius base value | Verify all component-specific radius classes still look correct | The entire radius scale recalculates from one value |
|
|
1395
|
+
| Update shadow values | Verify both light and dark mode look correct | Shadow opacity that works on white may be invisible on dark |
|
|
1396
|
+
|
|
1397
|
+
### Condensed Rules for project maintenance skill
|
|
1398
|
+
|
|
1399
|
+
```markdown
|
|
1400
|
+
### design-system maintenance
|
|
1401
|
+
- When design tokens change in docs/design/shared-styles.css, sync to config/tailwind-config/shared-styles.css (monorepo) or src/styles/shared-styles.css (single-repo)
|
|
1402
|
+
- When updating colors/shadows/radius: verify both light and dark mode tokens are updated together
|
|
1403
|
+
- When changing font families: ensure fonts are imported in the app layout (Google Fonts link or @font-face)
|
|
1404
|
+
- When adding new CSS variables: add corresponding entries to the @theme inline {} block
|
|
1405
|
+
- docs/design/design-system.md is the source of truth for design decisions — update it when making visual changes
|
|
1406
|
+
- Run /design-system to regenerate tokens after significant brand or audience changes
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
---
|
|
1410
|
+
|
|
1411
|
+
## What's Configurable
|
|
1412
|
+
|
|
1413
|
+
- **Creative direction** — fully conversational, user picks from proposed options or mixes elements
|
|
1414
|
+
- **Primary color hue** — any oklch hue value (0-360), proposed based on product personality and competition
|
|
1415
|
+
- **Typography** — any font pairing (display + body + optional mono), researched based on audience
|
|
1416
|
+
- **Rounding personality** — sharp (0-4px), moderate (6-10px), round (12-16px), or full (20px+, pill buttons)
|
|
1417
|
+
- **Shadow style** — ambient/diffused (modern), sharp/dramatic (bold), or brand-tinted (premium)
|
|
1418
|
+
- **Animation personality** — subtle and professional or bouncy and playful
|
|
1419
|
+
- **Border philosophy** — no-line (tonal), intentional (sparse borders), or traditional (bordered)
|
|
1420
|
+
- **Level of component guideline depth** — comprehensive by default, concise on request
|
|
1421
|
+
- **Spacing density** — standard (0.25rem base), tight (0.2rem), or loose (0.3rem)
|
|
1422
|
+
|
|
1423
|
+
---
|
|
1424
|
+
|
|
1425
|
+
## What's Opinionated
|
|
1426
|
+
|
|
1427
|
+
- **Teach the why** — every design decision is annotated with reasoning. "Use blue" is useless. "Use blue because your enterprise audience equates blue with trust, and your competitors at [X] and [Y] already use green and violet, leaving blue as defensible territory" is educational. This blueprint is a design education disguised as a configuration tool.
|
|
1428
|
+
|
|
1429
|
+
- **oklch color space** — perceptually uniform, better dark mode translations, wider gamut than hex/RGB. Not negotiable. Colors defined as raw hex values are objectively inferior for design systems because they don't maintain perceptual consistency across lightness adjustments.
|
|
1430
|
+
|
|
1431
|
+
- **Semantic tokens, always** — never raw color values in components. Always through `--primary`, `--muted`, `--destructive`, etc. This is what makes themes changeable — swap the token values and every component updates. Hard-coded colors create un-maintainable design debt.
|
|
1432
|
+
|
|
1433
|
+
- **Surface hierarchy** — layered surfaces (background -> card -> popover -> elevated), not flat. The human visual system interprets depth naturally. Flat designs without hierarchy make users work harder to understand the structure.
|
|
1434
|
+
|
|
1435
|
+
- **Both light AND dark mode** — always, no exceptions. Light-only designs are incomplete. The shared-styles.css file always contains both `:root` and `.dark` blocks with every token defined in both.
|
|
1436
|
+
|
|
1437
|
+
- **CSS output matches Tailwind v4 template structure exactly** — the generated `shared-styles.css` is a drop-in replacement for the Tailwind v4 blueprint's generic file. Same imports, same blocks, same variable names. No creative reinterpretation of the structure.
|
|
1438
|
+
|
|
1439
|
+
- **Creative direction before any tokens** — the Creative North Star comes first. Without it, color and typography choices are arbitrary. With it, every subsequent decision is evaluated against a coherent vision.
|
|
1440
|
+
|
|
1441
|
+
- **Educational annotations** — the user learns design thinking through the process. Every "I recommend X" comes with "because Y, which matters for your product because Z." The goal is not just a design system but a designer who understands it.
|
|
1442
|
+
|
|
1443
|
+
- **Honest about tradeoffs** — rounded corners ARE friendlier but DO lose information density. Dark mode IS expected but DOES require more design work. Bold colors DO differentiate but CAN fatigue users. Every recommendation acknowledges what you give up.
|
|
1444
|
+
|
|
1445
|
+
---
|
|
1446
|
+
|
|
1447
|
+
## Project Context Output
|
|
1448
|
+
|
|
1449
|
+
After completion, appends to `.project-context.md` in the target project:
|
|
1450
|
+
|
|
1451
|
+
```yaml
|
|
1452
|
+
### design-system
|
|
1453
|
+
blueprint: design-system
|
|
1454
|
+
installed_at: <date>
|
|
1455
|
+
creative_direction: "<north star name>"
|
|
1456
|
+
primary_color_hue: <oklch hue value>
|
|
1457
|
+
font_display: "<font name>"
|
|
1458
|
+
font_body: "<font name>"
|
|
1459
|
+
rounding: "<personality: sharp/moderate/round/full>"
|
|
1460
|
+
artifacts:
|
|
1461
|
+
- docs/design/design-system.md
|
|
1462
|
+
- docs/design/shared-styles.css
|
|
1463
|
+
synced_to: config/tailwind-config/shared-styles.css # if synced
|
|
1464
|
+
```
|
|
1465
|
+
|
|
1466
|
+
---
|
|
1467
|
+
|
|
1468
|
+
## References
|
|
1469
|
+
|
|
1470
|
+
- **Tailwind CSS v4 Theme:** https://tailwindcss.com/docs/theme
|
|
1471
|
+
- **OKLCH Color Space:** https://oklch.com
|
|
1472
|
+
- **OKLCH Color Picker:** https://oklch.com/#70,0.1,200,100
|
|
1473
|
+
- **Google Material Design 3:** https://m3.material.io
|
|
1474
|
+
- **Practical Typography:** https://practicaltypography.com
|
|
1475
|
+
- **Google Fonts:** https://fonts.google.com
|
|
1476
|
+
- **Type Scale Calculator:** https://typescale.com
|
|
1477
|
+
- **Bar & Neta (2006):** Humans prefer curved visual objects (Psychological Science) — the research behind rounding personality
|
|
1478
|
+
- **shadcn/ui Theming:** https://ui.shadcn.com/docs/theming
|
|
1479
|
+
- **WCAG Non-text Contrast (1.4.11):** https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html
|