跳至主要内容

主題系統

AppFuse Web 使用 Tailwind CSS 4 + DaisyUI 5 建構主題系統,支援 30+ 預設主題和自訂主題。

技術架構

預設主題

AppFuse Web 內建 Fusion 主題作為預設,另支援多種 DaisyUI 主題:

主題說明適用場景
fusionAppFuse 品牌主題(預設)企業應用
light明亮主題一般用途
dark深色主題低光環境
garden花園主題花店/園藝
cupcake柔和粉彩活潑風格
valentine情人節主題特殊活動
pastel粉彩主題柔和風格

Fusion 主題配色

Fusion 主題使用 OKLch 色彩空間定義:

/* 主要顏色 */
--color-primary: oklch(50% 0.035 230); /* Primary: 藍灰色 #546E7A */
--color-primary-content: oklch(100% 0 0);
--color-secondary: oklch(60% 0.20 35); /* Secondary: 深橘色 #E64A19 */
--color-secondary-content: oklch(100% 0 0);
--color-accent: oklch(48% 0.13 245); /* Accent: 藍色 #106BA3 */
--color-accent-content: oklch(100% 0 0);

/* 中性顏色 */
--color-neutral: oklch(50% 0.035 230); /* Neutral: 藍灰 #546E7A */
--color-neutral-content: oklch(100% 0 0);

/* 基礎顏色 */
--color-base-100: oklch(99% 0.005 230); /* 極淺藍灰背景 */
--color-base-200: oklch(97% 0.008 230); /* 淺藍灰背景 */
--color-base-300: oklch(94% 0.012 230); /* 藍灰邊框/分隔 */
--color-base-content: oklch(27% 0.025 230); /* 文字 #1C313A */

/* 語意顏色 */
--color-info: oklch(60% 0.12 200); /* Info: 青色 #0097A7 */
--color-info-content: oklch(100% 0 0);
--color-success: oklch(45% 0.10 170); /* Success: 深青綠 #00695C */
--color-success-content: oklch(100% 0 0);
--color-warning: oklch(71.5% 0.165 60); /* Warning: 橙色 #E68523 */
--color-warning-content: oklch(100% 0 0);
--color-error: oklch(52% 0.19 27); /* Error: 紅色 #C23030 */
--color-error-content: oklch(100% 0 0);

使用語意化顏色

文字顏色

// ✅ 正確:使用語意化顏色
<p className="text-base-content">主要文字</p>
<p className="text-base-content/60">次要文字</p>
<p className="text-primary">強調文字</p>
<p className="text-error">錯誤訊息</p>

// ❌ 錯誤:硬編碼顏色
<p className="text-gray-900">主要文字</p>
<p className="text-red-500">錯誤訊息</p>

背景顏色

// ✅ 正確
<div className="bg-base-100">主要背景</div>
<div className="bg-base-200">次要背景</div>
<div className="bg-primary text-primary-content">強調區塊</div>

// ❌ 錯誤
<div className="bg-white">主要背景</div>
<div className="bg-gray-100">次要背景</div>

邊框顏色

// ✅ 正確
<div className="border border-base-300">卡片</div>
<input className="border-primary focus:border-primary" />

// ❌ 錯誤
<div className="border border-gray-200">卡片</div>

切換主題

使用 data-theme 屬性

// 在 HTML 根元素設定主題
<html data-theme="fusion">
...
</html>

// 動態切換
function ThemeSwitcher() {
const setTheme = (theme: string) => {
document.documentElement.setAttribute('data-theme', theme);
};

return (
<select onChange={(e) => setTheme(e.target.value)}>
<option value="fusion">Fusion</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
);
}

持久化主題選擇

參考實作(app-office)使用 localStorage 持久化主題選擇:

const THEME_KEY = 'selected-theme';

// 初始化:讀取已儲存的主題
const savedTheme = localStorage.getItem(THEME_KEY) || 'fusion';
document.documentElement.setAttribute('data-theme', savedTheme);

// 切換並儲存主題
function setTheme(theme: string) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem(THEME_KEY, theme);
}

若需使用 Cookie 持久化(例如 SSR 場景),可使用框架的 cookie 工具:

import { cookie } from '@appfuse/appfuse-web/utils';

// 讀取已儲存的主題
const savedTheme = cookie.get('theme', 'fusion');
document.documentElement.setAttribute('data-theme', savedTheme);

// 儲存主題選擇
function setTheme(theme: string) {
document.documentElement.setAttribute('data-theme', theme);
cookie.set('theme', theme, { expiredInDays: 365 });
}

自訂主題

在 tailwind.css 定義新主題

@plugin "daisyui" {
themes: fusion --default, light, dark, my-custom-theme;
}

@plugin "daisyui/theme" {
name: "my-custom-theme";
default: false;
color-scheme: light;

/* 主要顏色 */
--color-primary: oklch(55% 0.2 260);
--color-primary-content: oklch(98% 0 0);
--color-secondary: oklch(60% 0.15 30);
--color-secondary-content: oklch(98% 0 0);
--color-accent: oklch(65% 0.2 150);
--color-accent-content: oklch(98% 0 0);

/* 中性顏色 */
--color-neutral: oklch(50% 0.03 260);
--color-neutral-content: oklch(98% 0 0);

/* 基礎顏色 */
--color-base-100: oklch(98% 0.01 260);
--color-base-200: oklch(94% 0.02 260);
--color-base-300: oklch(88% 0.03 260);
--color-base-content: oklch(25% 0.05 260);

/* 語意顏色 */
--color-info: oklch(70% 0.15 220);
--color-info-content: oklch(98% 0 0);
--color-success: oklch(65% 0.2 145);
--color-success-content: oklch(98% 0 0);
--color-warning: oklch(75% 0.15 85);
--color-warning-content: oklch(98% 0 0);
--color-error: oklch(60% 0.25 25);
--color-error-content: oklch(98% 0 0);

/* 設計參數 */
--radius-box: 0.5rem;
--radius-field: 0.5rem;
--radius-selector: 0.375rem;
--depth: 1;
--noise: 0;
--border: 1px;
--animation-btn: 0.25s;
--animation-input: 0.2s;
--btn-focus-scale: 0.95;
}

設計規範

圓角

元素圓角值CSS 變數
卡片/容器0.5rem--radius-box
輸入框/按鈕0.5rem--radius-field
下拉選單/選項0.375rem--radius-selector

動畫時間

元素時間CSS 變數
按鈕0.25s--animation-btn
輸入框0.2s--animation-input

字型策略

優先使用系統字型,確保最佳效能:

font-family:
/* 西文字型 */
-apple-system, BlinkMacSystemFont,
/* Windows */
"Segoe UI",
/* Android */
Roboto,
/* 中文字型 */
"PingFang TC",
"Noto Sans TC",
"Microsoft JhengHei",
/* 備用 */
sans-serif,
/* Emoji */
"Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";

元件樣式覆寫

全域覆寫

tailwind.css@layer daisyui 中覆寫:

@layer daisyui {
/* 卡片標題不使用粗體 */
.card-title {
@apply font-normal;
}

/* 表頭背景較深 */
.table thead {
@apply bg-base-200;
}

/* Checkbox 小圓角 */
.checkbox {
@apply rounded;
border-width: 2px;
}
}

元件級覆寫

使用 cn() 工具合併樣式:

import { cn } from '@appfuse/appfuse-web/utils';

function CustomButton({ className, ...props }) {
return (
<button
className={cn(
"btn btn-primary",
"rounded-lg shadow-md", // 覆寫樣式
className
)}
{...props}
/>
);
}

深色模式

自動偵測系統偏好

// 偵測系統深色模式偏好
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const theme = prefersDark ? 'dark' : 'fusion';
document.documentElement.setAttribute('data-theme', theme);

// 監聽系統偏好變更
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
const theme = e.matches ? 'dark' : 'fusion';
document.documentElement.setAttribute('data-theme', theme);
});

最佳實踐

  1. 永遠使用語意化顏色 - 不要硬編碼 gray-500red-600
  2. 測試多主題 - 確保元件在不同主題下都正常顯示
  3. 保持對比度 - 文字與背景對比度至少 4.5:1(WCAG AA)
  4. 使用 CSS 變數 - 自訂樣式時優先使用 DaisyUI CSS 變數

延伸閱讀

本文檔說明「如何切換與自訂主題」。如需了解設計規範,請參閱設計指南

下一步