📦 deps(skills): sync thirdparty skills
This commit is contained in:
+5
-18
@@ -10,9 +10,9 @@ Comprehensive design guide for web, mobile, and desktop applications. Contains 6
|
|||||||
|
|
||||||
当任务涉及 **UI 结构、视觉设计决策、交互模式或用户体验质量控制** 时,应使用此 Skill。
|
当任务涉及 **UI 结构、视觉设计决策、交互模式或用户体验质量控制** 时,应使用此 Skill。
|
||||||
|
|
||||||
### Must Use
|
### Primary Use Cases
|
||||||
|
|
||||||
在以下情况必须调用此 Skill:
|
在以下情况此 Skill 最为有用:
|
||||||
|
|
||||||
- 设计新的页面(Landing Page、Dashboard、Admin、SaaS、Mobile App)
|
- 设计新的页面(Landing Page、Dashboard、Admin、SaaS、Mobile App)
|
||||||
- 创建或重构 UI 组件(按钮、弹窗、表单、表格、图表等)
|
- 创建或重构 UI 组件(按钮、弹窗、表单、表格、图表等)
|
||||||
@@ -305,28 +305,15 @@ Search specific domains using the CLI tool below.
|
|||||||
---
|
---
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
|
|
||||||
Check if Python is installed:
|
The bundled scripts require Python 3 (standard library only — no third-party packages, no network access). Check if it is available:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 --version || python --version
|
python3 --version || python --version
|
||||||
```
|
```
|
||||||
|
|
||||||
If Python is not installed, install it based on user's OS:
|
If Python is not installed, **do not install it yourself**. Stop and ask the user to install Python 3 using their preferred method (e.g. from [python.org](https://www.python.org/downloads/) or their OS package manager), then continue once it is available. Never run package-manager or system-modifying commands (`sudo`, `brew`, `apt`, `winget`, etc.) on the user's machine for this skill.
|
||||||
|
|
||||||
**macOS:**
|
If the user prefers not to install Python, skip the CLI searches and rely on the Quick Reference sections above.
|
||||||
```bash
|
|
||||||
brew install python3
|
|
||||||
```
|
|
||||||
|
|
||||||
**Ubuntu/Debian:**
|
|
||||||
```bash
|
|
||||||
sudo apt update && sudo apt install python3
|
|
||||||
```
|
|
||||||
|
|
||||||
**Windows:**
|
|
||||||
```powershell
|
|
||||||
winget install Python.Python.3.12
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note:** On Windows, use `python` instead of `python3` to run scripts (e.g., `python scripts/search.py` instead of `python3 scripts/search.py`).
|
> **Note:** On Windows, use `python` instead of `python3` to run scripts (e.g., `python scripts/search.py` instead of `python3 scripts/search.py`).
|
||||||
|
|
||||||
|
|||||||
-414
@@ -1,414 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Sync colors.csv and ui-reasoning.csv with the updated products.csv (161 entries).
|
|
||||||
- Remove deleted product types
|
|
||||||
- Rename mismatched entries
|
|
||||||
- Add new entries for missing product types
|
|
||||||
- Keep colors.csv aligned 1:1 with products.csv
|
|
||||||
- Renumber everything
|
|
||||||
"""
|
|
||||||
import csv, os, json
|
|
||||||
|
|
||||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
# ─── Color derivation helpers ────────────────────────────────────────────────
|
|
||||||
def h2r(h):
|
|
||||||
h = h.lstrip("#")
|
|
||||||
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
|
||||||
|
|
||||||
def r2h(r, g, b):
|
|
||||||
return f"#{max(0,min(255,int(r))):02X}{max(0,min(255,int(g))):02X}{max(0,min(255,int(b))):02X}"
|
|
||||||
|
|
||||||
def lum(h):
|
|
||||||
r, g, b = [x/255.0 for x in h2r(h)]
|
|
||||||
r, g, b = [(x/12.92 if x<=0.03928 else ((x+0.055)/1.055)**2.4) for x in (r, g, b)]
|
|
||||||
return 0.2126*r + 0.7152*g + 0.0722*b
|
|
||||||
|
|
||||||
def is_dark(bg):
|
|
||||||
return lum(bg) < 0.18
|
|
||||||
|
|
||||||
def on_color(bg):
|
|
||||||
return "#FFFFFF" if lum(bg) < 0.4 else "#0F172A"
|
|
||||||
|
|
||||||
def blend(a, b, f=0.15):
|
|
||||||
ra, ga, ba = h2r(a)
|
|
||||||
rb, gb, bb = h2r(b)
|
|
||||||
return r2h(ra+(rb-ra)*f, ga+(gb-ga)*f, ba+(bb-ba)*f)
|
|
||||||
|
|
||||||
def shift(h, n):
|
|
||||||
r, g, b = h2r(h)
|
|
||||||
return r2h(r+n, g+n, b+n)
|
|
||||||
|
|
||||||
def derive_row(pt, pri, sec, acc, bg, notes=""):
|
|
||||||
"""Generate full 16-token color row from 4 base colors."""
|
|
||||||
dark = is_dark(bg)
|
|
||||||
fg = "#FFFFFF" if dark else "#0F172A"
|
|
||||||
on_pri = on_color(pri)
|
|
||||||
on_sec = on_color(sec)
|
|
||||||
on_acc = on_color(acc)
|
|
||||||
card = shift(bg, 10) if dark else "#FFFFFF"
|
|
||||||
card_fg = "#FFFFFF" if dark else "#0F172A"
|
|
||||||
muted = blend(bg, pri, 0.08) if dark else blend("#FFFFFF", pri, 0.06)
|
|
||||||
muted_fg = "#94A3B8" if dark else "#64748B"
|
|
||||||
border = f"rgba(255,255,255,0.08)" if dark else blend("#FFFFFF", pri, 0.12)
|
|
||||||
destr = "#DC2626"
|
|
||||||
on_destr = "#FFFFFF"
|
|
||||||
ring = pri
|
|
||||||
return [pt, pri, on_pri, sec, on_sec, acc, on_acc, bg, fg, card, card_fg, muted, muted_fg, border, destr, on_destr, ring, notes]
|
|
||||||
|
|
||||||
# ─── Rename maps ─────────────────────────────────────────────────────────────
|
|
||||||
COLOR_RENAMES = {
|
|
||||||
"Quantum Computing": "Quantum Computing Interface",
|
|
||||||
"Biohacking / Longevity": "Biohacking / Longevity App",
|
|
||||||
"Autonomous Systems": "Autonomous Drone Fleet Manager",
|
|
||||||
"Generative AI Art": "Generative Art Platform",
|
|
||||||
"Spatial / Vision OS": "Spatial Computing OS / App",
|
|
||||||
"Climate Tech": "Sustainable Energy / Climate Tech",
|
|
||||||
}
|
|
||||||
UI_RENAMES = {
|
|
||||||
"Architecture/Interior": "Architecture / Interior",
|
|
||||||
"Autonomous Drone Fleet": "Autonomous Drone Fleet Manager",
|
|
||||||
"B2B SaaS Enterprise": "B2B Service",
|
|
||||||
"Biohacking/Longevity App": "Biohacking / Longevity App",
|
|
||||||
"Biotech/Life Sciences": "Biotech / Life Sciences",
|
|
||||||
"Developer Tool/IDE": "Developer Tool / IDE",
|
|
||||||
"Education": "Educational App",
|
|
||||||
"Fintech (Banking)": "Fintech/Crypto",
|
|
||||||
"Government/Public": "Government/Public Service",
|
|
||||||
"Home Services": "Home Services (Plumber/Electrician)",
|
|
||||||
"Micro-Credentials/Badges": "Micro-Credentials/Badges Platform",
|
|
||||||
"Music/Entertainment": "Music Streaming",
|
|
||||||
"Quantum Computing": "Quantum Computing Interface",
|
|
||||||
"Real Estate": "Real Estate/Property",
|
|
||||||
"Remote Work/Collaboration": "Remote Work/Collaboration Tool",
|
|
||||||
"Restaurant/Food": "Restaurant/Food Service",
|
|
||||||
"SaaS Dashboard": "Analytics Dashboard",
|
|
||||||
"Space Tech/Aerospace": "Space Tech / Aerospace",
|
|
||||||
"Spatial Computing OS": "Spatial Computing OS / App",
|
|
||||||
"Startup Landing": "Micro SaaS",
|
|
||||||
"Sustainable Energy/Climate": "Sustainable Energy / Climate Tech",
|
|
||||||
"Travel/Tourism": "Travel/Tourism Agency",
|
|
||||||
"Wellness/Mental Health": "Mental Health App",
|
|
||||||
}
|
|
||||||
|
|
||||||
REMOVE_TYPES = {
|
|
||||||
"Service Landing Page", "Sustainability/ESG Platform",
|
|
||||||
"Cleaning Service", "Coffee Shop",
|
|
||||||
"Consulting Firm", "Conference/Webinar Platform",
|
|
||||||
}
|
|
||||||
|
|
||||||
# ─── New color definitions: (primary, secondary, accent, bg, notes) ──────────
|
|
||||||
# Grouped by category for clarity. Each tuple generates a full 16-token row.
|
|
||||||
NEW_COLORS = {
|
|
||||||
# ── Old #97-#116 that never got colors ──
|
|
||||||
"Todo & Task Manager": ("#2563EB","#3B82F6","#059669","#F8FAFC","Functional blue + progress green"),
|
|
||||||
"Personal Finance Tracker": ("#1E40AF","#3B82F6","#059669","#0F172A","Trust blue + profit green on dark"),
|
|
||||||
"Chat & Messaging App": ("#2563EB","#6366F1","#059669","#FFFFFF","Messenger blue + online green"),
|
|
||||||
"Notes & Writing App": ("#78716C","#A8A29E","#D97706","#FFFBEB","Warm ink + amber accent on cream"),
|
|
||||||
"Habit Tracker": ("#D97706","#F59E0B","#059669","#FFFBEB","Streak amber + habit green"),
|
|
||||||
"Food Delivery / On-Demand": ("#EA580C","#F97316","#2563EB","#FFF7ED","Appetizing orange + trust blue"),
|
|
||||||
"Ride Hailing / Transportation":("#1E293B","#334155","#2563EB","#0F172A","Map dark + route blue"),
|
|
||||||
"Recipe & Cooking App": ("#9A3412","#C2410C","#059669","#FFFBEB","Warm terracotta + fresh green"),
|
|
||||||
"Meditation & Mindfulness": ("#7C3AED","#8B5CF6","#059669","#FAF5FF","Calm lavender + mindful green"),
|
|
||||||
"Weather App": ("#0284C7","#0EA5E9","#F59E0B","#F0F9FF","Sky blue + sun amber"),
|
|
||||||
"Diary & Journal App": ("#92400E","#A16207","#6366F1","#FFFBEB","Warm journal brown + ink violet"),
|
|
||||||
"CRM & Client Management": ("#2563EB","#3B82F6","#059669","#F8FAFC","Professional blue + deal green"),
|
|
||||||
"Inventory & Stock Management":("#334155","#475569","#059669","#F8FAFC","Industrial slate + stock green"),
|
|
||||||
"Flashcard & Study Tool": ("#7C3AED","#8B5CF6","#059669","#FAF5FF","Study purple + correct green"),
|
|
||||||
"Booking & Appointment App": ("#0284C7","#0EA5E9","#059669","#F0F9FF","Calendar blue + available green"),
|
|
||||||
"Invoice & Billing Tool": ("#1E3A5F","#2563EB","#059669","#F8FAFC","Navy professional + paid green"),
|
|
||||||
"Grocery & Shopping List": ("#059669","#10B981","#D97706","#ECFDF5","Fresh green + food amber"),
|
|
||||||
"Timer & Pomodoro": ("#DC2626","#EF4444","#059669","#0F172A","Focus red on dark + break green"),
|
|
||||||
"Parenting & Baby Tracker": ("#EC4899","#F472B6","#0284C7","#FDF2F8","Soft pink + trust blue"),
|
|
||||||
"Scanner & Document Manager": ("#1E293B","#334155","#2563EB","#F8FAFC","Document grey + scan blue"),
|
|
||||||
# ── A. Utility / Productivity ──
|
|
||||||
"Calendar & Scheduling App": ("#2563EB","#3B82F6","#059669","#F8FAFC","Calendar blue + event green"),
|
|
||||||
"Password Manager": ("#1E3A5F","#334155","#059669","#0F172A","Vault dark blue + secure green"),
|
|
||||||
"Expense Splitter / Bill Split":("#059669","#10B981","#DC2626","#F8FAFC","Balance green + owe red"),
|
|
||||||
"Voice Recorder & Memo": ("#DC2626","#EF4444","#2563EB","#FFFFFF","Recording red + waveform blue"),
|
|
||||||
"Bookmark & Read-Later": ("#D97706","#F59E0B","#2563EB","#FFFBEB","Warm amber + link blue"),
|
|
||||||
"Translator App": ("#2563EB","#0891B2","#EA580C","#F8FAFC","Global blue + teal + accent orange"),
|
|
||||||
"Calculator & Unit Converter": ("#EA580C","#F97316","#2563EB","#1C1917","Operation orange on dark"),
|
|
||||||
"Alarm & World Clock": ("#D97706","#F59E0B","#6366F1","#0F172A","Time amber + night indigo on dark"),
|
|
||||||
"File Manager & Transfer": ("#2563EB","#3B82F6","#D97706","#F8FAFC","Folder blue + file amber"),
|
|
||||||
"Email Client": ("#2563EB","#3B82F6","#DC2626","#FFFFFF","Inbox blue + priority red"),
|
|
||||||
# ── B. Games ──
|
|
||||||
"Casual Puzzle Game": ("#EC4899","#8B5CF6","#F59E0B","#FDF2F8","Cheerful pink + reward gold"),
|
|
||||||
"Trivia & Quiz Game": ("#2563EB","#7C3AED","#F59E0B","#EFF6FF","Quiz blue + gold leaderboard"),
|
|
||||||
"Card & Board Game": ("#15803D","#166534","#D97706","#0F172A","Felt green + gold on dark"),
|
|
||||||
"Idle & Clicker Game": ("#D97706","#F59E0B","#7C3AED","#FFFBEB","Coin gold + prestige purple"),
|
|
||||||
"Word & Crossword Game": ("#15803D","#059669","#D97706","#FFFFFF","Word green + letter amber"),
|
|
||||||
"Arcade & Retro Game": ("#DC2626","#2563EB","#22C55E","#0F172A","Neon red+blue on dark + score green"),
|
|
||||||
# ── C. Creator Tools ──
|
|
||||||
"Photo Editor & Filters": ("#7C3AED","#6366F1","#0891B2","#0F172A","Editor violet + filter cyan on dark"),
|
|
||||||
"Short Video Editor": ("#EC4899","#DB2777","#2563EB","#0F172A","Video pink on dark + timeline blue"),
|
|
||||||
"Drawing & Sketching Canvas": ("#7C3AED","#8B5CF6","#0891B2","#1C1917","Canvas purple + tool teal on dark"),
|
|
||||||
"Music Creation & Beat Maker": ("#7C3AED","#6366F1","#22C55E","#0F172A","Studio purple + waveform green on dark"),
|
|
||||||
"Meme & Sticker Maker": ("#EC4899","#F59E0B","#2563EB","#FFFFFF","Viral pink + comedy yellow + share blue"),
|
|
||||||
"AI Photo & Avatar Generator": ("#7C3AED","#6366F1","#EC4899","#FAF5FF","AI purple + generation pink"),
|
|
||||||
"Link-in-Bio Page Builder": ("#2563EB","#7C3AED","#EC4899","#FFFFFF","Brand blue + creator purple"),
|
|
||||||
# ── D. Personal Life ──
|
|
||||||
"Wardrobe & Outfit Planner": ("#BE185D","#EC4899","#D97706","#FDF2F8","Fashion rose + gold accent"),
|
|
||||||
"Plant Care Tracker": ("#15803D","#059669","#D97706","#F0FDF4","Nature green + sun yellow"),
|
|
||||||
"Book & Reading Tracker": ("#78716C","#92400E","#D97706","#FFFBEB","Book brown + page amber"),
|
|
||||||
"Couple & Relationship App": ("#BE185D","#EC4899","#DC2626","#FDF2F8","Romance rose + love red"),
|
|
||||||
"Family Calendar & Chores": ("#2563EB","#059669","#D97706","#F8FAFC","Family blue + chore green"),
|
|
||||||
"Mood Tracker": ("#7C3AED","#6366F1","#D97706","#FAF5FF","Mood purple + insight amber"),
|
|
||||||
"Gift & Wishlist": ("#DC2626","#D97706","#EC4899","#FFF1F2","Gift red + gold + surprise pink"),
|
|
||||||
# ── E. Health ──
|
|
||||||
"Running & Cycling GPS": ("#EA580C","#F97316","#059669","#0F172A","Energetic orange + pace green on dark"),
|
|
||||||
"Yoga & Stretching Guide": ("#6B7280","#78716C","#0891B2","#F5F5F0","Sage neutral + calm teal"),
|
|
||||||
"Sleep Tracker": ("#4338CA","#6366F1","#7C3AED","#0F172A","Night indigo + dream violet on dark"),
|
|
||||||
"Calorie & Nutrition Counter": ("#059669","#10B981","#EA580C","#ECFDF5","Healthy green + macro orange"),
|
|
||||||
"Period & Cycle Tracker": ("#BE185D","#EC4899","#7C3AED","#FDF2F8","Blush rose + fertility lavender"),
|
|
||||||
"Medication & Pill Reminder": ("#0284C7","#0891B2","#DC2626","#F0F9FF","Medical blue + alert red"),
|
|
||||||
"Water & Hydration Reminder": ("#0284C7","#06B6D4","#0891B2","#F0F9FF","Refreshing blue + water cyan"),
|
|
||||||
"Fasting & Intermittent Timer":("#6366F1","#4338CA","#059669","#0F172A","Fasting indigo on dark + eating green"),
|
|
||||||
# ── F. Social ──
|
|
||||||
"Anonymous Community / Confession":("#475569","#334155","#0891B2","#0F172A","Protective grey + subtle teal on dark"),
|
|
||||||
"Local Events & Discovery": ("#EA580C","#F97316","#2563EB","#FFF7ED","Event orange + map blue"),
|
|
||||||
"Study Together / Virtual Coworking":("#2563EB","#3B82F6","#059669","#F8FAFC","Focus blue + session green"),
|
|
||||||
# ── G. Education ──
|
|
||||||
"Coding Challenge & Practice": ("#22C55E","#059669","#D97706","#0F172A","Code green + difficulty amber on dark"),
|
|
||||||
"Kids Learning (ABC & Math)": ("#2563EB","#F59E0B","#EC4899","#EFF6FF","Learning blue + play yellow + fun pink"),
|
|
||||||
"Music Instrument Learning": ("#DC2626","#9A3412","#D97706","#FFFBEB","Musical red + warm amber"),
|
|
||||||
# ── H. Transport ──
|
|
||||||
"Parking Finder": ("#2563EB","#059669","#DC2626","#F0F9FF","Available blue/green + occupied red"),
|
|
||||||
"Public Transit Guide": ("#2563EB","#0891B2","#EA580C","#F8FAFC","Transit blue + line colors"),
|
|
||||||
"Road Trip Planner": ("#EA580C","#0891B2","#D97706","#FFF7ED","Adventure orange + map teal"),
|
|
||||||
# ── I. Safety & Lifestyle ──
|
|
||||||
"VPN & Privacy Tool": ("#1E3A5F","#334155","#22C55E","#0F172A","Shield dark + connected green"),
|
|
||||||
"Emergency SOS & Safety": ("#DC2626","#EF4444","#2563EB","#FFF1F2","Alert red + safety blue"),
|
|
||||||
"Wallpaper & Theme App": ("#7C3AED","#EC4899","#2563EB","#FAF5FF","Aesthetic purple + trending pink"),
|
|
||||||
"White Noise & Ambient Sound": ("#475569","#334155","#4338CA","#0F172A","Ambient grey + deep indigo on dark"),
|
|
||||||
"Home Decoration & Interior Design":("#78716C","#A8A29E","#D97706","#FAF5F2","Interior warm grey + gold accent"),
|
|
||||||
}
|
|
||||||
|
|
||||||
# ─── 1. REBUILD colors.csv ───────────────────────────────────────────────────
|
|
||||||
def rebuild_colors():
|
|
||||||
src = os.path.join(BASE, "colors.csv")
|
|
||||||
with open(src, newline="", encoding="utf-8") as f:
|
|
||||||
reader = csv.DictReader(f)
|
|
||||||
headers = reader.fieldnames
|
|
||||||
existing = list(reader)
|
|
||||||
|
|
||||||
# Build lookup: Product Type -> row data
|
|
||||||
color_map = {}
|
|
||||||
for row in existing:
|
|
||||||
pt = row.get("Product Type", "").strip()
|
|
||||||
if not pt:
|
|
||||||
continue
|
|
||||||
# Remove deleted types
|
|
||||||
if pt in REMOVE_TYPES:
|
|
||||||
print(f" [colors] REMOVE: {pt}")
|
|
||||||
continue
|
|
||||||
# Rename mismatched types
|
|
||||||
if pt in COLOR_RENAMES:
|
|
||||||
new_name = COLOR_RENAMES[pt]
|
|
||||||
print(f" [colors] RENAME: {pt} → {new_name}")
|
|
||||||
row["Product Type"] = new_name
|
|
||||||
pt = new_name
|
|
||||||
color_map[pt] = row
|
|
||||||
|
|
||||||
# Read products.csv to get the correct order
|
|
||||||
with open(os.path.join(BASE, "products.csv"), newline="", encoding="utf-8") as f:
|
|
||||||
products = list(csv.DictReader(f))
|
|
||||||
|
|
||||||
# Build final rows in products.csv order
|
|
||||||
final_rows = []
|
|
||||||
added = 0
|
|
||||||
for i, prod in enumerate(products, 1):
|
|
||||||
pt = prod["Product Type"]
|
|
||||||
if pt in color_map:
|
|
||||||
row = color_map[pt]
|
|
||||||
row["No"] = str(i)
|
|
||||||
final_rows.append(row)
|
|
||||||
elif pt in NEW_COLORS:
|
|
||||||
pri, sec, acc, bg, notes = NEW_COLORS[pt]
|
|
||||||
new_row = derive_row(pt, pri, sec, acc, bg, notes)
|
|
||||||
d = dict(zip(headers, [str(i)] + new_row))
|
|
||||||
final_rows.append(d)
|
|
||||||
added += 1
|
|
||||||
else:
|
|
||||||
print(f" [colors] WARNING: No color data for '{pt}' - using defaults")
|
|
||||||
new_row = derive_row(pt, "#2563EB", "#3B82F6", "#059669", "#F8FAFC", "Auto-generated default")
|
|
||||||
d = dict(zip(headers, [str(i)] + new_row))
|
|
||||||
final_rows.append(d)
|
|
||||||
added += 1
|
|
||||||
|
|
||||||
# Write
|
|
||||||
with open(src, "w", newline="", encoding="utf-8") as f:
|
|
||||||
writer = csv.DictWriter(f, fieldnames=headers)
|
|
||||||
writer.writeheader()
|
|
||||||
writer.writerows(final_rows)
|
|
||||||
|
|
||||||
product_count = len(products)
|
|
||||||
print(f"\n ✅ colors.csv: {len(final_rows)} rows ({product_count} products)")
|
|
||||||
print(f" Added: {added} new color rows")
|
|
||||||
|
|
||||||
# ─── 2. REBUILD ui-reasoning.csv ─────────────────────────────────────────────
|
|
||||||
def derive_ui_reasoning(prod):
|
|
||||||
"""Generate ui-reasoning row from products.csv row."""
|
|
||||||
pt = prod["Product Type"]
|
|
||||||
style = prod.get("Primary Style Recommendation", "")
|
|
||||||
landing = prod.get("Landing Page Pattern", "")
|
|
||||||
color_focus = prod.get("Color Palette Focus", "")
|
|
||||||
considerations = prod.get("Key Considerations", "")
|
|
||||||
keywords = prod.get("Keywords", "")
|
|
||||||
|
|
||||||
# Typography mood derived from style
|
|
||||||
typo_map = {
|
|
||||||
"Minimalism": "Professional + Clean hierarchy",
|
|
||||||
"Glassmorphism": "Modern + Clear hierarchy",
|
|
||||||
"Brutalism": "Bold + Oversized + Monospace",
|
|
||||||
"Claymorphism": "Playful + Rounded + Friendly",
|
|
||||||
"Dark Mode": "High contrast + Light on dark",
|
|
||||||
"Neumorphism": "Subtle + Soft + Monochromatic",
|
|
||||||
"Flat Design": "Bold + Clean + Sans-serif",
|
|
||||||
"Vibrant": "Energetic + Bold + Large",
|
|
||||||
"Aurora": "Elegant + Gradient-friendly",
|
|
||||||
"AI-Native": "Conversational + Minimal chrome",
|
|
||||||
"Organic": "Warm + Humanist + Natural",
|
|
||||||
"Motion": "Dynamic + Hierarchy-shifting",
|
|
||||||
"Accessible": "Large + High contrast + Clear",
|
|
||||||
"Soft UI": "Modern + Accessible + Balanced",
|
|
||||||
"Trust": "Professional + Serif accents",
|
|
||||||
"Swiss": "Grid-based + Mathematical + Helvetica",
|
|
||||||
"3D": "Immersive + Spatial + Variable",
|
|
||||||
"Retro": "Nostalgic + Monospace + Neon",
|
|
||||||
"Cyberpunk": "Terminal + Monospace + Neon",
|
|
||||||
"Pixel": "Retro + Blocky + 8-bit",
|
|
||||||
}
|
|
||||||
typo_mood = "Professional + Clear hierarchy"
|
|
||||||
for key, val in typo_map.items():
|
|
||||||
if key.lower() in style.lower():
|
|
||||||
typo_mood = val
|
|
||||||
break
|
|
||||||
|
|
||||||
# Key effects from style
|
|
||||||
eff_map = {
|
|
||||||
"Glassmorphism": "Backdrop blur (10-20px) + Translucent overlays",
|
|
||||||
"Neumorphism": "Dual shadows (light+dark) + Soft press 150ms",
|
|
||||||
"Claymorphism": "Multi-layer shadows + Spring bounce + Soft press 200ms",
|
|
||||||
"Brutalism": "No transitions + Hard borders + Instant feedback",
|
|
||||||
"Dark Mode": "Subtle glow + Neon accents + High contrast",
|
|
||||||
"Flat Design": "Color shift hover + Fast 150ms transitions + No shadows",
|
|
||||||
"Minimalism": "Subtle hover 200ms + Smooth transitions + Clean",
|
|
||||||
"Motion-Driven": "Scroll animations + Parallax + Page transitions",
|
|
||||||
"Micro-interactions": "Haptic feedback + Small 50-100ms animations",
|
|
||||||
"Vibrant": "Large section gaps 48px+ + Color shift hover + Scroll-snap",
|
|
||||||
"Aurora": "Flowing gradients 8-12s + Color morphing",
|
|
||||||
"AI-Native": "Typing indicator + Streaming text + Context reveal",
|
|
||||||
"Organic": "Rounded 16-24px + Natural shadows + Flowing SVG",
|
|
||||||
"Soft UI": "Improved shadows + Modern 200-300ms + Focus visible",
|
|
||||||
"3D": "WebGL/Three.js + Parallax 3-5 layers + Physics 300-400ms",
|
|
||||||
"Trust": "Clear focus rings + Badge hover + Metric pulse",
|
|
||||||
"Accessible": "Focus rings 3-4px + ARIA + Reduced motion",
|
|
||||||
}
|
|
||||||
key_effects = "Subtle hover (200ms) + Smooth transitions"
|
|
||||||
for key, val in eff_map.items():
|
|
||||||
if key.lower() in style.lower():
|
|
||||||
key_effects = val
|
|
||||||
break
|
|
||||||
|
|
||||||
# Decision rules
|
|
||||||
rules = {}
|
|
||||||
if "dark" in style.lower() or "oled" in style.lower():
|
|
||||||
rules["if_light_mode_needed"] = "provide-theme-toggle"
|
|
||||||
if "glass" in style.lower():
|
|
||||||
rules["if_low_performance"] = "fallback-to-flat"
|
|
||||||
if "conversion" in landing.lower():
|
|
||||||
rules["if_conversion_focused"] = "add-urgency-colors"
|
|
||||||
if "social" in landing.lower():
|
|
||||||
rules["if_trust_needed"] = "add-testimonials"
|
|
||||||
if "data" in keywords.lower() or "dashboard" in keywords.lower():
|
|
||||||
rules["if_data_heavy"] = "prioritize-data-density"
|
|
||||||
if not rules:
|
|
||||||
rules["if_ux_focused"] = "prioritize-clarity"
|
|
||||||
rules["if_mobile"] = "optimize-touch-targets"
|
|
||||||
|
|
||||||
# Anti-patterns
|
|
||||||
anti_patterns = []
|
|
||||||
if "minimalism" in style.lower() or "minimal" in style.lower():
|
|
||||||
anti_patterns.append("Excessive decoration")
|
|
||||||
if "dark" in style.lower():
|
|
||||||
anti_patterns.append("Pure white backgrounds")
|
|
||||||
if "flat" in style.lower():
|
|
||||||
anti_patterns.append("Complex shadows + 3D effects")
|
|
||||||
if "vibrant" in style.lower():
|
|
||||||
anti_patterns.append("Muted colors + Low energy")
|
|
||||||
if "accessible" in style.lower():
|
|
||||||
anti_patterns.append("Color-only indicators")
|
|
||||||
if not anti_patterns:
|
|
||||||
anti_patterns = ["Inconsistent styling", "Poor contrast ratios"]
|
|
||||||
anti_str = " + ".join(anti_patterns[:2])
|
|
||||||
|
|
||||||
return {
|
|
||||||
"UI_Category": pt,
|
|
||||||
"Recommended_Pattern": landing,
|
|
||||||
"Style_Priority": style,
|
|
||||||
"Color_Mood": color_focus,
|
|
||||||
"Typography_Mood": typo_mood,
|
|
||||||
"Key_Effects": key_effects,
|
|
||||||
"Decision_Rules": json.dumps(rules),
|
|
||||||
"Anti_Patterns": anti_str,
|
|
||||||
"Severity": "HIGH"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def rebuild_ui_reasoning():
|
|
||||||
src = os.path.join(BASE, "ui-reasoning.csv")
|
|
||||||
with open(src, newline="", encoding="utf-8") as f:
|
|
||||||
reader = csv.DictReader(f)
|
|
||||||
headers = reader.fieldnames
|
|
||||||
existing = list(reader)
|
|
||||||
|
|
||||||
# Build lookup
|
|
||||||
ui_map = {}
|
|
||||||
for row in existing:
|
|
||||||
cat = row.get("UI_Category", "").strip()
|
|
||||||
if not cat:
|
|
||||||
continue
|
|
||||||
if cat in REMOVE_TYPES:
|
|
||||||
print(f" [ui-reason] REMOVE: {cat}")
|
|
||||||
continue
|
|
||||||
if cat in UI_RENAMES:
|
|
||||||
new_name = UI_RENAMES[cat]
|
|
||||||
print(f" [ui-reason] RENAME: {cat} → {new_name}")
|
|
||||||
row["UI_Category"] = new_name
|
|
||||||
cat = new_name
|
|
||||||
ui_map[cat] = row
|
|
||||||
|
|
||||||
with open(os.path.join(BASE, "products.csv"), newline="", encoding="utf-8") as f:
|
|
||||||
products = list(csv.DictReader(f))
|
|
||||||
|
|
||||||
final_rows = []
|
|
||||||
added = 0
|
|
||||||
for i, prod in enumerate(products, 1):
|
|
||||||
pt = prod["Product Type"]
|
|
||||||
if pt in ui_map:
|
|
||||||
row = ui_map[pt]
|
|
||||||
row["No"] = str(i)
|
|
||||||
final_rows.append(row)
|
|
||||||
else:
|
|
||||||
row = derive_ui_reasoning(prod)
|
|
||||||
row["No"] = str(i)
|
|
||||||
final_rows.append(row)
|
|
||||||
added += 1
|
|
||||||
|
|
||||||
with open(src, "w", newline="", encoding="utf-8") as f:
|
|
||||||
writer = csv.DictWriter(f, fieldnames=headers)
|
|
||||||
writer.writeheader()
|
|
||||||
writer.writerows(final_rows)
|
|
||||||
|
|
||||||
print(f"\n ✅ ui-reasoning.csv: {len(final_rows)} rows")
|
|
||||||
print(f" Added: {added} new reasoning rows")
|
|
||||||
|
|
||||||
|
|
||||||
# ─── MAIN ────────────────────────────────────────────────────────────────────
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("=== Rebuilding colors.csv ===")
|
|
||||||
rebuild_colors()
|
|
||||||
print("\n=== Rebuilding ui-reasoning.csv ===")
|
|
||||||
rebuild_ui_reasoning()
|
|
||||||
print("\n🎉 Done!")
|
|
||||||
-1776
File diff suppressed because it is too large
Load Diff
-1779
File diff suppressed because it is too large
Load Diff
+15
-4
@@ -16,6 +16,7 @@ Usage:
|
|||||||
import csv
|
import csv
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import io
|
import io
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -695,6 +696,17 @@ def generate_design_system(query: str, project_name: str = None, output_format:
|
|||||||
|
|
||||||
|
|
||||||
# ============ PERSISTENCE FUNCTIONS ============
|
# ============ PERSISTENCE FUNCTIONS ============
|
||||||
|
def safe_slug(name, fallback: str = "default") -> str:
|
||||||
|
"""Slugify a name into a single safe path segment.
|
||||||
|
|
||||||
|
Only [a-z0-9_-] survives; every other character (including '/', '\\' and
|
||||||
|
'.') collapses into '-'. This makes path traversal via project/page names
|
||||||
|
(e.g. "../../etc") impossible — the slug can never leave its parent dir.
|
||||||
|
"""
|
||||||
|
slug = re.sub(r'[^a-z0-9_-]+', '-', str(name).lower()).strip('-')
|
||||||
|
return slug or fallback
|
||||||
|
|
||||||
|
|
||||||
def persist_design_system(design_system: dict, page: str = None, output_dir: str = None, page_query: str = None) -> dict:
|
def persist_design_system(design_system: dict, page: str = None, output_dir: str = None, page_query: str = None) -> dict:
|
||||||
"""
|
"""
|
||||||
Persist design system to design-system/<project>/ folder using Master + Overrides pattern.
|
Persist design system to design-system/<project>/ folder using Master + Overrides pattern.
|
||||||
@@ -711,9 +723,8 @@ def persist_design_system(design_system: dict, page: str = None, output_dir: str
|
|||||||
base_dir = Path(output_dir) if output_dir else Path.cwd()
|
base_dir = Path(output_dir) if output_dir else Path.cwd()
|
||||||
|
|
||||||
# Use project name for project-specific folder. Coalesce falsy values
|
# Use project name for project-specific folder. Coalesce falsy values
|
||||||
# (missing key, explicit None, or "") so the .lower() below can't crash.
|
# (missing key, explicit None, or "") so slugification can't crash.
|
||||||
project_name = design_system.get("project_name") or "default"
|
project_slug = safe_slug(design_system.get("project_name") or "default")
|
||||||
project_slug = project_name.lower().replace(' ', '-')
|
|
||||||
|
|
||||||
design_system_dir = base_dir / "design-system" / project_slug
|
design_system_dir = base_dir / "design-system" / project_slug
|
||||||
pages_dir = design_system_dir / "pages"
|
pages_dir = design_system_dir / "pages"
|
||||||
@@ -734,7 +745,7 @@ def persist_design_system(design_system: dict, page: str = None, output_dir: str
|
|||||||
|
|
||||||
# If page is specified, create page override file with intelligent content
|
# If page is specified, create page override file with intelligent content
|
||||||
if page:
|
if page:
|
||||||
page_file = pages_dir / f"{page.lower().replace(' ', '-')}.md"
|
page_file = pages_dir / f"{safe_slug(page, 'page')}.md"
|
||||||
page_content = format_page_override_md(design_system, page, page_query)
|
page_content = format_page_override_md(design_system, page, page_query)
|
||||||
with open(page_file, 'w', encoding='utf-8') as f:
|
with open(page_file, 'w', encoding='utf-8') as f:
|
||||||
f.write(page_content)
|
f.write(page_content)
|
||||||
|
|||||||
+3
-3
@@ -24,7 +24,7 @@ import argparse
|
|||||||
import sys
|
import sys
|
||||||
import io
|
import io
|
||||||
from core import CSV_CONFIG, AVAILABLE_STACKS, MAX_RESULTS, search, search_stack
|
from core import CSV_CONFIG, AVAILABLE_STACKS, MAX_RESULTS, search, search_stack
|
||||||
from design_system import generate_design_system, persist_design_system
|
from design_system import generate_design_system, persist_design_system, safe_slug
|
||||||
|
|
||||||
# Force UTF-8 for stdout/stderr to handle emojis on Windows (cp1252 default)
|
# Force UTF-8 for stdout/stderr to handle emojis on Windows (cp1252 default)
|
||||||
if sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8':
|
if sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8':
|
||||||
@@ -98,12 +98,12 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# Print persistence confirmation
|
# Print persistence confirmation
|
||||||
if args.persist:
|
if args.persist:
|
||||||
project_slug = (args.project_name or args.query).lower().replace(' ', '-')
|
project_slug = safe_slug(args.project_name or args.query.upper())
|
||||||
print("\n" + "=" * 60)
|
print("\n" + "=" * 60)
|
||||||
print(f"✅ Design system persisted to design-system/{project_slug}/")
|
print(f"✅ Design system persisted to design-system/{project_slug}/")
|
||||||
print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)")
|
print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)")
|
||||||
if args.page:
|
if args.page:
|
||||||
page_filename = args.page.lower().replace(' ', '-')
|
page_filename = safe_slug(args.page, 'page')
|
||||||
print(f" 📄 design-system/{project_slug}/pages/{page_filename}.md (Page Overrides)")
|
print(f" 📄 design-system/{project_slug}/pages/{page_filename}.md (Page Overrides)")
|
||||||
print("")
|
print("")
|
||||||
print(f"📖 Usage: When building a page, check design-system/{project_slug}/pages/[page].md first.")
|
print(f"📖 Usage: When building a page, check design-system/{project_slug}/pages/[page].md first.")
|
||||||
|
|||||||
Reference in New Issue
Block a user