diff --git a/.agent/skills/ui-consistency/SKILL.md b/.agent/skills/ui-consistency/SKILL.md new file mode 100644 index 0000000..0560d13 --- /dev/null +++ b/.agent/skills/ui-consistency/SKILL.md @@ -0,0 +1,742 @@ +--- +name: UI 統一性規範 +description: 確保 koori-erp ERP 系統後台所有頁面的 UI 元件保持統一的樣式與行為 +--- + +# UI 統一性規範 + +## 概述 + +本 skill 提供 koori-erp ERP 系統的 UI 統一性規範,確保所有頁面使用一致的元件、樣式類別、圖標和佈局模式。 + +## 核心原則 + +1. **使用統一的 UI 組件庫**:優先使用 `@/Components/ui/` 中的元件 +2. **遵循既定的樣式類別**:使用 `app.css` 中定義的自定義按鈕類別 +3. **統一的圖標系統**:全面使用 `lucide-react` 圖標 +4. **一致的佈局模式**:表格、分頁、操作按鈕等保持相同結構 + +--- + +## 1. 按鈕規範 + +### 1.1 按鈕樣式類別 + +專案在 `resources/css/app.css` 中定義了統一的按鈕樣式類別,**必須**使用這些類別而非自定義樣式: + +#### Filled 按鈕(實心按鈕) + +```tsx +// 主要操作按鈕(綠色主題色) + + +// 成功操作 + + +// 資訊操作 + + +// 警告操作 + + +// 錯誤/刪除操作 + +``` + +#### Outlined 按鈕(邊框按鈕) + +```tsx +// 次要操作(主題色邊框) + + +// 成功樣式邊框 + + +// 資訊樣式邊框 + + +// 警告樣式邊框 + + +// 錯誤/刪除樣式邊框 + +``` + +#### Text 按鈕(文字按鈕) + +```tsx +// 文字按鈕 + +``` + +### 1.2 按鈕大小 + +使用 shadcn/ui Button 組件的標準尺寸: + +- `size="sm"`:小型按鈕(h-8),用於表格操作列 +- `size="default"`:預設按鈕(h-9),用於一般操作 +- `size="lg"`:大型按鈕(h-10),用於主要 CTA +- `size="icon"`:圖標按鈕(size-9),僅含圖標的正方形按鈕 + +### 1.3 常見操作按鈕模式 + +#### 新增按鈕(頁面頂部) + +```tsx + + + + + +``` + +#### 編輯按鈕(表格操作列) + +```tsx + + + + + +``` + +#### 刪除按鈕(表格操作列,帶確認對話框) + +```tsx + + + + + + + + 確認刪除 + + 確定要刪除「{item.name}」嗎?此操作無法復原。 + + + + 取消 + handleDelete(item.id)} + className="bg-red-600 hover:bg-red-700" + > + 刪除 + + + + + +``` + +--- + +## 2. 圖標規範 + +### 2.1 圖標庫 + +**統一使用 `lucide-react`**,不使用其他圖標庫(如 FontAwesome、Material Icons 等)。 + +### 2.2 圖標尺寸標準 + +- **小型圖標**:`h-3 w-3`(用於 Badge、小文字旁) +- **標準圖標**:`h-4 w-4`(用於按鈕、表格操作) +- **標題圖標**:`h-6 w-6`(用於頁面標題) + +### 2.3 常用操作圖標映射 + +| 操作 | 圖標組件 | 使用情境 | +|------|----------|----------| +| 新增 | `` | 新增按鈕 | +| 編輯 | `` | 編輯按鈕 | +| 刪除 | `` | 刪除按鈕 | +| 查看 | `` | 查看詳情 | +| 搜尋 | `` | 搜尋欄位 | +| 篩選 | `` | 篩選功能 | +| 下載 | `` | 下載/匯出 | +| 上傳 | `` | 上傳/匯入 | +| 設定 | `` | 設定功能 | +| 複製 | `` | 複製內容 | +| 郵件 | `` | Email 顯示 | +| 使用者 | ``, `` | 使用者管理 | +| 權限 | `` | 角色/權限 | +| 排序 | ``, ``, `` | 表格排序 | + +### 2.4 圖標使用範例 + +```tsx +import { Plus, Pencil, Trash2, Eye, Search } from 'lucide-react'; + +// 頁面標題 +

+ + 使用者管理 +

+ +// 按鈕內圖標 + + +// 純圖標按鈕(表格操作列) + +``` + +--- + +## 3. 表格規範 + +### 3.1 表格容器 + +使用統一的表格包裝樣式: + +```tsx +
+ + {/* 表格內容 */} +
+
+``` + +或使用更精緻的樣式(用於管理頁面): + +```tsx +
+ + {/* 表格內容 */} +
+
+``` + +### 3.2 表格標題列 + +```tsx + + + # + + + + 操作 + + +``` + +**關鍵要點**: +- 使用 `bg-gray-50` 背景色 +- 序號欄位固定寬度 `w-[50px]` 並置中 +- 可排序欄位使用 ` + + + + + {/* 刪除確認對話框 */} + + + + +``` + +--- + +## 4. 分頁規範 + +### 4.1 統一分頁元件 + +使用 `@/Components/shared/Pagination` 元件: + +```tsx +import Pagination from "@/Components/shared/Pagination"; + +// 在表格下方 +
+
+ 每頁顯示 + + +
+ +
+``` + +### 4.2 每頁筆數狀態管理 + +```tsx +const [perPage, setPerPage] = useState(filters.per_page || "10"); + +const handlePerPageChange = (value: string) => { + setPerPage(value); + router.get( + route('resource.index'), + { per_page: value }, + { preserveState: false, replace: true, preserveScroll: true } + ); +}; +``` + +--- + +## 5. Badge 與狀態顯示 + +### 5.1 基本 Badge + +使用 `@/Components/ui/badge`: + +```tsx +import { Badge } from "@/Components/ui/badge"; + +// Outline 樣式(最常用) + + {item.category?.name || '-'} + + +// 預設樣式(主題色背景) +啟用中 + +// 錯誤樣式 +停用 +``` + +### 5.2 角色顯示(特殊樣式) + +參考使用者管理的角色顯示模式: + +```tsx +
+ {user.roles.map(role => ( +
+
+ {role.name === 'super-admin' && } + + {role.display_name} + +
+ + {role.name} + +
+ ))} +
+``` + +--- + +## 6. 頁面佈局規範 + +### 6.1 標準頁面頭部 + +```tsx +
+
+

+ + 頁面標題 +

+

+ 頁面說明文字 +

+
+ + + + + +
+``` + +### 6.2 容器寬度 + +```tsx +
+ {/* 頁面內容 */} +
+``` + +--- + +## 7. 權限控制規範 + +### 7.1 使用 Can 元件 + +**所有**涉及權限的 UI 元素都必須使用 `` 元件包裹: + +```tsx +import { Can } from "@/Components/Permission/Can"; + + + {/* 新增按鈕 */} + + + + {/* 編輯按鈕 */} + + + + {/* 刪除按鈕 */} + +``` + +### 7.2 權限命名規範 + +遵循 `resource.action` 格式: + +- `resource.index`:查看列表 +- `resource.show`:查看詳情 +- `resource.create`:新增 +- `resource.edit`:編輯 +- `resource.delete`:刪除 + +--- + +## 8. 通知訊息規範 + +### 8.1 使用 Toast 通知 + +使用 `sonner` 的 `toast` 進行通知: + +```tsx +import { toast } from 'sonner'; + +// 成功訊息 +toast.success('操作成功'); + +// 錯誤訊息 +toast.error('操作失敗'); + +// 資訊訊息 +toast.info('提示訊息'); + +// 警告訊息 +toast.warning('警告訊息'); +``` + +### 8.2 常見操作的 Toast 訊息 + +```tsx +// 新增成功 +router.post(route('resource.store'), data, { + onSuccess: () => toast.success('新增成功'), + onError: () => toast.error('新增失敗,請檢查輸入內容'), +}); + +// 更新成功 +router.put(route('resource.update', id), data, { + onSuccess: () => toast.success('更新成功'), + onError: () => toast.error('更新失敗'), +}); + +// 刪除成功 +router.delete(route('resource.destroy', id), { + onSuccess: () => toast.success('已刪除'), + onError: () => toast.error('刪除失敗,請檢查權限'), +}); +``` + +--- + +## 9. 顏色系統 + +### 9.1 主題色 + +參考 `resources/css/app.css` 中的色彩定義: + +```css +--primary-main: #01ab83; /* 主題綠色 */ +--primary-dark: #018a6a; /* 深綠色 */ +--primary-light: #33bc9a; /* 淺綠色 */ +--primary-lightest: #e6f7f3; /* 最淺綠色背景 */ + +--grey-0: #1a1a1a; /* 深黑色文字 */ +--grey-1: #4a4a4a; /* 深灰色文字 */ +--grey-2: #6b6b6b; /* 中灰色文字 */ +--grey-3: #9e9e9e; /* 淺灰色文字 */ +--grey-4: #e0e0e0; /* 邊框灰色 */ +--grey-5: #fff; /* 白色 */ +``` + +### 9.2 狀態色 + +```css +--other-success: #01ab83; /* 成功(同主題色)*/ +--other-error: #dc2626; /* 錯誤紅色 */ +--other-warning: #f59e0b; /* 警告橙色 */ +--other-info: #3b82f6; /* 資訊藍色 */ +``` + +--- + +## 10. 檢查清單 + +在開發或審查頁面時,請確認以下項目: + +### ✅ 按鈕 +- [ ] 使用 `button-filled-*` 或 `button-outlined-*` 類別 +- [ ] 主要操作使用 `button-filled-primary` +- [ ] 編輯操作使用 `button-outlined-primary` +- [ ] 刪除操作使用 `button-outlined-error` +- [ ] 按鈕尺寸正確(sm/default/lg) +- [ ] 包含適當的圖標(左側或單一圖標) + +### ✅ 圖標 +- [ ] 全部使用 `lucide-react` +- [ ] 尺寸正確(h-3/h-4/h-6 w-3/w-4/w-6) +- [ ] 顏色與上下文一致 +- [ ] 有明確的語義(編輯=Pencil、刪除=Trash2 等) + +### ✅ 表格 +- [ ] 使用 `@/Components/ui/table` 元件 +- [ ] 有 `bg-white rounded-lg shadow-sm border` 容器 +- [ ] 標題列有 `bg-gray-50` 背景 +- [ ] 序號欄固定寬度並置中 +- [ ] 操作欄使用 `flex justify-center gap-2` +- [ ] 空狀態訊息置中顯示 +- [ ] 可排序欄位有排序圖標 + +### ✅ 分頁 +- [ ] 使用 `@/Components/shared/Pagination` +- [ ] 有每頁筆數選擇器(10/20/50/100) +- [ ] 佈局為 `flex justify-between` + +### ✅ 權限 +- [ ] 所有操作按鈕都用 `` 包裹 +- [ ] 權限命名符合 `resource.action` 格式 + +### ✅ 通知 +- [ ] 使用 `toast` 提供操作反饋 +- [ ] 成功/錯誤訊息明確 + +### ✅ 整體 +- [ ] 頁面有標準頭部(標題 + 圖標 + 說明 + 新增按鈕) +- [ ] 容器寬度使用 `max-w-7xl` +- [ ] 色彩使用符合主題 + +--- + +## 11. 常見錯誤與修正 + +### ❌ 錯誤:自定義按鈕樣式 + +```tsx +// 錯誤 + +``` + +```tsx +// 正確 + +``` + +### ❌ 錯誤:混用圖標庫 + +```tsx +// 錯誤 +import { FaEdit } from 'react-icons/fa'; // ❌ 不使用 react-icons + + +``` + +```tsx +// 正確 +import { Pencil } from 'lucide-react'; // ✅ 使用 lucide-react + + +``` + +### ❌ 錯誤:操作欄未置中 + +```tsx +// 錯誤 + + + + +``` + +```tsx +// 正確 + +
+ + +
+
+``` + +### ❌ 錯誤:缺少權限控制 + +```tsx +// 錯誤 + +``` + +```tsx +// 正確 + + + +``` + +--- + +## 12. 實際範例 + +參考以下頁面作為標準實作: + +- **使用者管理**:`resources/js/Pages/Admin/User/Index.tsx` +- **產品管理**:`resources/js/Pages/Product/Index.tsx` +- **產品表格**:`resources/js/Components/Product/ProductTable.tsx` + +這些頁面展示了完整的 UI 統一性實踐,包括按鈕、圖標、表格、分頁、權限控制等所有元素。 + +--- + +## 總結 + +遵循本規範可確保: + +1. ✅ **視覺一致性**:所有頁面看起來像同一個系統 +2. ✅ **維護效率**:使用統一組件,修改一處即可影響全局 +3. ✅ **開發速度**:有明確的模式可循,減少決策時間 +4. ✅ **使用者體驗**:一致的互動模式降低學習成本 + +當你在開發或審查 koori-erp 的 UI 時,請務必參考此規範,確保每個元件都符合既定的標準。 diff --git a/resources/css/app.css b/resources/css/app.css index e69985f..51160bb 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -262,7 +262,12 @@ } .button-outlined-error { - @apply border-2 text-[var(--grey-0)] bg-transparent transition-colors; + @apply border-2 text-[var(--grey-0)] bg-transparent transition-colors disabled:border-[var(--grey-4)] disabled:text-[var(--grey-3)] disabled:cursor-not-allowed; + border-color: var(--other-error); +} + +.button-outlined-error:hover { + @apply bg-red-50 text-[var(--grey-0)]; border-color: var(--other-error); } diff --git a/resources/js/Components/Warehouse/WarehouseDialog.tsx b/resources/js/Components/Warehouse/WarehouseDialog.tsx index a2ae723..79a1b83 100644 --- a/resources/js/Components/Warehouse/WarehouseDialog.tsx +++ b/resources/js/Components/Warehouse/WarehouseDialog.tsx @@ -191,9 +191,9 @@ export default function WarehouseDialog({ type="button" onClick={() => setShowDeleteDialog(true)} variant="outline" - className="group mr-auto border-2 border-red-600 text-red-600 hover:bg-red-600 hover:text-white" + className="mr-auto button-outlined-error" > - + 刪除倉庫 )} diff --git a/resources/js/Pages/Admin/Role/Index.tsx b/resources/js/Pages/Admin/Role/Index.tsx index 743b850..edc755f 100644 --- a/resources/js/Pages/Admin/Role/Index.tsx +++ b/resources/js/Pages/Admin/Role/Index.tsx @@ -3,6 +3,7 @@ import { Head, Link, router } from '@inertiajs/react'; import { cn } from "@/lib/utils"; import { Shield, Plus, Pencil, Trash2, Users } from 'lucide-react'; import { Button } from '@/Components/ui/button'; +import { Badge } from '@/Components/ui/badge'; import { Table, TableBody, @@ -112,9 +113,9 @@ export default function RoleIndex({ roles }: Props) { {role.name} - + {role.permissions_count} 項權限 - +