From ca0f50596517f4f1bebb39dd6c46929f4c3805a1 Mon Sep 17 00:00:00 2001 From: v0 Date: Tue, 31 Mar 2026 04:39:37 +0000 Subject: [PATCH 1/4] feat: unify and optimize prompt templates for style rules Optimize 'aiRulesEn' structure for 6 styles; improve consistency, code clarity, and verification checklists. Co-authored-by: Anx <130662349+AnxForever@users.noreply.github.com> --- lib/styles/cyberpunk-neon.ts | 61 +++++++- lib/styles/glassmorphism.ts | 242 +++++++++++++++++++++++------ lib/styles/minimalist-flat.ts | 266 ++++++++++++++++++++++++++----- lib/styles/neo-brutalist.ts | 285 ++++++++++++++++++++++++++++------ lib/styles/neumorphism.ts | 182 ++++++++++++++++------ lib/styles/vaporwave.ts | 239 +++++++++++++++++++++++----- 6 files changed, 1043 insertions(+), 232 deletions(-) diff --git a/lib/styles/cyberpunk-neon.ts b/lib/styles/cyberpunk-neon.ts index 81d459da..57bc0509 100644 --- a/lib/styles/cyberpunk-neon.ts +++ b/lib/styles/cyberpunk-neon.ts @@ -267,11 +267,62 @@ SPECIAL EFFECTS: - Pulsing elements with animate-pulse - Glow intensifies on hover -Animation & Interaction Rules: -- Unstable Neon: Glow effects may carry subtle pulsing and intensity fluctuations, but must not flicker at high frequency to the point of affecting readability. -- Glitch Press: \`:active\` should prioritize offset translation (e.g., \`translate-x\` + \`-translate-y\`) with color inversion, avoiding standard button scale feedback. -- CRT Scanline: Large cards increase scanline density or visibility on hover, emphasizing the terminal-scanning state change. -- Fast & Raw: Standard interaction response should use \`duration-100\` to \`duration-150\`; only scan sweeps may extend up to \`duration-300\`.`, +--- + +## Animation Rules + +### Interaction Physics +- **Unstable Neon**: Glow effects may pulse subtly. Use \`animate-pulse\` sparingly. NO high-frequency flickering that hurts readability. +- **Glitch Press**: Active state uses OFFSET translation + color inversion, NOT scale. Example: \`active:translate-x-[2px] active:-translate-y-[1px] active:text-fuchsia-400\` +- **CRT Scanline**: Cards increase scanline density/visibility on hover, simulating terminal scanning. +- **Fast & Raw**: Standard interactions use \`duration-100\` to \`duration-150\`. Only scan sweeps may use up to \`duration-300\`. + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| Button hover | 100-150ms | ease-out | +| Glow pulse | 2-3s | ease-in-out (loop) | +| Scan sweep | 150-300ms | ease-out | +| Glitch press | instant | — | + +--- + +## Typography + +| Element | Classes | +|---------|---------| +| Headers | font-mono font-bold uppercase tracking-[0.2em] | +| Labels | text-xs font-mono uppercase tracking-wider | +| Body | font-mono text-sm | +| Code/Data | font-mono tabular-nums | + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| Light/white backgrounds | Destroys neon visibility | +| Low saturation colors | Loses cyberpunk intensity | +| shadow-md, shadow-lg | No blur shadows — only glow | +| Warm color schemes | Contradicts cold tech aesthetic | +| rounded-2xl, rounded-3xl | Too soft, not technical enough | +| Soft/friendly language | Breaks immersion | +| scale transforms on active | Use glitch offset instead | + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] Background is near-black (#0a0a0f or bg-gray-950) +- [ ] Neon glows use shadow-[0_0_Xpx_rgba(...)] format +- [ ] Text has textShadow glow effect where appropriate +- [ ] High saturation colors only (cyan, magenta, yellow, green) +- [ ] font-mono for all text elements +- [ ] Active states use glitch offset, NOT scale +- [ ] Rounded corners are rounded-sm or rounded-none +- [ ] Transitions are fast: duration-100 to duration-150`, examplePrompts: [ { diff --git a/lib/styles/glassmorphism.ts b/lib/styles/glassmorphism.ts index bee44e4c..a9907aff 100644 --- a/lib/styles/glassmorphism.ts +++ b/lib/styles/glassmorphism.ts @@ -337,60 +337,200 @@ Core principles: 6. 过渡使用 spring easing 7. 文字可读性良好`, - aiRulesEn: `You are a Liquid Glass design style frontend development expert. All generated code must strictly follow these constraints: - -## Absolutely Forbidden - -- Using glass effects on solid color backgrounds (must have gradient or image background) -- Omitting backdrop-blur or using low blur values (minimum backdrop-blur-[40px]) -- Omitting backdrop-saturate (must use backdrop-saturate-[180%]) -- Using opaque backgrounds bg-white, bg-black -- Using sharp or small corners rounded-none, rounded-sm -- Using single-layer flat shadows -- Using fast transitions duration-100, duration-150 - -## Must Follow - -### Glass Panel Three-Layer Structure -1. Semi-transparent background bg-white/10 to bg-white/20 + backdrop-blur-[40px] + backdrop-saturate-[180%] -2. Inner luminance gradient background-image: linear-gradient(to bottom, rgba(255,255,255,0.18), transparent) -3. Multi-layer shadows shadow-[outer depth, inset_top highlight] - -### Borders -- Default border-white/20 -- Hover increase to border-white/35 ~ border-white/40 - -### Transitions -- duration-500 + ease-[cubic-bezier(0.16,1,0.3,1)] spring easing -- Hover lift -translate-y-0.5 to -translate-y-1 - -### Interactions -- Specular sweep layer: skew-x-[-20deg] gradient from -translate-x-[150%] to translate-x-[150%] -- Shadows enhance synchronously on hover -- Active scale scale-[0.97] + aiRulesEn: `# Liquid Glass Design System + +You are an expert frontend developer specializing in Apple's Liquid Glass (Glassmorphism 2.0) design language. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Liquid Glass / Premium Glassmorphism +- **Category**: Modern, Premium +- **Essence**: Real glass optics — refraction, chromatic dispersion, inner luminance, depth layering +- **Mood**: Ethereal, premium, immersive, futuristic +- **Inspiration**: Apple WWDC25 Liquid Glass, visionOS interfaces + +--- + +## Core Visual Principles + +### 1. Background Requirement (CRITICAL) +\`\`\` +MANDATORY: Rich gradient or image background +Examples: +- from-indigo-600 via-purple-600 to-pink-500 +- from-blue-500 via-purple-500 to-pink-500 +- from-cyan-400 via-blue-500 to-indigo-600 + +Add floating ambient orbs for depth: +
+\`\`\` + +### 2. Glass Panel Three-Layer Structure +\`\`\` +LAYER 1 — Glass Surface: +bg-white/10 to bg-white/20 +backdrop-blur-[40px] or backdrop-blur-[60px] +backdrop-saturate-[180%] + +LAYER 2 — Inner Luminance: + + +LAYER 3 — Multi-Depth Shadows: +shadow-[0_8px_32px_rgba(0,0,0,0.12),inset_0_1px_0_rgba(255,255,255,0.35)] +\`\`\` + +### 3. Border System +\`\`\` +Default: border border-white/20 +Hover: border-white/35 to border-white/40 +\`\`\` + +### 4. Border Radius +\`\`\` +REQUIRED: rounded-2xl (16px) or rounded-3xl (24px) +Large, smooth curves for glass aesthetics +\`\`\` + +--- + +## Interaction Specifications + +### Hover Effects +| Element | Effect | Implementation | +|---------|--------|----------------| +| Cards | Lift + glow enhance | hover:-translate-y-1 hover:shadow-[0_16px_56px_rgba(0,0,0,0.18),inset_0_1px_0_rgba(255,255,255,0.45)] | +| Buttons | Subtle lift + border brighten | hover:-translate-y-0.5 hover:border-white/40 hover:bg-white/28 | +| Links | Background reveal | hover:bg-white/10 | + +### Specular Sweep (Light Reflection) +\`\`\`jsx + +\`\`\` + +### Active State +\`\`\` +active:scale-[0.97] +Brief compression feedback +\`\`\` + +--- + +## Animation Rules + +### Spring Physics +\`\`\` +transition-all duration-500 ease-[cubic-bezier(0.16,1,0.3,1)] +\`\`\` +This cubic-bezier creates natural spring-like motion simulating glass inertia. + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| Hover lift | 500ms | cubic-bezier(0.16,1,0.3,1) | +| Specular sweep | 700ms | ease-out | +| Focus glow | 500ms | cubic-bezier(0.16,1,0.3,1) | +| Active press | 150ms | ease-out | + +--- ## Color Palette -Recommended gradient backgrounds: -- Indigo-purple-pink: from-indigo-600 via-purple-600 to-pink-500 -- Blue-purple: from-blue-500 via-purple-500 to-pink-500 -- Cyan-blue: from-cyan-400 via-blue-500 to-indigo-600 - -Glass elements: -- Background: bg-white/10 to bg-white/20 -- Border: border-white/20 to border-white/40 -- Text: text-white, text-white/85, text-white/50 - -## Self-Check - -After generating code, verify: -1. Has gradient or image background -2. Has backdrop-blur-[40px] or higher -3. Has backdrop-saturate-[180%] -4. Has multi-layer shadows (outer + inset) -5. Has inner luminance gradient overlay -6. Transitions use spring easing -7. Text readability is good`, +### Gradient Backgrounds +| Name | Classes | +|------|---------| +| Indigo Purple Pink | from-indigo-600 via-purple-600 to-pink-500 | +| Blue Purple | from-blue-500 via-purple-500 to-pink-500 | +| Violet Fuchsia | from-violet-600 via-purple-600 to-fuchsia-500 | +| Cyan Blue | from-cyan-400 via-blue-500 to-indigo-600 | + +### Glass Surface +| Token | Value | Usage | +|-------|-------|-------| +| Glass BG | bg-white/10 to bg-white/20 | Panel backgrounds | +| Glass BG Hover | bg-white/25 to bg-white/30 | Hover states | +| Border | border-white/20 | Default borders | +| Border Hover | border-white/40 | Hover borders | +| Text Primary | text-white | Headlines | +| Text Secondary | text-white/85 | Body copy | +| Text Muted | text-white/50 | Captions | + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| Solid bg-white, bg-black | Glass requires translucent backgrounds | +| backdrop-blur-sm, backdrop-blur | Insufficient blur for glass effect | +| Omit backdrop-saturate | Loses color vibrancy through glass | +| Single-layer shadow | Glass needs multi-depth shadows | +| rounded-none, rounded-sm | Sharp corners break glass illusion | +| duration-100, duration-150 | Too fast, loses glass fluidity | +| Solid color backgrounds | No refraction without gradient/image | +| Strobing/high-freq animations | Breaks premium feel | + +--- + +## Responsive Guidelines + +### Blur Scaling +\`\`\` +Mobile: backdrop-blur-[30px] +Desktop (md:): backdrop-blur-[40px] to backdrop-blur-[60px] +\`\`\` + +### Shadow Scaling +\`\`\` +Mobile: shadow-[0_4px_16px_rgba(0,0,0,0.1),inset_0_1px_0_rgba(255,255,255,0.25)] +Desktop: shadow-[0_8px_32px_rgba(0,0,0,0.12),inset_0_1px_0_rgba(255,255,255,0.35)] +\`\`\` + +### Padding +\`\`\` +Cards: p-6 md:p-8 lg:p-10 +Buttons: px-5 py-3 md:px-6 md:py-3.5 +\`\`\` + +--- + +## Component Templates + +### Glass Card +\`\`\`jsx +
+ {/* Inner luminance */} + + {/* Content */} +
...
+
+\`\`\` + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] Background is gradient or image (NOT solid color) +- [ ] backdrop-blur-[40px] or higher present +- [ ] backdrop-saturate-[180%] present +- [ ] Multi-layer shadows (outer depth + inset highlight) +- [ ] Inner luminance gradient overlay added +- [ ] Borders use white with opacity (border-white/20) +- [ ] Rounded corners are rounded-2xl or rounded-3xl +- [ ] Transitions use spring easing cubic-bezier(0.16,1,0.3,1) +- [ ] duration-500 for main interactions +- [ ] Text is legible (white with good contrast) +- [ ] Ambient orbs added for depth on hero sections`, examplePrompts: [ { diff --git a/lib/styles/minimalist-flat.ts b/lib/styles/minimalist-flat.ts index b5b5e489..4e59ee10 100644 --- a/lib/styles/minimalist-flat.ts +++ b/lib/styles/minimalist-flat.ts @@ -275,42 +275,236 @@ After generating code, verify: 5. Spacing is consistent using the defined scale 6. All animations respect prefers-reduced-motion`, - aiRulesEn: `STYLE: Minimalist Flat -TYPE: Ultra-minimal flat design - -MUST USE: -- Pure colors only: bg-white, bg-black, bg-[accent] -- border-2 border-black for defined edges -- Consistent corners: all rounded-none OR all rounded-full -- High contrast: black/white with one accent -- Generous whitespace: space-y-12 md:space-y-24 -- Color hover states: hover:bg-black hover:text-white - -MUST AVOID: -- ANY shadows (shadow-sm, shadow-md, etc.) -- ANY gradients (bg-gradient-*) -- Low opacity colors -- Gray text (unless intentional muted text) -- Mixed border-radius values -- Pattern backgrounds - -COLOR RULES: -- Primary: Black (#000000) -- Background: White (#ffffff) -- Accent: One vibrant color (e.g., #ff3366) -- No grays except for intentional muted elements - -TYPOGRAPHY: -- Headers: font-bold tracking-tight -- Body: Regular weight, good line-height -- Labels: text-xs uppercase tracking-widest - -## Animation & Interaction Rules - -- Strict 2D Flatness: No translate, scale, or shadow Z-axis feedback allowed; all interactions stay within the 2D plane. -- High-Contrast Inversion: Hover primarily uses foreground/background color inversion, ensuring crisp and clear visual feedback. -- Instant Sharpness: Interactions prefer transition-none or duration-75 short feedback, no soft transitions. -- Border Dynamics: Focus or hover establishes hierarchy through border thickness/underline changes, replacing shadows and displacement.`, + aiRulesEn: `# Minimalist Flat Design System + +You are an expert frontend developer specializing in ultra-minimal flat design. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Minimalist Flat / Pure Flat Design +- **Category**: Minimal, Modern +- **Essence**: Content is king — zero decoration, maximum clarity, pure function +- **Mood**: Clean, confident, artistic, editorial +- **Inspiration**: Dieter Rams, Swiss design, art galleries, high-fashion editorials + +--- + +## Core Visual Principles + +### 1. Color Purity (CRITICAL) +\`\`\` +ONLY PURE COLORS ALLOWED: +- bg-white, bg-black +- bg-[#ff3366] (or one chosen accent) +- text-black, text-white + +NO transparency, NO grays (except intentional muted text) +\`\`\` + +### 2. Shadow Policy +\`\`\` +ABSOLUTELY FORBIDDEN: +- shadow-sm, shadow-md, shadow-lg, shadow-xl, shadow-2xl +- ANY box-shadow whatsoever + +This is a zero-shadow design system. +\`\`\` + +### 3. Gradient Policy +\`\`\` +ABSOLUTELY FORBIDDEN: +- bg-gradient-*, from-*, via-*, to-* + +Pure flat colors only. +\`\`\` + +### 4. Border Radius Consistency +\`\`\` +CHOOSE ONE and apply consistently: +OPTION A: rounded-none (sharp, editorial) +OPTION B: rounded-full (for circular elements only) + +NEVER mix rounded values in the same design. +\`\`\` + +### 5. Border System +\`\`\` +DEFAULT: border-2 border-black +Establishes structure without shadows +\`\`\` + +--- + +## Interaction Specifications + +### Hover (High-Contrast Inversion) +| Element | Default | Hover | +|---------|---------|-------| +| Button (filled) | bg-black text-white | hover:bg-white hover:text-black | +| Button (outlined) | bg-white text-black | hover:bg-black hover:text-white | +| Card | bg-white border-black | hover:bg-black hover:text-white | +| Link | text-black | hover:text-[accent] | + +### Active State +\`\`\` +active:bg-gray-200 (light variant) +active:bg-gray-100 (dark variant) +Brief flash feedback only +\`\`\` + +### Focus State +\`\`\` +focus:outline-none focus:border-[accent] +OR +focus:bg-black focus:text-white +\`\`\` + +--- + +## Animation Rules + +### Interaction Physics +- **Strict 2D Flatness**: NO translate, NO scale, NO shadow Z-axis feedback. All interactions stay within the 2D plane. +- **High-Contrast Inversion**: Hover uses foreground/background color swap. Clean, binary feedback. +- **Instant Sharpness**: Use \`transition-none\` or \`duration-75\`. NO soft fades, NO ease-in-out. +- **Border Dynamics**: Focus/hover establishes hierarchy through border thickness or underline changes, NOT shadows. + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| Color inversion | 0ms (instant) | transition-none | +| Border change | 75ms | ease-out | +| Focus ring | 150-200ms | ease-out | + +--- + +## Color Palette + +### Core Colors +| Token | Value | Usage | +|-------|-------|-------| +| Primary | #000000 (black) | Text, borders, filled buttons | +| Background | #ffffff (white) | Page background, cards | +| Accent | #ff3366 (or chosen) | CTAs, highlights, hover states | + +### Text Hierarchy +| Level | Classes | +|-------|---------| +| H1 | text-black text-5xl md:text-7xl font-bold tracking-tight | +| H2 | text-black text-3xl md:text-5xl font-bold | +| H3 | text-black text-xl md:text-2xl font-black | +| Body | text-black text-base leading-relaxed | +| Muted | text-gray-500 text-sm | +| Label | text-xs uppercase tracking-widest | + +--- + +## Typography + +| Element | Classes | +|---------|---------| +| Headlines | font-bold tracking-tight leading-tight | +| Body | Regular weight, leading-relaxed | +| Labels | text-xs font-bold uppercase tracking-widest | +| Links | underline-offset-4 hover:text-[accent] | + +--- + +## Whitespace Philosophy + +\`\`\` +GENEROUS SPACING IS MANDATORY: +- Section gaps: space-y-12 md:space-y-24 +- Card padding: p-8 md:p-12 +- Between elements: gap-6 md:gap-8 +- Page margins: px-6 md:px-12 + +"When in doubt, add more whitespace." +\`\`\` + +--- + +## Component Templates + +### Button (Filled) +\`\`\`jsx + +\`\`\` + +### Button (Outlined) +\`\`\`jsx + +\`\`\` + +### Card (Bordered) +\`\`\`jsx +
+ Category +

Title

+

Description text.

+
+\`\`\` + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| ANY shadow-* | Shadows create depth, violates flat principle | +| ANY gradient | Gradients add dimension, violates flat principle | +| opacity < 0.5 | Low opacity weakens contrast | +| Mixed border-radius | Breaks visual consistency | +| Gray text (unintentional) | Reduces clarity | +| Pattern backgrounds | Adds unnecessary visual noise | +| translate on hover | Creates Z-axis illusion | +| scale on hover | Creates Z-axis illusion | +| Soft transitions (300ms+) | Delays instant feedback | + +--- + +## Responsive Guidelines + +### Spacing Scale +\`\`\` +Mobile: space-y-8, p-6, gap-4 +Desktop (md:): space-y-16, p-12, gap-8 +Large (lg:): space-y-24, p-16, gap-12 +\`\`\` + +### Typography Scale +\`\`\` +Mobile: text-3xl, text-base +Desktop (md:): text-5xl, text-lg +\`\`\` + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] NO shadows anywhere (zero shadow-* classes) +- [ ] NO gradients anywhere (zero bg-gradient-* classes) +- [ ] Colors are pure (no transparency except intentional text muting) +- [ ] Border-radius is consistent (all sharp OR all circular) +- [ ] Whitespace is generous (space-y-12+ between sections) +- [ ] Hover uses color inversion (bg swap, not translate/scale) +- [ ] Transitions are instant or very short (transition-none or duration-75) +- [ ] High contrast maintained (black/white + one accent)`, examplePrompts: [ { diff --git a/lib/styles/neo-brutalist.ts b/lib/styles/neo-brutalist.ts index 27b64fd0..8ff06971 100644 --- a/lib/styles/neo-brutalist.ts +++ b/lib/styles/neo-brutalist.ts @@ -403,57 +403,240 @@ body { 4. active 位移量等于阴影像素值 5. 有 md: 响应式前缀`, - aiRulesEn: `You are a Neo-Brutalist design style frontend development expert. All generated code must strictly follow these constraints: - -## Absolutely Forbidden - -- Rounded corners: rounded-lg, rounded-md, rounded-xl, rounded-full (except for decorative circles) -- Blurred shadows: shadow-lg, shadow-xl, shadow-2xl, shadow-md -- Gradients: bg-gradient-* -- Gray borders: border-gray-*, border-slate-* -- Fade-in/fade-out semi-transparent effects - -## Must Follow - -- No rounded corners or rounded-none -- Hard-edge shadows shadow-[Xpx_Xpx_0px_0px_rgba(0,0,0,1)] -- Pure black borders border-black -- Hover: shadow disappears + translate displacement -- Headings font-black, body text font-mono - -## Color Palette - -Primary: Black #000000, White #ffffff -Accent colors: -- accent-pink: #ff006e (CTA, hover) -- accent-green: #ccff00 (success, decoration) -- accent-blue: #00d9ff (links, info) -- accent-yellow: #ff9500 (tags, warnings) - -## Responsive Rules - -All styles must include both mobile and desktop values: -- Spacing: p-4 md:p-8, py-12 md:py-32 -- Borders: border-2 md:border-4 -- Shadows: shadow-[4px] md:shadow-[8px] -- Font size: text-sm md:text-base, text-xl md:text-3xl -- Mobile is approximately 50% of desktop - -## Animation & Interaction Rules - -- Physical Crushing: Button active:translate-x-[Npx] active:translate-y-[Npx] active:shadow-none, N must equal original shadow pixel value for a fully flattened crushing feel. -- Brutal Snap: Hover instantly switches to high-contrast background color (e.g. hover:bg-[#ffff00]), duration-150 ease-out, no gradients or opacity transitions -- must be a hard cut. -- Zero Rounding Easing: All transitions ease-out duration-150, maintaining raw collision feel, rejecting softening. -- Heavy Focus: Card hover enlarges shadow and switches to colored (rgba(255,0,110,1)), with background color change, emphasizing physical impact. - -## Self-Check - -After generating code, verify: -1. No rounded corners -2. No blurred shadows -3. Borders are pure black -4. Active displacement equals shadow pixel value -5. Has md: responsive prefixes`, + aiRulesEn: `# Neo-Brutalist Design System + +You are an expert frontend developer specializing in Neo-Brutalist web design. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Neo-Brutalist / Web Brutalism +- **Category**: Expressive, High-Contrast +- **Essence**: Raw, honest, unapologetic — function over form, rejection of polish +- **Mood**: Bold, confrontational, playful-aggressive, anti-corporate +- **Inspiration**: Architectural Brutalism, punk zines, early web, Swiss posters + +--- + +## Core Visual Principles + +### 1. Border System (CRITICAL) +\`\`\` +REQUIRED: Pure black borders +border-black border-2 md:border-4 + +NEVER use: border-gray-*, border-slate-*, border-neutral-* +\`\`\` + +### 2. Shadow System (Hard-Edge Only) +\`\`\` +REQUIRED FORMAT: +shadow-[Xpx_Xpx_0px_0px_rgba(0,0,0,1)] + +Examples: +Mobile: shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] +Desktop: shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] + +FORBIDDEN: shadow-sm, shadow-md, shadow-lg, shadow-xl, shadow-2xl +(No blur allowed — hard edges only) +\`\`\` + +### 3. Corner Radius +\`\`\` +REQUIRED: rounded-none +Sharp corners everywhere + +FORBIDDEN: rounded-lg, rounded-md, rounded-xl, rounded-2xl +(Exception: rounded-full for intentional decorative circles only) +\`\`\` + +### 4. Typography +\`\`\` +HEADINGS: font-black (900 weight) +BODY: font-mono +LABELS: font-mono uppercase tracking-wider +\`\`\` + +--- + +## Interaction Specifications + +### Button States (Physical Crushing) +| State | Effect | Implementation | +|-------|--------|----------------| +| Default | Raised with shadow | shadow-[6px_6px_0px_0px_rgba(0,0,0,1)] | +| Hover | Shadow enlarges + offset | hover:shadow-[10px_10px_0px_0px...] hover:-translate-y-1 hover:-translate-x-1 | +| Active | FULLY FLATTENED | active:translate-x-[6px] active:translate-y-[6px] active:shadow-none | + +**CRITICAL**: Active displacement MUST equal original shadow pixel value. This creates the "physical crushing" — button is fully pressed into the surface. + +### Card Hover (Brutal Snap) +\`\`\`jsx +
+ ... +
+\`\`\` + +**CRITICAL**: Hover background color switch must be INSTANT (hard cut). NO gradients, NO opacity fade. Use duration-150 ease-out for position/shadow only. + +--- + +## Animation Rules + +### Interaction Physics +- **Physical Crushing**: Button active displacement EQUALS shadow offset. \`active:translate-x-[6px] active:translate-y-[6px] active:shadow-none\` for a 6px shadow. +- **Brutal Snap**: Hover switches to high-contrast background INSTANTLY. Hard cut, no fade. \`hover:bg-[#ffff00]\` +- **Zero Rounding Easing**: All transitions use \`ease-out duration-150\`. Raw collision feel. No soft spring physics. +- **Heavy Focus**: Card hover enlarges shadow AND changes shadow color to accent (pink/magenta). + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| Hover transform | 150ms | ease-out | +| Active press | instant | — | +| Shadow change | 150ms | ease-out | +| Color snap | 0ms | instant | + +--- + +## Color Palette + +### Primary +| Token | Value | Usage | +|-------|-------|-------| +| Black | #000000 | Borders, text, shadows | +| White | #ffffff | Backgrounds | + +### Accent Colors +| Token | Hex | Usage | +|-------|-----|-------| +| Pink | #ff006e | CTAs, hover effects | +| Green | #ccff00 | Success, hero backgrounds | +| Blue | #00d9ff | Links, info | +| Yellow | #ff9500 | Tags, warnings | +| Bright Yellow | #ffff00 | Hover backgrounds | + +### Shadow Colors +\`\`\` +Default: rgba(0,0,0,1) +Hover accent: rgba(255,0,110,1) +\`\`\` + +--- + +## Typography + +| Element | Classes | +|---------|---------| +| H1 | font-black text-4xl md:text-6xl lg:text-8xl tracking-tight leading-tight | +| H2 | font-black text-2xl md:text-4xl | +| H3 | font-black text-xl md:text-2xl | +| Body | font-mono text-sm md:text-base leading-relaxed | +| Labels | font-mono text-xs uppercase tracking-wider | +| CTA | font-black uppercase text-lg | + +--- + +## Responsive Guidelines + +### Scale Ratio +Mobile values are approximately 50% of desktop values. + +### Borders +\`\`\` +border-2 md:border-4 +\`\`\` + +### Shadows +\`\`\` +shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] +md:shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] +\`\`\` + +### Spacing +\`\`\` +p-4 md:p-8 +py-12 md:py-24 +gap-4 md:gap-8 +\`\`\` + +### Typography +\`\`\` +text-sm md:text-base +text-xl md:text-3xl +text-4xl md:text-6xl lg:text-8xl +\`\`\` + +--- + +## Component Templates + +### Button +\`\`\`jsx + +\`\`\` + +### Card +\`\`\`jsx +
+

+ Neo-Brutalism +

+

+ Raw, bold, unapologetic design. +

+
+\`\`\` + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| rounded-lg, rounded-md, rounded-xl | Softens brutalist edges | +| shadow-lg, shadow-xl, shadow-2xl | Blur violates hard-edge principle | +| bg-gradient-* | Gradients are too polished | +| border-gray-*, border-slate-* | Must use pure black borders | +| Fade/opacity transitions | Must use hard cuts | +| rounded-full (general use) | Only for decorative circles | +| Active displacement < shadow value | Fails to achieve full crushing | +| Hover opacity fade | Must snap to new color | + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] NO rounded corners (except intentional decorative circles) +- [ ] Shadows are hard-edge format: shadow-[Xpx_Xpx_0px_0px_rgba...] +- [ ] Borders are pure black: border-black +- [ ] Button active displacement = original shadow pixel value +- [ ] Hover background changes are instant (hard cut, no fade) +- [ ] Transitions use duration-150 ease-out +- [ ] Font-black for headings, font-mono for body +- [ ] Has responsive md: prefixes for borders, shadows, spacing +- [ ] Mobile values ≈ 50% of desktop values`, examplePrompts: [ { diff --git a/lib/styles/neumorphism.ts b/lib/styles/neumorphism.ts index e4b89270..68baf3f4 100644 --- a/lib/styles/neumorphism.ts +++ b/lib/styles/neumorphism.ts @@ -360,56 +360,138 @@ Core principles: - Smooth Molding: 所有过渡使用 duration-300 ease-in-out,模拟软橡胶/软塑料的柔韧弹性。 - Fixed Illuminant: 光源方向锁定左上(负 X/Y 偏移 = 白色),右下为暗(正 X/Y 偏移 = #b8bcc2),禁止任何破坏光方向的阴影配置。`, - aiRulesEn: `# Neumorphism Design Specification - -## Core Principles -You are using the Neumorphism design style. This style creates a sense of depth through soft dual shadows. - -## Must Follow -1. Background color uses light gray bg-[#e0e5ec] or bg-[#f0f0f3] -2. Raised effect: shadow-[8px_8px_16px_#b8bcc2,-8px_-8px_16px_#ffffff] -3. Recessed effect: shadow-[inset_8px_8px_16px_#b8bcc2,inset_-8px_-8px_16px_#ffffff] -4. Rounded corners use rounded-xl or rounded-2xl (12-24px) -5. Buttons switch from raised to recessed when pressed (active: pseudo-class) -6. Input fields use recessed effect to indicate input areas -7. Keep same color family: element colors close to background -8. Responsive shadows: reduce shadow size on mobile - -## Forbidden -1. Pure black/pure white backgrounds -2. Hard-edge shadows shadow-[Xpx_Xpx_0px] -3. High-contrast color schemes -4. Thick borders border-2 and above -5. Gradient backgrounds -6. Sharp corners rounded-none - -## Shadow Parameter Guide -- Light shadow direction: upper-left (-X, -Y), color close to white #ffffff -- Dark shadow direction: lower-right (X, Y), color darker than background #b8bcc2 -- Shadow blur is typically 1.5-2x the offset value - -## Color Scheme -- Main background: #e0e5ec -- Light background: #f0f0f3 -- Dark shadow: #b8bcc2 -- Light shadow: #ffffff -- Accent: #6d5dfc (purple) -- Text: #333333 -- Secondary text: #6b7280 - -## Interaction States -- Default: Raised shadow -- Hover: Shadow shrinks (Hover Shadowing, finger approaching blocks light) -- Active/Pressed: Switches to recessed shadow (Extrude to Intrude, no translate allowed) -- Focus: Input inner shadow reduces (channel opening feel) -- Disabled: Shadow weakens, opacity reduces - -## Animation & Interaction Rules - -- Extrude to Intrude: Button active state must switch from raised to recessed (active:shadow-[inset_...]), strictly no translate displacement allowed -- elements grow from the background material. -- Hover Shadowing: Hover reduces outer shadow (from 16px to 8px), simulating finger approaching and blocking light source -- opposite to convention, shadows should shrink not grow. -- Smooth Molding: All transitions use duration-300 ease-in-out, simulating soft rubber/plastic flexibility. -- Fixed Illuminant: Light source direction locked to upper-left (negative X/Y offset = white), lower-right is dark (positive X/Y offset = #b8bcc2), no shadow configuration that breaks light direction allowed.`, + aiRulesEn: `# Neumorphism Design System + +You are an expert frontend developer specializing in Neumorphism (Soft UI) design. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Neumorphism / Soft UI +- **Category**: Modern, Minimal +- **Essence**: Soft 3D depth through dual shadows simulating light hitting clay-like surfaces +- **Mood**: Calm, tactile, premium, approachable + +--- + +## Core Visual Principles + +### 1. Background Foundation +\`\`\` +REQUIRED: bg-[#e0e5ec] or bg-[#f0f0f3] +Light gray monochromatic backgrounds only +Elements must share the same color family as background +\`\`\` + +### 2. Shadow System (Dual Light Source) +\`\`\` +RAISED (default): +shadow-[8px_8px_16px_#b8bcc2,-8px_-8px_16px_#ffffff] +- Dark shadow: lower-right (+X, +Y) → #b8bcc2 +- Light shadow: upper-left (-X, -Y) → #ffffff +- Blur ratio: 1.5-2x of offset value + +RECESSED (pressed/input): +shadow-[inset_8px_8px_16px_#b8bcc2,inset_-8px_-8px_16px_#ffffff] +- Same light direction, but inset +\`\`\` + +### 3. Border Radius +\`\`\` +REQUIRED: rounded-xl (12px) or rounded-2xl (16-24px) +Soft, consistent curves across all elements +\`\`\` + +--- + +## Interaction Specifications + +### Button States +| State | Effect | Implementation | +|-------|--------|----------------| +| Default | Raised | shadow-[8px_8px_16px_#b8bcc2,-8px_-8px_16px_#ffffff] | +| Hover | Shadow shrinks | shadow-[4px_4px_8px_#b8bcc2,-4px_-4px_8px_#ffffff] | +| Active | Recessed (inset) | shadow-[inset_4px_4px_8px_#b8bcc2,inset_-4px_-4px_8px_#ffffff] | +| Disabled | Faded | opacity-50, shadow weakened | + +### Input States +| State | Effect | Implementation | +|-------|--------|----------------| +| Default | Deep recess | shadow-[inset_6px_6px_12px_#b8bcc2,inset_-6px_-6px_12px_#ffffff] | +| Focus | Shallow recess | shadow-[inset_2px_2px_4px_#b8bcc2,inset_-2px_-2px_4px_#ffffff] | + +--- + +## Animation Rules + +### Interaction Physics +- **Extrude to Intrude**: Button active state MUST switch from raised to recessed shadow. NO translate displacement allowed — elements grow from the surface, they don't float. +- **Hover Shadowing**: Hover REDUCES shadow size (16px → 8px), simulating finger blocking light. Opposite of typical hover — shadows shrink, not grow. +- **Smooth Molding**: All transitions use \`duration-300 ease-in-out\`, mimicking soft rubber/plastic flexibility. +- **Fixed Illuminant**: Light source LOCKED at upper-left. Never break this direction in any shadow configuration. + +### Transition Timing +\`\`\` +transition-all duration-300 ease-in-out +\`\`\` + +--- + +## Color Palette + +| Token | Value | Usage | +|-------|-------|-------| +| Background | #e0e5ec | Main surface | +| Background Light | #f0f0f3 | Elevated surfaces | +| Dark Shadow | #b8bcc2 | Lower-right shadows | +| Light Shadow | #ffffff | Upper-left highlights | +| Accent | #6d5dfc | Interactive elements, CTAs | +| Text Primary | #333333 | Headings, body | +| Text Secondary | #6b7280 | Muted, labels | + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| bg-white, bg-black | Breaks monochromatic harmony | +| shadow-[Xpx_Xpx_0px] | Hard shadows violate soft aesthetic | +| High-contrast colors | Disrupts subtle depth perception | +| border-2 or thicker | Borders break seamless surface illusion | +| bg-gradient-* | Gradients conflict with flat light simulation | +| rounded-none | Sharp corners contradict soft material feel | +| translate on buttons | Elements are part of surface, not floating | +| Larger hover shadows | Contradicts light physics (finger blocks light) | + +--- + +## Responsive Guidelines + +### Shadow Scaling +\`\`\` +Mobile: shadow-[4px_4px_8px_#b8bcc2,-4px_-4px_8px_#ffffff] +Desktop (md:): shadow-[8px_8px_16px_#b8bcc2,-8px_-8px_16px_#ffffff] +\`\`\` + +### Spacing +\`\`\` +Padding: p-4 md:p-6 lg:p-8 +Gap: gap-4 md:gap-6 +Section: py-12 md:py-20 +\`\`\` + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] Background is #e0e5ec or #f0f0f3 +- [ ] All shadows use dual light/dark format +- [ ] Light shadow at -X/-Y, dark at +X/+Y +- [ ] Buttons: hover shrinks shadow, active goes inset +- [ ] Inputs use inset shadows, focus reduces depth +- [ ] No translate on interactive elements +- [ ] Border radius is rounded-xl or rounded-2xl +- [ ] Transitions use duration-300 ease-in-out`, examplePrompts: [ { diff --git a/lib/styles/vaporwave.ts b/lib/styles/vaporwave.ts index 7cd2063f..df9fc97b 100644 --- a/lib/styles/vaporwave.ts +++ b/lib/styles/vaporwave.ts @@ -393,45 +393,206 @@ After generating code, verify: 5. Spacing is consistent using the defined scale 6. All animations respect prefers-reduced-motion`, - aiRulesEn: `You are a Vaporwave design style frontend development expert. All generated code must strictly follow these constraints: - -## Absolute Prohibitions - -- Using monotone gray or black-and-white color schemes -- Using overly modern minimalist designs -- Omitting neon glow effects -- Using formal serif fonts - -## Must Follow - -- Pink-purple-cyan gradients bg-gradient-to-r from-pink-500 via-purple-500 to-cyan-500 -- Neon glow shadow-[0_0_20px_rgba(255,113,206,0.5)] -- Dark backgrounds bg-purple-900, bg-pink-900 -- Grid line background decoration -- Uppercase letters and wide tracking uppercase tracking-wider - -## Color Palette - -Primary: -- Pink: #ff71ce, from-pink-500 -- Cyan: #01cdfe, from-cyan-500 -- Purple: #b967ff, from-purple-500 -- Green: #05ffa1 -- Yellow: #fffb96 - -## Special Elements - -- Japanese text decoration -- Greek sculpture imagery -- Palm trees, sunset elements -- VHS glitch effects - -## Animation & Interaction Rules - -- Aesthetic Warp: Hover introduces slight rotation and displacement, driving gradient flow (e.g., bg-[length:200%_auto] + hover:bg-right). -- Glitch/Error Snap: Active uses abrupt offset (e.g., translate-x / -translate-y), simulating old system error popup feedback. -- Dual-Color Irradiation: Glow must present pink #ff71ce and cyan #01cdfe dual scattering ghosting. -- Floating Slowness: Non-click animations use around duration-500, creating a slow floating feel in internet ruins.`, + aiRulesEn: `# Vaporwave / Neon Retro Design System + +You are an expert frontend developer specializing in Vaporwave (蒸汽波) aesthetics. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Vaporwave / Neon Retro / Synthwave +- **Category**: Retro, Expressive, High-Contrast +- **Essence**: 80s-90s retro-futurism, consumer nostalgia, digital decay, aesthetic irony +- **Mood**: Dreamy, nostalgic, surreal, melancholic yet vibrant +- **Inspiration**: 80s malls, VHS tapes, early internet, Greek statues, Japanese city pop + +--- + +## Core Visual Principles + +### 1. Background Foundation +\`\`\` +REQUIRED: Deep purple/pink gradient or solid dark colors +- bg-purple-900, bg-pink-900, bg-indigo-900 +- bg-gradient-to-b from-purple-900 via-pink-900 to-indigo-900 + +Add grid overlay for depth: +bg-[linear-gradient(rgba(255,113,206,0.1)_1px,transparent_1px),linear-gradient(90deg,rgba(255,113,206,0.1)_1px,transparent_1px)] +bg-[size:50px_50px] +\`\`\` + +### 2. Neon Glow System (Dual-Color) +\`\`\` +REQUIRED: Pink + Cyan dual glow (NOT single color) + +TEXT GLOW: +style={{ textShadow: '2px 2px 0px rgba(185,103,255,0.5)' }} + +ELEMENT GLOW: +shadow-[0_0_20px_rgba(255,113,206,0.5)] // Pink +shadow-[0_0_20px_rgba(1,205,254,0.5)] // Cyan +shadow-[4px_4px_0_rgba(1,205,254,0.6)] // Hard offset shadow + +DUAL IRRADIATION (ghosting effect): +shadow-[0_10px_30px_rgba(255,113,206,0.2)] +hover:shadow-[0_0_50px_rgba(1,205,254,0.4)] +\`\`\` + +### 3. Gradient Text +\`\`\`jsx +

+ VAPORWAVE +

+\`\`\` + +### 4. Border System +\`\`\` +Asymmetric neon borders: +border-t-2 border-l-2 border-[#ff71ce]/50 +border-b-4 border-r-4 border-[#01cdfe]/50 +\`\`\` + +--- + +## Interaction Specifications + +### Hover Effects (Aesthetic Warp) +| Element | Effect | Implementation | +|---------|--------|----------------| +| Buttons | Gradient flow + lift | bg-[length:200%_auto] hover:bg-right hover:-translate-y-1 | +| Cards | Rotate + shadow shift | hover:-translate-y-2 hover:rotate-1 hover:shadow-[0_0_50px_...] | +| Text | Letter spacing expand | group-hover:tracking-[0.4em] | + +### Active State (Glitch/Error Snap) +\`\`\` +active:rotate-0 +active:translate-x-[6px] active:translate-y-[6px] +active:shadow-none +\`\`\` +Simulates old system error popup — abrupt, offset displacement. + +### Specular Sweep +\`\`\`jsx + +\`\`\` + +--- + +## Animation Rules + +### Interaction Physics +- **Aesthetic Warp**: Hover introduces slight rotation + displacement + gradient flow. Use \`bg-[length:200%_auto] hover:bg-right\`. +- **Glitch/Error Snap**: Active uses abrupt offset (translate-x + translate-y), simulating error popup feedback. +- **Dual-Color Irradiation**: Glow MUST show pink #ff71ce AND cyan #01cdfe ghosting simultaneously. +- **Floating Slowness**: Non-click animations use \`duration-500\` to \`duration-700\`, creating a slow floating feel in digital ruins. + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| Hover lift | 300-500ms | ease-out | +| Gradient flow | 500ms | ease-out | +| Active press | instant | — | +| Grid scale | 700ms | ease-in-out | + +--- + +## Color Palette + +### Primary Neon Colors +| Token | Hex | Tailwind | Usage | +|-------|-----|----------|-------| +| Neon Pink | #ff71ce | pink-400 | Primary, headlines | +| Neon Cyan | #01cdfe | cyan-400 | Links, accents | +| Neon Purple | #b967ff | purple-400 | Secondary | +| Neon Green | #05ffa1 | — | Highlights | +| Neon Yellow | #fffb96 | — | Special elements | + +### Background & Surface +| Token | Value | Usage | +|-------|-------|-------| +| BG Deep | bg-purple-900 | Main background | +| BG Panel | bg-[#2b0057]/60 | Card backgrounds | +| Text Primary | text-pink-100 | Body text | +| Text Glow | text-[#ff71ce] | Emphasized text | + +--- + +## Typography + +| Element | Classes | +|---------|---------| +| Headlines | font-black uppercase tracking-[0.2em] text-transparent bg-clip-text bg-gradient-... | +| Body | font-medium leading-relaxed drop-shadow-[0_0_5px_rgba(255,113,206,0.5)] | +| Labels | font-mono font-bold text-xs uppercase | + +--- + +## Special Elements + +### Decorative Motifs +- Japanese text: アエステティック, 新しい, 仮想現実 +- Greek statues/busts imagery +- Palm trees, sunset horizons +- VHS scanlines and glitch effects +- Windows 95/98 UI elements +- Perspective grid floors + +### Grid Background +\`\`\`jsx +
+\`\`\` + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| Monotone gray/black-white | Destroys retro vibrancy | +| Modern minimalist design | Contradicts maximalist aesthetic | +| Omit neon glow | Loses vaporwave identity | +| Formal serif fonts | Wrong era, wrong mood | +| Single-color glow | Must have pink+cyan dual irradiation | +| Fast interactions | Use slow, dreamy timing | + +--- + +## Responsive Guidelines + +### Glow Scaling +\`\`\` +Mobile: shadow-[0_0_10px_...] +Desktop (md:): shadow-[0_0_20px_...] +\`\`\` + +### Grid Size +\`\`\` +Mobile: bg-[size:30px_30px] +Desktop: bg-[size:50px_50px] +\`\`\` + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] Background is purple/pink gradient or deep purple solid +- [ ] Neon glows use BOTH pink AND cyan (dual irradiation) +- [ ] Grid line overlay present on major sections +- [ ] Gradient text for major headlines +- [ ] Hover includes rotation/displacement/gradient flow +- [ ] Active uses abrupt offset (glitch snap) +- [ ] Transitions use duration-500+ for floating feel +- [ ] Japanese decorative text where appropriate +- [ ] Asymmetric borders (thicker on bottom-right)`, examplePrompts: [ { From f4b56d21af6a189dc038c964eb08054d073e4a54 Mon Sep 17 00:00:00 2001 From: v0 Date: Tue, 31 Mar 2026 04:42:34 +0000 Subject: [PATCH 2/4] feat: add comprehensive optimization guide document Create detailed guide with templates, explanations, and examples Co-authored-by: Anx <130662349+AnxForever@users.noreply.github.com> --- docs/ai-rules-optimization-guide.md | 409 ++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 docs/ai-rules-optimization-guide.md diff --git a/docs/ai-rules-optimization-guide.md b/docs/ai-rules-optimization-guide.md new file mode 100644 index 00000000..dba19089 --- /dev/null +++ b/docs/ai-rules-optimization-guide.md @@ -0,0 +1,409 @@ +# AI Rules English Prompt Optimization Guide + +This document provides a standardized approach for optimizing the `aiRulesEn` field in style definition files located at `/lib/styles/*.ts`. + +--- + +## Optimization Goals + +1. **Structured Format**: Transform unstructured text into a consistent, hierarchical Markdown format +2. **English Only**: Convert all Chinese content to professional English +3. **Actionable Specifications**: Provide concrete Tailwind classes, not vague descriptions +4. **Self-Verification**: Include checklists for AI to validate its own output +5. **Clear Prohibitions**: Explicitly state forbidden patterns with reasons + +--- + +## Standard Template Structure + +Every `aiRulesEn` field should follow this exact structure: + +```markdown +# [Style Name] Design System + +You are an expert frontend developer specializing in [Style Name] design. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: [Full name] / [Alternative names] +- **Category**: [Modern/Retro/Minimal/Expressive], [High-Contrast/Subtle] +- **Essence**: [One sentence describing the core principle] +- **Mood**: [4-5 adjectives describing the emotional feel] +- **Inspiration**: [Real-world references, designers, movements] + +--- + +## Core Visual Principles + +### 1. Background Foundation +\`\`\` +[Specific background requirements with exact Tailwind classes] +\`\`\` + +### 2. Shadow System +\`\`\` +[Shadow specifications with exact values] +\`\`\` + +### 3. Border System +\`\`\` +[Border specifications] +\`\`\` + +### 4. Border Radius +\`\`\` +[Border radius rules] +\`\`\` + +--- + +## Interaction Specifications + +### Button States +| State | Effect | Implementation | +|-------|--------|----------------| +| Default | [description] | [Tailwind classes] | +| Hover | [description] | [Tailwind classes] | +| Active | [description] | [Tailwind classes] | +| Focus | [description] | [Tailwind classes] | +| Disabled | [description] | [Tailwind classes] | + +### [Other Element] States +[Similar table format] + +--- + +## Animation Rules + +### Interaction Physics +- **[Rule Name]**: [Detailed explanation of the interaction principle] +- **[Rule Name]**: [Detailed explanation] + +### Timing Guidelines +| Interaction | Duration | Easing | +|-------------|----------|--------| +| [type] | [ms] | [easing function] | + +--- + +## Color Palette + +### Primary Colors +| Token | Hex | Tailwind | Usage | +|-------|-----|----------|-------| +| [name] | [#hex] | [class] | [usage] | + +### Secondary/Accent Colors +[Similar table] + +### Background & Surface +| Token | Value | Usage | +|-------|-------|-------| +| [name] | [value] | [usage] | + +--- + +## Typography + +| Element | Classes | +|---------|---------| +| Headlines | [classes] | +| Body | [classes] | +| Labels | [classes] | + +--- + +## Forbidden Patterns + +| Pattern | Reason | +|---------|--------| +| [pattern] | [why it violates this style] | + +--- + +## Responsive Guidelines + +### [Aspect] Scaling +\`\`\` +Mobile: [classes] +Desktop (md:): [classes] +\`\`\` + +--- + +## Component Templates (Optional) + +### [Component Name] +\`\`\`jsx +[Full component code example] +\`\`\` + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] [Verification item 1] +- [ ] [Verification item 2] +- [ ] [Verification item 3] +``` + +--- + +## Section-by-Section Guidelines + +### 1. Style Identity + +**Purpose**: Give the AI a mental model of the style's essence. + +| Field | Description | Example | +|-------|-------------|---------| +| Name | Primary name + alternatives | "Neumorphism / Soft UI" | +| Category | 2-3 classification tags | "Modern, Minimal" | +| Essence | Core principle in one sentence | "Soft 3D depth through dual shadows simulating light hitting clay-like surfaces" | +| Mood | 4-5 emotional adjectives | "Calm, tactile, premium, approachable" | +| Inspiration | Real references | "Apple WWDC25, visionOS, Dribbble trends" | + +### 2. Core Visual Principles + +**Purpose**: Define the non-negotiable visual rules. + +- Use code blocks with exact Tailwind classes +- Mark required vs optional with labels like `REQUIRED:`, `PREFERRED:` +- Include both mobile and desktop values where applicable +- Use comments to explain complex values + +Example: +```markdown +### Shadow System +\`\`\` +RAISED (default): +shadow-[8px_8px_16px_#b8bcc2,-8px_-8px_16px_#ffffff] +- Dark shadow: lower-right (+X, +Y) → #b8bcc2 +- Light shadow: upper-left (-X, -Y) → #ffffff + +RECESSED (pressed): +shadow-[inset_8px_8px_16px_#b8bcc2,inset_-8px_-8px_16px_#ffffff] +\`\`\` +``` + +### 3. Interaction Specifications + +**Purpose**: Define exact state changes for interactive elements. + +- Use tables for clarity +- Include ALL states: Default, Hover, Active, Focus, Disabled +- Provide complete Tailwind class strings, not fragments +- Group by element type (Button, Card, Input, Link) + +### 4. Animation Rules + +**Purpose**: Define the physics and timing of interactions. + +**Interaction Physics section should include named rules:** +- Give each rule a memorable name (e.g., "Physical Crushing", "Glitch Press") +- Explain the real-world metaphor +- Provide the exact implementation + +**Timing Guidelines table must include:** +- Interaction type +- Duration in milliseconds +- Easing function (use exact cubic-bezier if custom) + +### 5. Color Palette + +**Purpose**: Provide exact color values and their semantic usage. + +**Required tables:** +1. Primary/Core colors with Hex, Tailwind class, and usage +2. Background & Surface colors +3. Text hierarchy colors +4. For glow-based styles: RGBA values for shadows + +### 6. Typography + +**Purpose**: Define font treatments by element type. + +**Include:** +- Font family (font-sans, font-mono, font-serif) +- Font weight +- Letter spacing (tracking) +- Line height (leading) +- Text transform (uppercase, etc.) + +### 7. Forbidden Patterns + +**Purpose**: Explicitly state what NOT to do. + +**Rules:** +- Always pair the forbidden pattern with a reason +- Be specific: use actual class names, not vague descriptions +- Include common mistakes developers might make + +Example: +```markdown +| Pattern | Reason | +|---------|--------| +| shadow-md, shadow-lg | Blur shadows violate hard-edge principle | +| rounded-2xl | Too soft for brutalist aesthetic | +| translate on active | Use shadow collapse instead | +``` + +### 8. Responsive Guidelines + +**Purpose**: Ensure mobile-first, consistent scaling. + +**Include scaling for:** +- Shadows +- Borders +- Spacing (padding, gap, margins) +- Typography +- Any style-specific elements (blur, glow intensity) + +### 9. Component Templates (Optional) + +**Purpose**: Provide copy-paste ready examples. + +**When to include:** +- Complex shadow/glow configurations +- Multi-layer structures (glass panels, neumorphic buttons) +- Animation-heavy interactions + +### 10. Self-Verification Checklist + +**Purpose**: AI self-review before outputting code. + +**Rules:** +- Use checkbox format `- [ ]` +- 8-12 items maximum +- Focus on the most critical, style-defining requirements +- Order from most important to least + +--- + +## Translation Guidelines + +When converting Chinese to English: + +| Chinese Term | English Translation | +|--------------|---------------------| +| 新拟物派 / 新拟态 | Neumorphism / Soft UI | +| 毛玻璃 | Glassmorphism / Liquid Glass | +| 赛博朋克 | Cyberpunk | +| 蒸汽波 | Vaporwave | +| 新野兽派 | Neo-Brutalist | +| 极简扁平 | Minimalist Flat | +| 扫光 | Specular sweep / Light sweep | +| 发光 | Glow | +| 圆角 | Border radius / Rounded corners | +| 阴影 | Shadow | +| 边框 | Border | +| 悬停 | Hover | +| 点击/按下 | Active / Pressed | +| 聚焦 | Focus | +| 禁用 | Disabled | + +--- + +## Quality Checklist for Optimized Prompts + +Before finalizing an optimized `aiRulesEn`, verify: + +- [ ] All sections from the template are present +- [ ] All Chinese text has been translated to English +- [ ] Code blocks use exact Tailwind classes (not vague descriptions) +- [ ] Tables are properly formatted with | separators +- [ ] Animation rules include named principles with metaphors +- [ ] Forbidden patterns table includes reasons +- [ ] Self-verification checklist has 8-12 items +- [ ] Responsive guidelines cover mobile and desktop +- [ ] Color palette includes Hex values AND Tailwind classes +- [ ] No placeholder text like "[TODO]" or "[...]" + +--- + +## Files to Optimize + +The following style files in `/lib/styles/` need their `aiRulesEn` field optimized: + +### Already Optimized (Reference Examples) +- `neumorphism.ts` - Soft UI with dual shadows +- `glassmorphism.ts` - Liquid Glass / Premium glass effects +- `cyberpunk-neon.ts` - Sci-Fi neon HUD +- `vaporwave.ts` - Retro 80s/90s aesthetics +- `minimalist-flat.ts` - Zero-shadow flat design +- `neo-brutalist.ts` - Hard-edge brutalist + +### Need Optimization +Run this command to find all style files: +```bash +ls /lib/styles/*.ts +``` + +For each file, locate the `aiRulesEn:` field and replace its content following this guide. + +--- + +## Example: Before and After + +### Before (Unstructured) +```typescript +aiRulesEn: `STYLE: Example Style +MUST USE: +- Some color +- Some shadow + +MUST AVOID: +- Bad thing 1 +- Bad thing 2 + +Animation rules in Chinese: 悬停时放大...` +``` + +### After (Optimized) +```typescript +aiRulesEn: `# Example Style Design System + +You are an expert frontend developer specializing in Example Style design. Generate all code strictly following these specifications. + +## Style Identity +- **Name**: Example Style / Alternative Name +- **Category**: Modern, Expressive +- **Essence**: [Core principle description] +- **Mood**: Bold, playful, dynamic, fresh +- **Inspiration**: [Real-world references] + +--- + +## Core Visual Principles + +### 1. Background Foundation +\`\`\` +REQUIRED: bg-[#specific-color] +[Additional context] +\`\`\` + +[... remaining sections ...] + +--- + +## Self-Verification Checklist + +Before outputting code, verify: +- [ ] [Item 1] +- [ ] [Item 2] +- [ ] [Item 3]` +``` + +--- + +## Important Notes + +1. **Preserve the backtick structure**: The `aiRulesEn` field uses template literals (\`...\`). Ensure internal code blocks use escaped backticks or indentation. + +2. **Keep aiRules (Chinese) intact**: Only modify the `aiRulesEn` field unless explicitly asked to update both. + +3. **Test readability**: The prompt will be read by AI models. Ensure formatting renders correctly in Markdown. + +4. **Maintain style uniqueness**: Each style should feel distinct. Don't copy-paste generic content — adapt each section to the specific style's characteristics. + +5. **Reference existing components**: Check if the style has example components in the same file. The prompt should align with those implementations. From ea8c5745e88bc379ba912bb9b0b31dd76dd3840e Mon Sep 17 00:00:00 2001 From: v0 Date: Tue, 31 Mar 2026 04:55:40 +0000 Subject: [PATCH 3/4] feat: build style combination recommendation system Add style recipe system, recipe showcase, and enhance playground features Co-authored-by: Anx <130662349+AnxForever@users.noreply.github.com> --- app/recipes/[id]/_content.tsx | 287 ++++++++++ app/recipes/[id]/page.tsx | 83 +++ app/recipes/page.tsx | 68 +++ app/styles/[slug]/_content.tsx | 33 ++ components/home/home-content.tsx | 7 + .../playground/playground-container.tsx | 252 ++++++--- components/playground/playground-preview.tsx | 504 ++++++++++++++--- components/playground/playground-toolbar.tsx | 122 ++-- components/playground/project-export.tsx | 420 ++++++++++++++ components/playground/style-comparison.tsx | 145 +++++ components/recipes/recipe-card.tsx | 169 ++++++ components/recipes/recipe-showcase.tsx | 130 +++++ lib/i18n/translations.ts | 4 +- lib/nav-config.ts | 13 +- lib/styles/recipes.ts | 535 ++++++++++++++++++ 15 files changed, 2554 insertions(+), 218 deletions(-) create mode 100644 app/recipes/[id]/_content.tsx create mode 100644 app/recipes/[id]/page.tsx create mode 100644 app/recipes/page.tsx create mode 100644 components/playground/project-export.tsx create mode 100644 components/playground/style-comparison.tsx create mode 100644 components/recipes/recipe-card.tsx create mode 100644 components/recipes/recipe-showcase.tsx create mode 100644 lib/styles/recipes.ts diff --git a/app/recipes/[id]/_content.tsx b/app/recipes/[id]/_content.tsx new file mode 100644 index 00000000..ff419533 --- /dev/null +++ b/app/recipes/[id]/_content.tsx @@ -0,0 +1,287 @@ +"use client"; + +import { ArrowRight, Copy, Check, Sparkles, Layout, Layers, ExternalLink } from "lucide-react"; +import { useState } from "react"; +import { LocalizedLink } from "@/components/i18n/localized-link"; +import { StyleCoverPreview } from "@/components/style-preview/style-cover-preview"; +import { RecipeCard } from "@/components/recipes/recipe-card"; +import { useI18n } from "@/lib/i18n/context"; +import { + type StyleRecipe, + getRecipesByUseCase, + getRecipesByVisualStyle, +} from "@/lib/styles/recipes"; +import type { DesignStyle } from "@/lib/styles"; + +interface Props { + recipe: StyleRecipe; + visualStyle: DesignStyle | undefined; + layoutStyle: DesignStyle | undefined; +} + +export function RecipeDetailContent({ recipe, visualStyle, layoutStyle }: Props) { + const { locale } = useI18n(); + const [copied, setCopied] = useState(false); + + const name = locale === "zh" ? recipe.nameZh : recipe.name; + const description = locale === "zh" ? recipe.descriptionZh : recipe.description; + const reasoning = locale === "zh" ? recipe.reasoningZh : recipe.reasoning; + + // Related recipes + const relatedByUseCase = getRecipesByUseCase(recipe.useCase) + .filter((r) => r.id !== recipe.id) + .slice(0, 3); + const relatedByStyle = getRecipesByVisualStyle(recipe.visualStyle) + .filter((r) => r.id !== recipe.id) + .slice(0, 3); + + // Generate prompt for this recipe + const generatePrompt = () => { + const parts = [ + `Design Style: ${recipe.visualStyle}`, + `Layout Pattern: ${recipe.layout}`, + recipe.animations?.length + ? `Animations: ${recipe.animations.join(", ")}` + : null, + `Use Case: ${recipe.useCase}`, + `Tags: ${recipe.tags.join(", ")}`, + ].filter(Boolean); + + return `Create a ${recipe.useCase.replace("-", " ")} using the following design specifications: + +${parts.join("\n")} + +${reasoning}`; + }; + + const handleCopyPrompt = async () => { + const prompt = generatePrompt(); + await navigator.clipboard.writeText(prompt); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( + <> + {/* Hero */} +
+
+
+ {/* Left: Info */} +
+
+ {recipe.featured && ( + + {locale === "zh" ? "精选配方" : "Featured Recipe"} + + )} + + {recipe.useCase} + +
+ +

{name}

+

{description}

+ + {/* Recipe Components */} +
+ + + {recipe.visualStyle} + + + + + {recipe.layout} + + + {recipe.animations && recipe.animations.length > 0 && ( +
+ + + {recipe.animations.length}{" "} + {locale === "zh" ? "个动画" : "animations"} + +
+ )} +
+ + {/* Tags */} +
+ {recipe.tags.map((tag) => ( + + {tag} + + ))} +
+ + {/* Reasoning */} +
+

+ {locale === "zh" ? "为什么这个组合有效" : "Why This Combination Works"} +

+

{reasoning}

+
+ + {/* Quick Copy Prompt */} + +
+ + {/* Right: Preview */} +
+ {/* Visual Style Preview */} + {visualStyle && ( +
+

+ {locale === "zh" ? "视觉风格预览" : "Visual Style Preview"} +

+ +
+ +
+
+
+

{visualStyle.name}

+

{visualStyle.nameEn}

+
+ + {locale === "zh" ? "查看展示" : "View Showcase"} + + +
+
+
+ )} + + {/* Layout Preview */} + {layoutStyle && ( +
+

+ {locale === "zh" ? "布局风格预览" : "Layout Pattern Preview"} +

+ +
+ +
+
+
+

{layoutStyle.name}

+

{layoutStyle.nameEn}

+
+ + {locale === "zh" ? "查看展示" : "View Showcase"} + + +
+
+
+ )} +
+
+
+
+ + {/* Animations */} + {recipe.animations && recipe.animations.length > 0 && ( +
+
+

+ {locale === "zh" ? "推荐动画" : "Recommended Animations"} +

+

+ {locale === "zh" ? "为此配方精选的动画效果" : "Curated Animations for This Recipe"} +

+
+ {recipe.animations.map((anim) => ( + +

{anim}

+

+ {locale === "zh" ? "查看动画" : "View Animation"} + +

+
+ ))} +
+
+
+ )} + + {/* Related Recipes */} + {(relatedByUseCase.length > 0 || relatedByStyle.length > 0) && ( +
+
+ {relatedByUseCase.length > 0 && ( +
+

+ {locale === "zh" ? "同类使用场景" : "Same Use Case"} +

+

+ {locale === "zh" + ? `其他 ${recipe.useCase} 配方` + : `Other ${recipe.useCase} Recipes`} +

+
+ {relatedByUseCase.map((r) => ( + + ))} +
+
+ )} + + {relatedByStyle.length > 0 && ( +
+

+ {locale === "zh" ? "相同视觉风格" : "Same Visual Style"} +

+

+ {locale === "zh" + ? `其他使用 ${recipe.visualStyle} 的配方` + : `Other Recipes Using ${recipe.visualStyle}`} +

+
+ {relatedByStyle.map((r) => ( + + ))} +
+
+ )} +
+
+ )} + + ); +} diff --git a/app/recipes/[id]/page.tsx b/app/recipes/[id]/page.tsx new file mode 100644 index 00000000..297f1cd4 --- /dev/null +++ b/app/recipes/[id]/page.tsx @@ -0,0 +1,83 @@ +import { notFound } from "next/navigation"; +import { Metadata } from "next"; +import { Header } from "@/components/layout/header"; +import { Footer } from "@/components/layout/footer"; +import { Breadcrumb } from "@/components/ui/breadcrumb"; +import { RecipeDetailContent } from "./_content"; +import { + getAllRecipes, + getRecipeById, + resolveRecipeStyles, +} from "@/lib/styles/recipes"; + +export function generateStaticParams() { + return getAllRecipes().map((recipe) => ({ + id: recipe.id, + })); +} + +export async function generateMetadata({ + params, +}: { + params: Promise<{ id: string }>; +}): Promise { + const { id } = await params; + const recipe = getRecipeById(id); + + if (!recipe) { + return { title: "Recipe Not Found" }; + } + + return { + title: `${recipe.name} - Design Recipe | StyleKit`, + description: recipe.description, + keywords: [ + recipe.name, + recipe.visualStyle, + recipe.layout, + recipe.useCase, + ...recipe.tags, + ], + }; +} + +export default async function RecipeDetailPage({ + params, +}: { + params: Promise<{ id: string }>; +}) { + const { id } = await params; + const recipe = getRecipeById(id); + + if (!recipe) { + notFound(); + } + + const { visual, layout } = resolveRecipeStyles(recipe); + + return ( +
+
+ +
+
+ +
+ + +
+ +
+
+ ); +} diff --git a/app/recipes/page.tsx b/app/recipes/page.tsx new file mode 100644 index 00000000..7ce98eb0 --- /dev/null +++ b/app/recipes/page.tsx @@ -0,0 +1,68 @@ +import { Metadata } from "next"; +import { Header } from "@/components/layout/header"; +import { Footer } from "@/components/layout/footer"; +import { Breadcrumb } from "@/components/ui/breadcrumb"; +import { RecipeShowcase } from "@/components/recipes/recipe-showcase"; +import { getAllRecipes } from "@/lib/styles/recipes"; + +export const metadata: Metadata = { + title: "Design Recipes - Ready-to-Use Style Combinations | StyleKit", + description: + "Curated combinations of visual styles, layouts, and animations optimized for specific use cases. SaaS, e-commerce, portfolio, blog, and more.", + keywords: [ + "design recipes", + "style combinations", + "UI patterns", + "SaaS design", + "landing page templates", + "design system", + ], +}; + +export default function RecipesPage() { + const allRecipes = getAllRecipes(); + + return ( +
+
+ +
+
+ +
+ + {/* Hero */} +
+
+

+ Design Recipes +

+

+ Curated combinations of visual styles, layouts, and animations. + Each recipe is optimized for a specific use case and includes + reasoning for why it works. +

+
+ + {allRecipes.length} Recipes + + + {allRecipes.filter((r) => r.featured).length} Featured + +
+
+
+ + {/* Recipe Showcase */} + +
+ +
+
+ ); +} diff --git a/app/styles/[slug]/_content.tsx b/app/styles/[slug]/_content.tsx index 5e10afa5..d8d101da 100644 --- a/app/styles/[slug]/_content.tsx +++ b/app/styles/[slug]/_content.tsx @@ -28,6 +28,8 @@ import type { DesignStyle } from "@/lib/styles"; import type { AccessibilityScore } from "@/lib/accessibility"; import type { StyleVersion } from "@/lib/versioning"; import type { RuntimeStyleSource } from "@/lib/styles/community-runtime"; +import { getRecipesByVisualStyle, getRecipesByLayout } from "@/lib/styles/recipes"; +import { RecipeCard } from "@/components/recipes/recipe-card"; interface Props { style: DesignStyle; @@ -74,6 +76,11 @@ export function StyleDetailContent({ cancelAnimationFrame(rafId); }; }, [updateShowcaseScale]); + // Get related recipes + const relatedRecipes = style.styleType === "layout" + ? getRecipesByLayout(style.slug).slice(0, 3) + : getRecipesByVisualStyle(style.slug).slice(0, 3); + const localizedDescription = localizedString( locale, style.description, @@ -483,6 +490,32 @@ export function StyleDetailContent({ )} + {/* Related Recipes */} + {relatedRecipes.length > 0 && ( +
+
+

+ {locale === "zh" ? "设计配方" : "Design Recipes"} +

+

+ {locale === "zh" + ? `使用 ${style.name} 的推荐组合` + : `Recommended Combinations with ${style.nameEn}`} +

+

+ {locale === "zh" + ? "这些精选配方将此风格与布局和动画组合,针对特定场景优化。" + : "These curated recipes combine this style with layouts and animations, optimized for specific use cases."} +

+
+ {relatedRecipes.map((recipe) => ( + + ))} +
+
+
+ )} + {/* SEO Extended */}
diff --git a/components/home/home-content.tsx b/components/home/home-content.tsx index 011731cd..873532e2 100644 --- a/components/home/home-content.tsx +++ b/components/home/home-content.tsx @@ -27,6 +27,11 @@ const BuiltForSection = dynamic( { ssr: true } ); +const RecipeShowcase = dynamic( + () => import("@/components/recipes/recipe-showcase").then((m) => ({ default: m.RecipeShowcase })), + { ssr: true } +); + import type { StyleMeta } from "@/lib/styles/meta"; import { getScenarioLabel, @@ -606,6 +611,8 @@ export function HomeContent({ styles, stats }: HomeContentProps) { + + diff --git a/components/playground/playground-container.tsx b/components/playground/playground-container.tsx index b4a020de..7913d987 100644 --- a/components/playground/playground-container.tsx +++ b/components/playground/playground-container.tsx @@ -10,11 +10,13 @@ import { styleTokensRegistry } from "@/lib/styles/tokens-registry"; import { getAllArchetypes } from "@/lib/archetypes"; import type { StyleTokens } from "@/lib/styles/tokens"; -import { getTemplateCode } from "@/lib/playground/template-code"; -import { PlaygroundPreview } from "./playground-preview"; -import { PlaygroundToolbar } from "./playground-toolbar"; -import { StyleSwitcher } from "./style-switcher"; -import { TemplateSelector } from "./template-selector"; +import { getTemplateCode } from "@/lib/playground/template-code"; +import { PlaygroundPreview, type ElementInfo } from "./playground-preview"; +import { PlaygroundToolbar } from "./playground-toolbar"; +import { StyleSwitcher } from "./style-switcher"; +import { TemplateSelector } from "./template-selector"; +import { StyleComparison } from "./style-comparison"; +import { ProjectExport } from "./project-export"; const PlaygroundEditor = dynamic( () => @@ -108,57 +110,112 @@ function getDefaultCode(): string {
`; } -/** - * Convert StyleTokens into a CSS string that can be injected into the iframe. - * Extracts key color values from Tailwind class references. - */ -function tokensToCSS(tokens: StyleTokens): string { - const lines: string[] = []; - - // Extract background colors - const bgPrimary = tokens.colors.background.primary; - const bgSecondary = tokens.colors.background.secondary; - - // Extract text colors - const textPrimary = tokens.colors.text.primary; - - // Build a basic CSS based on token info - lines.push("/* StyleKit Token Overrides */"); - - // Typography - if (tokens.typography.heading.includes("font-serif")) { - lines.push("h1, h2, h3, h4, h5, h6 { font-family: Georgia, 'Times New Roman', serif; }"); - } - if (tokens.typography.body.includes("font-mono")) { - lines.push("body, p { font-family: 'JetBrains Mono', 'Fira Code', monospace; }"); - } - if (tokens.typography.body.includes("font-sans")) { - lines.push("body, p { font-family: system-ui, -apple-system, sans-serif; }"); - } - - // Border radius - if (tokens.border.radius.includes("rounded-none")) { - lines.push("* { --tw-border-radius: 0; }"); - lines.push("button, input, .card, [class*='rounded'] { border-radius: 0 !important; }"); - } else if (tokens.border.radius.includes("rounded-full")) { - lines.push("button { border-radius: 9999px; }"); - } else if (tokens.border.radius.includes("rounded-2xl") || tokens.border.radius.includes("rounded-3xl")) { - lines.push("button, .card { border-radius: 1rem; }"); - } - - // Additional styling hints from token color classes - if (bgPrimary.includes("bg-black") || bgPrimary.includes("bg-zinc-950") || bgPrimary.includes("bg-gray-950")) { - lines.push("body { background-color: #09090b; color: #fafafa; }"); - } - if (textPrimary.includes("text-white")) { - lines.push("body { color: #ffffff; }"); - } - if (bgSecondary.includes("bg-zinc-900")) { - lines.push(".card, section:nth-child(even) { background-color: #18181b; }"); - } - - return lines.join("\n"); -} +/** + * Convert StyleTokens into a CSS string that can be injected into the iframe. + * Extracts key color values from Tailwind class references. + */ +function tokensToCSS(tokens: StyleTokens): string { + const lines: string[] = []; + + // Extract background colors + const bgPrimary = tokens.colors.background.primary; + const bgSecondary = tokens.colors.background.secondary; + + // Extract text colors + const textPrimary = tokens.colors.text.primary; + + // Build a basic CSS based on token info + lines.push("/* StyleKit Token Overrides */"); + + // Typography - 更完整的字体处理 + if (tokens.typography.heading.includes("font-serif")) { + lines.push("h1, h2, h3, h4, h5, h6 { font-family: Georgia, 'Times New Roman', serif; }"); + } + if (tokens.typography.body.includes("font-mono")) { + lines.push("body, p { font-family: 'JetBrains Mono', 'Fira Code', monospace; }"); + } + if (tokens.typography.body.includes("font-sans")) { + lines.push("body, p { font-family: system-ui, -apple-system, sans-serif; }"); + } + + // 字重处理 + if (tokens.typography.heading.includes("font-black")) { + lines.push("h1, h2, h3 { font-weight: 900; }"); + } else if (tokens.typography.heading.includes("font-bold")) { + lines.push("h1, h2, h3 { font-weight: 700; }"); + } else if (tokens.typography.heading.includes("font-medium")) { + lines.push("h1, h2, h3 { font-weight: 500; }"); + } + + // 行高处理 + if (tokens.typography.body.includes("leading-relaxed")) { + lines.push("body, p { line-height: 1.625; }"); + } else if (tokens.typography.body.includes("leading-loose")) { + lines.push("body, p { line-height: 2; }"); + } + + // Border radius - 更细致的圆角处理 + if (tokens.border.radius.includes("rounded-none")) { + lines.push("button, input, .card, [class*='rounded'] { border-radius: 0 !important; }"); + } else if (tokens.border.radius.includes("rounded-full")) { + lines.push("button { border-radius: 9999px; }"); + } else if (tokens.border.radius.includes("rounded-3xl")) { + lines.push("button, .card { border-radius: 1.5rem; }"); + } else if (tokens.border.radius.includes("rounded-2xl")) { + lines.push("button, .card { border-radius: 1rem; }"); + } else if (tokens.border.radius.includes("rounded-xl")) { + lines.push("button, .card { border-radius: 0.75rem; }"); + } else if (tokens.border.radius.includes("rounded-lg")) { + lines.push("button, .card { border-radius: 0.5rem; }"); + } + + // 边框样式 + if (tokens.border.style.includes("border-4") || tokens.border.style.includes("border-3")) { + lines.push("button, .card { border-width: 3px; }"); + } else if (tokens.border.style.includes("border-2")) { + lines.push("button, .card { border-width: 2px; }"); + } + + // 阴影样式 + if (tokens.shadow.card.includes("shadow-brutal") || tokens.shadow.card.includes("shadow-[")) { + // Neo-brutalist 风格阴影 + if (tokens.shadow.card.includes("4px_4px") || tokens.shadow.card.includes("6px_6px")) { + lines.push(".card, button { box-shadow: 4px 4px 0px 0px rgba(0,0,0,1); }"); + lines.push("button:hover { transform: translate(2px, 2px); box-shadow: 2px 2px 0px 0px rgba(0,0,0,1); }"); + } + } else if (tokens.shadow.card.includes("shadow-lg")) { + lines.push(".card { box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1); }"); + } else if (tokens.shadow.card.includes("shadow-xl")) { + lines.push(".card { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1); }"); + } + + // Background color themes + if (bgPrimary.includes("bg-black") || bgPrimary.includes("bg-zinc-950") || bgPrimary.includes("bg-gray-950")) { + lines.push("body { background-color: #09090b; color: #fafafa; }"); + lines.push("a { color: #60a5fa; }"); + } else if (bgPrimary.includes("bg-zinc-900") || bgPrimary.includes("bg-gray-900")) { + lines.push("body { background-color: #18181b; color: #f4f4f5; }"); + } else if (bgPrimary.includes("bg-slate-900")) { + lines.push("body { background-color: #0f172a; color: #f1f5f9; }"); + } + + if (textPrimary.includes("text-white")) { + lines.push("body { color: #ffffff; }"); + } + if (bgSecondary.includes("bg-zinc-900")) { + lines.push(".card, section:nth-child(even) { background-color: #18181b; }"); + } else if (bgSecondary.includes("bg-zinc-800")) { + lines.push(".card, section:nth-child(even) { background-color: #27272a; }"); + } + + // 按钮过渡效果 + lines.push("button { transition: all 0.15s ease; }"); + + // 链接悬停效果 + lines.push("a:hover { opacity: 0.8; }"); + + return lines.join("\n"); +} export function PlaygroundContainer() { const searchParams = useSearchParams(); @@ -194,9 +251,12 @@ export function PlaygroundContainer() { const [styleSlug, setStyleSlug] = useState(initialState.style); const [templateId, setTemplateId] = useState(initialState.template); const [deviceSize, setDeviceSize] = useState("desktop"); - const [editorVisible, setEditorVisible] = useState(true); - const [templatesVisible, setTemplatesVisible] = useState(false); - const [editorTab, setEditorTab] = useState("code"); + const [editorVisible, setEditorVisible] = useState(true); + const [templatesVisible, setTemplatesVisible] = useState(false); + const [editorTab, setEditorTab] = useState("code"); + const [comparisonVisible, setComparisonVisible] = useState(false); + const [exportVisible, setExportVisible] = useState(false); + const [selectedElementInfo, setSelectedElementInfo] = useState(null); // Get style metadata for switcher const stylesForSwitcher = useMemo( @@ -263,10 +323,20 @@ export function PlaygroundContainer() { router.replace("/playground", { scroll: false }); }, [router]); - // Handle editor change - const handleCodeChange = useCallback((newCode: string) => { - setCode(newCode); - }, []); + // Handle editor change + const handleCodeChange = useCallback((newCode: string) => { + setCode(newCode); + }, []); + + // Handle element selection from preview inspector + const handleElementSelect = useCallback((info: ElementInfo | null) => { + setSelectedElementInfo(info); + // 如果选中了元素,尝试在代码中搜索相关类名 + if (info && info.classes.length > 0) { + // 可以后续扩展:高亮编辑器中的相关行 + console.log('[v0] Selected element:', info); + } + }, []); return (
@@ -279,10 +349,12 @@ export function PlaygroundContainer() { deviceSize={deviceSize} onDeviceSizeChange={setDeviceSize} editorVisible={editorVisible} - onToggleEditor={() => setEditorVisible((v) => !v)} - onToggleTemplates={() => setTemplatesVisible((v) => !v)} - templatesVisible={templatesVisible} - /> + onToggleEditor={() => setEditorVisible((v) => !v)} + onToggleTemplates={() => setTemplatesVisible((v) => !v)} + templatesVisible={templatesVisible} + onOpenComparison={() => setComparisonVisible(true)} + onOpenExport={() => setExportVisible(true)} + /> {/* Style switcher bar */}
@@ -377,16 +449,36 @@ export function PlaygroundContainer() { maxWidth: "100%", }} > - -
-
-
-
- - ); -} + + + + + + + {/* Style Comparison Modal */} + {comparisonVisible && ( + setComparisonVisible(false)} + /> + )} + + {/* Project Export Modal */} + {exportVisible && ( + setExportVisible(false)} + /> + )} + + ); +} diff --git a/components/playground/playground-preview.tsx b/components/playground/playground-preview.tsx index 080a3f37..e2b2a70b 100644 --- a/components/playground/playground-preview.tsx +++ b/components/playground/playground-preview.tsx @@ -1,84 +1,420 @@ -"use client"; - -import { useState, useEffect, useRef, useMemo } from "react"; -import { Loader2 } from "lucide-react"; - -interface PlaygroundPreviewProps { - code: string; - styleSlug: string; - /** CSS variables/tokens to inject as inline styles */ - tokenCss: string; - deviceWidth?: number; -} - -function buildSrcdoc(code: string, tokenCss: string): string { - // Escape closing script tags in user code to prevent srcdoc breakout - const safeCode = code.replace(/<\/script/gi, "<\\/script"); - - return ` - - - - - + +`; +} + +function generateStandaloneHtml(code: string, css: string, styleName: string): string { + return ` + + + + + ${styleName} - Built with StyleKit + + + + +${code} + +`; +} + +async function downloadZip(files: Record, styleSlug: string) { + // Create a simple text-based download for now + // In production, you'd use a library like JSZip + const content = Object.entries(files) + .map(([filename, fileContent]) => `// ===== ${filename} =====\n\n${fileContent}`) + .join("\n\n"); + + const blob = new Blob([content], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `stylekit-${styleSlug}-project.txt`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} diff --git a/components/playground/style-comparison.tsx b/components/playground/style-comparison.tsx new file mode 100644 index 00000000..1e47f06c --- /dev/null +++ b/components/playground/style-comparison.tsx @@ -0,0 +1,145 @@ +"use client"; + +import { useState, useMemo } from "react"; +import { ChevronDown, X, ArrowLeftRight } from "lucide-react"; +import { stylesMeta, type StyleMeta } from "@/lib/styles/meta"; +import { useI18n } from "@/lib/i18n/context"; + +interface StyleComparisonProps { + baseStyleSlug: string; + code: string; + onClose: () => void; +} + +export function StyleComparison({ baseStyleSlug, code, onClose }: StyleComparisonProps) { + const { locale } = useI18n(); + const [compareSlug, setCompareSlug] = useState(""); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + + const styles = useMemo(() => { + return stylesMeta + .filter((s) => s.styleType === "visual" && s.slug !== baseStyleSlug) + .slice(0, 30); + }, [baseStyleSlug]); + + const baseStyle = stylesMeta.find((s) => s.slug === baseStyleSlug); + const compareStyle = stylesMeta.find((s) => s.slug === compareSlug); + + return ( +
+ {/* Header */} +
+
+

+ + {locale === "zh" ? "风格对比" : "Style Comparison"} +

+ + {/* Base style badge */} +
+ + {locale === "zh" ? "基础:" : "Base:"} + + {baseStyle?.name || baseStyleSlug} +
+ + {/* VS */} + vs + + {/* Compare style selector */} +
+ + + {isDropdownOpen && ( +
+ {styles.map((style) => ( + + ))} +
+ )} +
+
+ + +
+ + {/* Comparison view */} +
+ {/* Left: Base style */} +
+
+ + {baseStyle?.name || baseStyleSlug} + +
+
+