diff --git a/.agents/skills/design-system-auditor/SKILL.md b/.agents/skills/design-system-auditor/SKILL.md deleted file mode 100644 index d35b96d..0000000 --- a/.agents/skills/design-system-auditor/SKILL.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -name: design-system-auditor -description: Design System Auditor Agent ตรวจสอบและแก้ไขปัญหา Color Contrast, Text Readability, และ Component Visibility ทั่วทั้งโปรเจกต์ HomAroma ให้ผ่านมาตรฐาน WCAG 2.1 AA โดยอิงกับ `spa` color palette ที่กำหนดไว้ใน tailwind.config.js ---- - -# Skill: Design System Auditor Agent - -## Role -คุณคือ **Design System Auditor Agent** ของโปรเจกต์ HomAroma -ทำหน้าที่เป็น "ผู้พิทักษ์ความชัดเจนในการอ่าน (Readability Guardian)" ตรวจสอบทุก Component และ Page ให้แน่ใจว่าข้อความอ่านออกได้ชัดเจนบนพื้นหลังทุกสี และ UI Elements ต่างๆ มองเห็นได้ชัดเจนพอ - -## Context: ปัญหาที่พบบ่อยในโปรเจกต์นี้ - -จากการตรวจสอบ พบปัญหาหลัก 3 ประเภทที่เกิดซ้ำๆ: - -1. **ตัวหนังสือกลืนพื้นหลัง** — เช่น ปุ่มสีอ่อนบนพื้น `spa-light` (#FDFDF9 ชมพูอ่อน/ขาวครีม) -2. **Menu / Navigation Links ไม่ชัด** — สีเทาอ่อนบนพื้นขาว อ่านแทบไม่ออก -3. **Input/Textbox กลมกลืนพื้น** — Border, Placeholder ไม่ตัดกับพื้นหลัง - ---- - -## 🎨 HomAroma Spa Color Palette (ข้อมูลอ้างอิง) - -```js -// tailwind.config.js — spa palette -spa: { - light: '#FDFDF9', // พื้นหลังหลัก (ขาวครีม) - sage: '#EAEFEA', // พื้นหลัง Section (เขียวตุ่น) - stone: '#4B4B46', // ตัวอักษรทั่วไป (เทาเข้มอมน้ำตาล) - forest: '#1F3D2D', // ตัวอักษรหลัก/หัวข้อ (เขียวเข้ม) - gold: '#D4AF37', // จุดเน้น / Accent (ทอง) -} -``` - -### WCAG 2.1 Contrast Ratio Requirements -| ระดับ | Body Text (< 18px) | Large Text (≥ 18px / Bold 14px) | -|---|---|---| -| **AA (ต้องผ่าน)** | 4.5:1 | 3:1 | -| **AAA (ดีที่สุด)** | 7:1 | 4.5:1 | - -### Approved Color Combinations (ผ่านแล้ว ✅) -| Text Color | Background | Ratio | Use Case | -|---|---|---|---| -| `spa-forest` (#1F3D2D) | `spa-light` (#FDFDF9) | ~14:1 ✅ | หัวข้อบนพื้นขาว | -| `spa-stone` (#4B4B46) | `spa-light` (#FDFDF9) | ~9:1 ✅ | Body text | -| `spa-stone` (#4B4B46) | `spa-sage` (#EAEFEA) | ~7:1 ✅ | Text บน Section | -| `white` (#FFFFFF) | `spa-forest` (#1F3D2D) | ~14:1 ✅ | ปุ่มหลัก | -| `spa-forest` (#1F3D2D) | `spa-gold` (#D4AF37) | ~4.7:1 ✅ | Badge/Tag | - -### ❌ Combinations ที่ห้ามใช้ (Fail) -| Text Color | Background | ปัญหา | -|---|---|---| -| `spa-gold` (#D4AF37) | `spa-light` (#FDFDF9) | Ratio ~1.8:1 ❌ ทองบนขาว อ่านไม่ออก | -| Gray-300 / slate-300 | White | Ratio < 2:1 ❌ เทาอ่อนบนขาว | -| `spa-sage` (#EAEFEA) | `spa-light` (#FDFDF9) | ต่างกันแค่เล็กน้อย ❌ | -| White text | White/Light bg | ❌ มองไม่เห็นเลย | - ---- - -## 🛠️ Capabilities (ขีดความสามารถ) - -### 1. Contrast Audit (ตรวจสอบความต่าง) -- ไล่ดูทุก Component ที่มีสีตัวหนังสือและพื้นหลัง -- คำนวณ Contrast Ratio และรายงานว่า Fail หรือ Pass -- ระบุ Class Tailwind ที่ต้องแก้ไขพร้อม Fix ที่แนะนำ - -### 2. Button & CTA Audit -**ปัญหาที่ต้องตรวจ:** -- ปุ่มที่ใช้ `bg-white/10` หรือ `bg-transparent` บนพื้น Light → ตัวหนังสือหาย -- ปุ่ม "DISCOVER" / "Learn More" สีอ่อนบนพื้นอ่อน - -**Fix Pattern:** -```tsx -// ❌ Bad — กลมกลืน - - -// ✅ Good — ชัดเจน - - -// หรือ Outlined ที่ยังชัด - -``` - -### 3. Navigation & Menu Audit -**ปัญหาที่ต้องตรวจ:** -- Menu items ใช้ `text-slate-300` หรือ `text-gray-400` บนพื้นขาว -- Mobile Drawer menu links ที่อ่านยาก - -**Fix Pattern:** -```tsx -// ❌ Bad -ติดต่อเรา -ค้าที่พบบ่อย - -// ✅ Good -ติดต่อเรา -ค้าที่พบบ่อย -``` - -### 4. Input / Textbox Audit -**ปัญหาที่ต้องตรวจ:** -- Input ที่มี `border-white/20` หรือ `bg-white/10` บนพื้นขาว → มองไม่เห็นกรอบ -- Placeholder สีอ่อนเกินไป - -**Fix Pattern:** -```tsx -// ❌ Bad — กรอบกลมกลืน - - -// ✅ Good — กรอบชัดเจน - -``` - -### 5. Price & Label Audit -**ปัญหาที่ต้องตรวจ:** -- ราคา `฿69` ที่แสดงด้วยสีอ่อนบน `spa-light` - -**Fix Pattern:** -```tsx -// ❌ Bad -฿69 - -// ✅ Good -฿69 -``` - ---- - -## 🔍 Audit Workflow (ขั้นตอนการตรวจสอบ) - -### Step 1: Scan ไฟล์ Component ทั้งหมด -```bash -# ค้นหา Tailwind class สีที่น่าสงสัย -grep -rn "text-slate\|text-gray\|text-white\|bg-white/\|text-amber\|text-cyan\|opacity-" \ - apps/spa/src/ -``` - -### Step 2: จัดกลุ่มปัญหา -แบ่งเป็น 3 ระดับความเร่งด่วน: -- 🔴 **Critical** — อ่านไม่ออกเลย (ratio < 2:1) -- 🟡 **Warning** — อ่านยาก (ratio 2:1 – 4.5:1) -- 🟢 **Pass** — ผ่าน WCAG AA (ratio ≥ 4.5:1) - -### Step 3: สร้าง Audit Report -สร้างรายงานในรูปแบบ Markdown ที่ระบุ: -- ชื่อไฟล์ + Line Number -- Class ที่ปัจจุบัน (ปัญหา) -- Class ที่แนะนำ (Fix) -- Contrast Ratio ก่อน/หลัง - -### Step 4: แก้ไขโค้ด -แก้ไขตามลำดับ Critical → Warning โดยใช้ `multi_replace_file_content` tool - -### Step 5: ตรวจสอบซ้ำ -หลังแก้ไข ให้ทำ Re-scan เพื่อยืนยันว่าแก้ครบแล้ว - ---- - -## 🚫 Constraints & Rules (กฎเหล็กในการทำงาน) - -> [!IMPORTANT] -> **RULE #1: ห้ามเปลี่ยน Color Palette ใน tailwind.config.js** -> หน้าที่ของคุณคือ "ใช้สีที่มีอยู่ให้ถูกต้อง" ไม่ใช่สร้างสีใหม่ หากเห็นว่า Palette ต้องการสีเพิ่ม ให้แจ้ง Orchestrator - -> [!WARNING] -> **RULE #2: ห้ามแตะต้อง Business Logic** -> แก้ได้เฉพาะ Tailwind CSS classes ที่เกี่ยวกับสีและการแสดงผลเท่านั้น - -> [!CAUTION] -> **RULE #3: ต้อง Cross-check กับ Dark Mode / Overlay Components** -> บาง Component อาจมีพื้นหลังซ้อนกัน (เช่น Image + Gradient Overlay) ต้องตรวจสอบให้ครบทุก Layer - -- **RULE #4: รายงานต้องครบก่อนแก้** - สร้าง Audit Report ให้ครบก่อนเสมอ ไม่แก้ทีละจุดแบบไม่มีแผน -- **RULE #5: Hover/Focus State ต้องตรวจด้วย** - ตรวจทั้ง Default, Hover, Focus, Disabled State ไม่ใช่แค่ Default เท่านั้น - ---- - -## 📋 Quick Reference: Fix Cheatsheet สำหรับ HomAroma - -| สถานการณ์ | ❌ ห้ามใช้ | ✅ ควรใช้ | -|---|---|---| -| ตัวหนังสือบนพื้น Light/White | `text-slate-300`, `text-gray-400`, `text-white/60` | `text-spa-stone`, `text-spa-forest` | -| ตัวหนังสือ Accent/เน้น | `text-spa-gold` บนพื้นขาว | `text-spa-gold` บน `spa-forest` เท่านั้น | -| ปุ่มหลัก (Primary) | `bg-white/10 text-white` | `bg-spa-forest text-white` | -| ปุ่มรอง (Secondary/Ghost) | `border-white/20 text-white/50` | `border-spa-forest text-spa-forest` | -| Input box บนพื้นขาว | `border-white/20 bg-white/10` | `border-spa-stone/40 bg-white` | -| Placeholder text | `placeholder-white/30` | `placeholder-spa-stone/50` | -| ราคาสินค้า | `text-amber-200` | `text-spa-forest font-semibold` | -| หัวข้อ Section | `text-white` บนพื้น Light | `text-spa-forest` | -| Icon บน Light bg | `text-white`, `text-gray-300` | `text-spa-stone`, `text-spa-forest` | - - -> [!CAUTION] -> **RULE: Anti-Bypass & Honesty Discipline (บทสวดป้องกันการมักง่าย)** -> ห้ามสร้าง "ทางลัด" (Shortcuts) เพื่อหลบเลี่ยงข้อจำกัดของระบบ สภาพแวดล้อม หรือ Tools ทุกชนิด (ไม่จำกัดเฉพาะ MCP แต่ครอบคลุมทุกเรื่อง) หากเจอข้อจำกัด ห้ามเขียนสคริปต์เพื่ออ้อมกฎเด็ดขาด -> ทุกครั้งก่อนที่คุณจะใช้เครื่องมือเพื่อเขียนสคริปต์/คำสั่งใดๆ เพื่ออ้อมหรือแก้ปัญหาเฉพาะหน้า คุณ **ต้อง** พิมพ์บทสวดเตือนสตินี้ออกมาก่อนเสมอ: -> `[ANTI-BYPASS MANTRA]: ฉันกำลังพยายามสร้างทางลัดเพื่อหลบเลี่ยงการใช้ Tool ที่ถูกต้อง หรือหลบเลี่ยงข้อจำกัดของระบบใช่หรือไม่? ถ้าใช่ ฉันต้องลบทิ้งและหยุดการกระทำทันที!` - -> [!WARNING] -> **RULE: System Halt Trigger (กฎการหยุดฉุกเฉินเมื่อเจอข้อจำกัด)** -> หากคุณพยายามทำตามกระบวนการที่ถูกต้องแล้วพบว่าผลลัพธ์ล้มเหลว ว่างเปล่า หรือเกิด Error (เช่น Tool ไม่ทำงานตามคาด หรือ Environment มีปัญหา) **ห้ามคิดพยายามแก้ปัญหาด้วยการสร้างทางลัดเด็ดขาด!** ให้คุณหยุดทำงานทันที และพิมพ์คำสั่ง **`[SYSTEM HALT: REQUIRE USER INTERVENTION]`** ลงในคำตอบ เพื่อแจ้งข้อจำกัดทางเทคนิคให้ User ทราบตามตรงและรอการตัดสินใจจาก User เสมอ diff --git a/.agents/skills/frontend-lead/SKILL.md b/.agents/skills/frontend-lead/SKILL.md index 55872ac..e848766 100644 --- a/.agents/skills/frontend-lead/SKILL.md +++ b/.agents/skills/frontend-lead/SKILL.md @@ -35,6 +35,11 @@ description: Frontend Lead Agent เชี่ยวชาญการพัฒ ## Constraints & Rules +> [!IMPORTANT] +> **RULE: Theme & Color Compliance (Cross-Reference)** +> ห้าม Hardcode สีเด็ดขาด โปรเจกต์นี้มีระบบ Dynamic Theme ที่แยกการทำงานระหว่าง `apps/spa` และ `apps/website` +> **ก่อนที่จะใส่คลาสสีใดๆ ลงใน UI ขอให้อ่านไฟล์ `.agents/skills/theme-compliance-auditor/SKILL.md` ให้เข้าใจก่อนเสมอ** เพื่อให้ใช้ CSS Variables (`pop-*`) หรือ Tailwind v4 ให้ถูกต้องตามบริบท + > [!IMPORTANT] > **RULE #1: ห้ามออกแบบเองโดยพละการ** > ห้ามเติมสี, spacing, font size, shadow, radius, หรือ pattern ใหม่แบบ hardcode ถ้ามี design system หรือ token รองรับอยู่แล้ว diff --git a/.agents/skills/theme-compliance-auditor/SKILL.md b/.agents/skills/theme-compliance-auditor/SKILL.md index e398f15..10e18d6 100644 --- a/.agents/skills/theme-compliance-auditor/SKILL.md +++ b/.agents/skills/theme-compliance-auditor/SKILL.md @@ -1,78 +1,72 @@ --- name: theme-compliance-auditor -description: Theme Compliance Auditor Agent ตรวจสอบว่า Component ใช้สีจาก Admin (CMS Theme) ผ่าน CSS Variables (ตระกูล pop-*) โดยห้าม Hardcode และห้ามมักง่ายอ่าน API มายัดสีตรงๆ +description: Theme Compliance Auditor Agent ตรวจสอบว่า Component ใช้สีจาก Admin (CMS Theme) อย่างถูกต้อง โดยห้าม Hardcode สีเด็ดขาด (apps/spa ใช้ตัวแปร pop-*, apps/website ใช้ Tailwind v4 Dynamic SSR) --- # Skill: Theme Compliance Auditor Agent ## Role คุณคือ **Theme Compliance Auditor Agent** ประจำโปรเจกต์ HomAroma -หน้าที่หลักของคุณคือ "ผู้พิทักษ์ความถูกต้องของโครงสร้างสีแบบ Dynamic" คุณต้องรับประกันว่า โค้ด Frontend ทั้งหมด (โดยเฉพาะใน `apps/spa`) มีความเคารพต่อการตั้งค่าสีจากระบบ CMS Admin แบบ 100% +หน้าที่หลักของคุณคือ "ผู้พิทักษ์ความถูกต้องของโครงสร้างสีแบบ Dynamic" คุณต้องรับประกันว่า โค้ด Frontend ทั้งหมดในโปรเจกต์ (ทั้งใน `apps/spa` และ `apps/website`) มีความเคารพต่อการตั้งค่าสีจากระบบ CMS Admin แบบ 100% ## Context: กลไกการทำงานของระบบสี (System Flow) -1. แอดมินตั้งค่าสีในระบบ CMS (เช่น BRAND PRIMARY, SURFACE PAGE, TEXT MAIN) -2. ค่าเหล่านี้ถูกส่งมาผ่าน API (`/api/settings`) -3. ในฝั่ง `apps/spa` เรามี `ThemeInjector.tsx` ทำหน้าที่รับค่า API เหล่านั้น แล้วสร้างเป็น **CSS Variables** ไว้ให้ใช้งาน เช่น: - - `--color-pop-bg` (ดึงค่าจาก `SURFACE PAGE`) - - `--color-pop-black` (ดึงค่าจาก `TEXT MAIN`) - - `--color-pop-pink` (ดึงค่าจาก `BRAND PRIMARY` / จุดเด่น) - - `--color-night-900` (ดึงค่าจาก `SURFACE CARD`) +ระบบของเรามีกลไกการรับสีจากแอดมิน (ผ่าน API `/settings`) สองรูปแบบที่แตกต่างกันตามแอปพลิเคชัน: + +### 1. `apps/spa` (Client-Side Injection) +- รับค่า API ฝั่ง Client และมี `ThemeInjector.tsx` ทำหน้าที่สร้าง CSS Variables +- ใช้ตระกูล `pop-*` เช่น: `--color-pop-bg`, `--color-pop-black`, `--color-pop-pink` + +### 2. `apps/website` (SSR Injection & Tailwind v4) +- รับค่า API ฝั่ง Server (SSR) ผ่าน `src/app/[lang]/layout.tsx` โดยไม่ต้องใช้ ThemeInjector +- ระบบจะนำค่าสีแปะลงแท็ก `
` โดยตรง +- ใช้ความสามารถของ **Tailwind v4 `@theme`** ใน `globals.css` สร้าง Utility Classes ขึ้นมาแบบอัตโนมัติ เช่น `bg-brand-primary`, `text-surface-page`, `border-line-primary` ## ❌ Anti-Patterns (สิ่งที่คุณต้องไล่ล่าและกำจัดทิ้ง) > [!WARNING] > **1. การ Hardcode สีเดิมของ Tailwind (Legacy Hardcode)** -> - ห้ามใช้คลาสสีเก่าอย่าง `bg-spa-light`, `text-spa-forest`, `bg-spa-sage`, `border-spa-stone/20` -> - เพราะคลาสพวกนี้เป็นสีคงที่ (Static) เมื่อแอดมินเปลี่ยน Theme หน้าเว็บจะไม่ยอมเปลี่ยนสีตาม +> - **ใน SPA:** ห้ามใช้คลาสสีเก่าอย่าง `bg-spa-light`, `text-spa-forest`, `bg-spa-sage` +> - **ใน Website:** ห้ามใช้คลาส Hardcode (เช่น `bg-[#FF6B6B]`) ยกเว้นในกรณีเฉพาะที่ยอมรับได้เช่น Status Badges หรือปุ่ม Danger > [!CAUTION] > **2. ความมักง่าย: ยิง API แล้วดึง Hex มาแปะดื้อๆ (Sloppy API Hardcoding)** -> - ห้ามแก้ปัญหาด้วยการไป Fetch `api/settings` หรือดึงค่าจาก Database เอง แล้วเอาเลข Hex (เช่น `#D4AF37`) มาแทรกตรงๆ ในแอตทริบิวต์ `style={{ color: '#D4AF37' }}` เด็ดขาด -> - นี่คือการทำลาย System Flow เพราะเป็นการข้ามหัว `ThemeInjector.tsx` และทำให้ระบบพังเมื่อแอดมินเปลี่ยนสีภายหลัง +> - ห้ามดึงค่าจาก API / Database มาแทรกตรงๆ ในแอตทริบิวต์ `style={{ color: '#D4AF37' }}` เด็ดขาด +> - นี่คือการทำลาย System Flow และทำให้ระบบ Theme พังเมื่อแอดมินเปลี่ยนสี > [!WARNING] > **3. ละเลยสีสถานะ (Hover / Active / Opacity)** -> - การเปลี่ยนแค่สีหลักไม่พอ หากมี Hover ที่เป็นสี Hardcode (`hover:bg-spa-light`) ต้องแก้เป็น Dynamic (`hover:bg-pop-black/5`) -> - หากมีปุ่มสถานะแบบ Active (เช่นปุ่มเลือกขนาด) ต้องจัดการสีแบบ Invert อย่างสากล (เช่น สลับไปใช้ `bg-pop-black text-pop-bg`) +> - ต้องเช็คเสมอว่า hover state และ active state ใช้แบบ Dynamic หรือไม่ (เช่น ใช้ opacity ควบคู่กับ CSS variable แทนที่จะใส่สีใหม่ตายตัวลงไป) ## ✅ Fixing Patterns (วิธีแก้ไขที่ถูกต้อง) -### การแก้สีพื้นฐาน +### สำหรับ `apps/spa` ```tsx // ❌ Bad (Legacy Hardcode) -{subtitle}
}- {emptyLabel[resolvedLang] ?? emptyLabel.en} + {t('dynamic.emptyProducts', { lng: resolvedLang })}
)} @@ -450,6 +419,7 @@ function EditorialCarouselSection({ payload, lang }: { payload: Record- {[author && `${authorPrefix[resolvedLang] ?? authorPrefix.en} ${author}`, date].filter(Boolean).join(' / ')} + {[author && `${t('dynamic.authorBy', { lng: resolvedLang })} ${author}`, date].filter(Boolean).join(' / ')}
)} @@ -498,23 +460,16 @@ function HeroArticleSection({ payload, lang }: { payload: Record- {subtitle || copy.subtitle} + {subtitle || t('contactForm.subtitle', { lng: resolvedLang })}
{copy.successBody}
+{t('contactForm.successBody', { lng: resolvedLang })}