37 KiB
37 KiB
DramaLing UI/UX 設計規範
設計理念
DramaLing詞彙學習系統採用清新、直觀、專注學習的設計理念,致力於創造無障礙且引人入勝的學習體驗。設計強調簡潔性、一致性和互動性,讓用戶能夠專注於學習內容本身。
1. 視覺設計系統
1.1 顏色系統
主要顏色調色板
/* 主色調 - 藍色系統 */
--primary-default: #3B82F6; /* 主要按鈕、鏈接 */
--primary-hover: #2563EB; /* 懸停狀態 */
--primary-light: #EFF6FF; /* 淺色背景 */
/* 語義顏色 */
--success: #10B981; /* 正確答案、成功狀態 */
--warning: #F59E0B; /* 警告、提示 */
--error: #EF4444; /* 錯誤、失敗狀態 */
--info: #8B5CF6; /* 資訊提示 */
/* 中性色系 */
--gray-50: #F9FAFB; /* 最淺背景 */
--gray-100: #F3F4F6; /* 卡片背景 */
--gray-200: #E5E7EB; /* 邊框、分隔線 */
--gray-300: #D1D5DB; /* 次要邊框 */
--gray-500: #6B7280; /* 次要文字 */
--gray-600: #4B5563; /* 主要文字 */
--gray-700: #374151; /* 標題文字 */
--gray-900: #111827; /* 強調文字 */
顏色使用規範
- 主色調藍色: 用於主要動作按鈕、導航高亮、進度指示
- 成功綠色: 正確答案回饋、完成狀態、積極反饋
- 錯誤紅色: 錯誤答案回饋、警告信息、負面反饋
- 警告黃色: 提示信息、注意事項、中性反饋
- 中性灰色: 文字內容、背景、邊框等
1.2 字體系統
字體家族
font-family: 'Inter', 'Noto Sans TC', 'system-ui', 'sans-serif';
字體尺寸階層
/* 標題層級 */
.text-3xl { font-size: 1.875rem; } /* 主頁面標題 */
.text-2xl { font-size: 1.5rem; } /* 區塊標題 */
.text-xl { font-size: 1.25rem; } /* 子標題 */
.text-lg { font-size: 1.125rem; } /* 大號正文 */
/* 正文層級 */
.text-base { font-size: 1rem; } /* 標準正文 */
.text-sm { font-size: 0.875rem; } /* 小號文字 */
.text-xs { font-size: 0.75rem; } /* 標籤、說明文字 */
字重規範
.font-bold { font-weight: 700; } /* 標題、重點強調 */
.font-semibold { font-weight: 600; } /* 副標題、按鈕文字 */
.font-medium { font-weight: 500; } /* 導航、標籤 */
.font-normal { font-weight: 400; } /* 正文內容 */
1.3 間距系統
間距單位
/* 基礎間距單位:4px */
.space-y-1 { margin: 4px 0; } /* 緊密間距 */
.space-y-2 { margin: 8px 0; } /* 小間距 */
.space-y-3 { margin: 12px 0; } /* 標準間距 */
.space-y-4 { margin: 16px 0; } /* 中等間距 */
.space-y-6 { margin: 24px 0; } /* 大間距 */
.space-y-8 { margin: 32px 0; } /* 區塊間距 */
/* 內邊距 */
.p-2 { padding: 8px; } /* 小內距 */
.p-3 { padding: 12px; } /* 標準內距 */
.p-4 { padding: 16px; } /* 中等內距 */
.p-6 { padding: 24px; } /* 大內距 */
.p-8 { padding: 32px; } /* 大型容器內距 */
1.4 圓角系統
.rounded-md { border-radius: 6px; } /* 小元素:按鈕、輸入框 */
.rounded-lg { border-radius: 8px; } /* 標準元素:卡片、容器 */
.rounded-xl { border-radius: 12px; } /* 大元素:主要卡片 */
.rounded-full { border-radius: 50%; } /* 圓形:頭像、標籤 */
2. 組件設計規範
2.1 按鈕設計系統
主要按鈕 (Primary Button)
<button className="
px-6 py-3
bg-primary text-white
rounded-lg
hover:bg-primary-hover
transition-colors
font-medium
disabled:opacity-50
disabled:cursor-not-allowed
">
主要動作
</button>
次要按鈕 (Secondary Button)
<button className="
px-6 py-3
bg-gray-200 text-gray-700
rounded-lg
hover:bg-gray-300
transition-colors
font-medium
">
次要動作
</button>
危險按鈕 (Danger Button)
<button className="
px-4 py-2
bg-red-600 text-white
rounded-lg
hover:bg-red-700
transition-colors
font-medium
">
刪除/危險動作
</button>
模式切換按鈕 (Mode Toggle)
<button className={`
px-3 py-2
rounded-md
transition-colors
${isActive
? 'bg-primary text-white'
: 'text-gray-600 hover:text-gray-900'
}
`}>
模式名稱
</button>
2.2 卡片設計系統
主要內容卡片
<div className="
bg-white
rounded-xl
shadow-lg
p-8
hover:shadow-xl
transition-shadow
">
{/* 卡片內容 */}
</div>
資訊展示卡片
<div className="
bg-gray-50
rounded-lg
p-4
border border-gray-200
">
{/* 資訊內容 */}
</div>
狀態回饋卡片
{/* 成功狀態 */}
<div className="
bg-green-50
border border-green-200
rounded-lg
p-6
">
{/* 成功內容 */}
</div>
{/* 錯誤狀態 */}
<div className="
bg-red-50
border border-red-200
rounded-lg
p-6
">
{/* 錯誤內容 */}
</div>
{/* 警告狀態 */}
<div className="
bg-yellow-50
border border-yellow-200
rounded-lg
p-6
">
{/* 警告內容 */}
</div>
2.3 輸入組件設計
文字輸入框
<input className="
w-full
px-4 py-3
border border-gray-300
rounded-lg
focus:ring-2 focus:ring-primary focus:border-transparent
outline-none
placeholder-gray-400
" />
下拉選單
<select className="
w-full
p-2
border border-gray-300
rounded-md
focus:ring-blue-500 focus:border-blue-500
bg-white
">
<option>選項</option>
</select>
複選框/單選框
<input type="checkbox" className="
w-4 h-4
text-blue-600
bg-gray-100
border-gray-300
rounded
focus:ring-blue-500
" />
2.4 標籤和徽章系統
難度等級標籤
{/* A1-A2 基礎等級 */}
<span className="
text-xs px-2 py-1
rounded-full
bg-green-100 text-green-700
">
CEFR A2
</span>
{/* B1-B2 中級等級 */}
<span className="
text-xs px-2 py-1
rounded-full
bg-yellow-100 text-yellow-700
">
CEFR B1
</span>
{/* C1-C2 高級等級 */}
<span className="
text-xs px-2 py-1
rounded-full
bg-red-100 text-red-700
">
CEFR C1
</span>
詞性標籤
<span className="
text-sm
bg-gray-100 text-gray-600
px-2 py-1
rounded
">
noun
</span>
同義詞標籤
<span className="
text-xs
bg-blue-100 text-blue-700
px-2 py-1
rounded-full
">
synonym
</span>
3. 交互設計模式
3.1 學習模式設計
模式切換器設計原則
- 視覺清晰: 當前選中模式使用主色調高亮
- 狀態一致: 所有模式按鈕使用相同的設計語言
- 響應迅速: 切換模式時即時更新UI狀態
- 分組合理: 相關功能模式在視覺上聚集
{/* 學習模式切換器 */}
<div className="bg-white rounded-lg shadow-sm p-1 inline-flex flex-wrap">
{modes.map(mode => (
<button
key={mode.id}
onClick={() => setMode(mode.id)}
className={`
px-3 py-2 rounded-md transition-colors
${currentMode === mode.id
? 'bg-primary text-white'
: 'text-gray-600 hover:text-gray-900'
}
`}
>
{mode.label}
</button>
))}
</div>
3.2 進度指示設計
學習進度條
<div className="mb-8">
{/* 進度資訊 */}
<div className="flex justify-between items-center mb-2">
<span className="text-sm text-gray-600">進度</span>
<div className="flex items-center gap-4">
<span className="text-sm text-gray-600">
{currentIndex + 1} / {total}
</span>
<div className="text-sm">
<span className="text-green-600 font-semibold">{correct}</span>
<span className="text-gray-500">/</span>
<span className="text-gray-600">{total}</span>
{total > 0 && (
<span className="text-blue-600 ml-2">
({Math.round((correct / total) * 100)}%)
</span>
)}
</div>
</div>
</div>
{/* 進度條 */}
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-primary h-2 rounded-full transition-all"
style={{ width: `${((currentIndex + 1) / total) * 100}%` }}
/>
</div>
</div>
3.3 狀態回饋設計
答案回饋模式
{/* 正確回饋 */}
<div className="
p-6 rounded-lg
bg-green-50 border border-green-200
">
<p className="font-semibold text-left text-xl mb-4 text-green-700">
正確!
</p>
{/* 回饋內容 */}
</div>
{/* 錯誤回饋 */}
<div className="
p-6 rounded-lg
bg-red-50 border border-red-200
">
<p className="font-semibold text-left text-xl mb-4 text-red-700">
錯誤!
</p>
<div className="mb-4">
<p className="text-gray-700 text-left">
正確答案是:<strong className="text-lg">{correctAnswer}</strong>
</p>
</div>
</div>
載入狀態設計
{/* 按鈕載入狀態 */}
<button disabled className="
flex items-center justify-center gap-2
bg-primary text-white
px-4 py-2 rounded-lg
opacity-50 cursor-not-allowed
">
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
<span>載入中...</span>
</button>
{/* 頁面載入狀態 */}
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center">
<div className="text-gray-500 text-lg">載入中...</div>
</div>
3.4 互動式元素設計
點擊式詞彙分析
{/* 高價值詞彙 - 綠色邊框 + 星星 */}
<span className="
cursor-pointer transition-all duration-200 rounded relative
mx-0.5 px-1 py-0.5
bg-green-100 border-2 border-green-400
hover:bg-green-200 hover:shadow-sm
transform hover:-translate-y-0.5
">
{word}
<span className="absolute -top-1 -right-1 text-xs">⭐</span>
</span>
{/* 高價值片語 - 黃色邊框 + 星星 */}
<span className="
cursor-pointer transition-all duration-200 rounded relative
mx-0.5 px-1 py-0.5
bg-yellow-100 border-2 border-yellow-400
hover:bg-yellow-200 hover:shadow-sm
transform hover:-translate-y-0.5
">
{phrase}
<span className="absolute -top-1 -right-1 text-xs">⭐</span>
</span>
{/* 普通詞彙 - 藍色邊框 */}
<span className="
cursor-pointer transition-all duration-200 rounded
mx-0.5 px-1 py-0.5
bg-blue-100 border-2 border-blue-300
hover:bg-blue-200 hover:shadow-sm
">
{word}
</span>
詞彙詳情彈窗
<div className="
fixed z-20
bg-white border border-gray-300
rounded-lg shadow-lg
p-4 w-80 max-w-sm
" style={{
left: `${position.x}px`,
top: `${position.y}px`,
transform: 'translate(-50%, -100%)'
}}>
{/* 標題區 */}
<div className="flex items-center justify-between mb-3">
<h3 className="text-lg font-bold text-gray-900">{word}</h3>
<button className="text-gray-400 hover:text-gray-600">✕</button>
</div>
{/* 高價值標記 */}
{isHighValue && (
<div className="bg-green-50 border border-green-200 rounded-lg p-3 mb-3">
<div className="flex items-center gap-2">
<div className="text-green-600 text-lg">🎯</div>
<div className="text-sm font-medium text-green-800">重點學習詞彙</div>
</div>
</div>
)}
{/* 詞彙資訊 */}
<div className="space-y-3">
{/* 詞性和發音 */}
<div className="flex items-center gap-4">
<span className="text-sm bg-gray-100 px-2 py-1 rounded">
{partOfSpeech}
</span>
<span className="text-sm text-gray-600">{pronunciation}</span>
<AudioPlayer text={word} />
</div>
{/* 翻譯 */}
<div>
<div className="text-sm font-medium text-gray-700">翻譯</div>
<div className="text-base text-gray-900">{translation}</div>
</div>
{/* 定義 */}
<div>
<div className="text-sm font-medium text-gray-700">定義</div>
<div className="text-sm text-gray-600">{definition}</div>
</div>
{/* 保存按鈕 */}
<div className="pt-3 border-t border-gray-200">
<button className="
w-full
bg-blue-600 text-white
py-2 px-4
rounded-lg
text-sm font-medium
hover:bg-blue-700
transition-colors
flex items-center justify-center gap-2
">
<span>💾</span>
<span>保存到詞卡</span>
</button>
</div>
</div>
</div>
2.2 學習卡片設計
翻卡記憶卡片
{/* 卡片容器 */}
<div className="card-container" style={{ height: `${cardHeight}px` }}>
<div className={`card ${isFlipped ? 'flipped' : ''}`}>
{/* 正面 */}
<div className="card-front">
<div className="
bg-white rounded-xl shadow-lg
cursor-pointer hover:shadow-xl transition-shadow
p-8
">
{/* 標題區 */}
<div className="flex justify-between items-start mb-6">
<h2 className="text-2xl font-bold text-gray-900">翻卡記憶</h2>
<span className="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">
{difficulty}
</span>
</div>
{/* 單字展示 */}
<div className="flex-1 flex items-center justify-center mt-6">
<div className="bg-gray-50 rounded-lg p-8 w-full text-center">
<h3 className="text-4xl font-bold text-gray-900 mb-6">{word}</h3>
<div className="flex items-center justify-center gap-3">
<span className="text-lg text-gray-500">{pronunciation}</span>
<AudioPlayer text={word} />
</div>
</div>
</div>
</div>
</div>
{/* 背面 */}
<div className="card-back">
<div className="bg-white rounded-xl shadow-lg p-6">
<div className="space-y-4">
{/* 定義區塊 */}
<div className="bg-gray-50 rounded-lg p-4">
<h3 className="font-semibold text-gray-900 mb-2 text-left">定義</h3>
<p className="text-gray-700 text-left">{definition}</p>
</div>
{/* 例句區塊 */}
<div className="bg-gray-50 rounded-lg p-4">
<h3 className="font-semibold text-gray-900 mb-2 text-left">例句</h3>
<div className="relative">
<p className="text-gray-700 italic mb-2 text-left pr-12">"{example}"</p>
<div className="absolute bottom-0 right-0">
<AudioPlayer text={example} />
</div>
</div>
<p className="text-gray-600 text-sm text-left">"{exampleTranslation}"</p>
</div>
{/* 同義詞區塊 */}
<div className="bg-gray-50 rounded-lg p-4">
<h3 className="font-semibold text-gray-900 mb-2 text-left">同義詞</h3>
<div className="flex flex-wrap gap-2">
{synonyms.map((synonym, index) => (
<span key={index} className="
bg-white text-gray-700
px-3 py-1
rounded-full text-sm
border border-gray-200
">
{synonym}
</span>
))}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
3D翻卡動畫CSS
.card-container {
perspective: 1000px;
transition: height 0.3s ease;
overflow: visible;
position: relative;
}
.card {
position: relative;
width: 100%;
height: 100%;
text-align: center;
transition: transform 0.6s ease;
transform-style: preserve-3d;
}
.card.flipped {
transform: rotateY(180deg);
}
.card-front, .card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
display: flex;
align-items: stretch;
justify-content: center;
top: 0;
left: 0;
}
.card-back {
transform: rotateY(180deg);
}
3.3 測驗模式設計
選擇題設計
<div className="space-y-3 mb-6">
{options.map((option, idx) => (
<button
key={idx}
onClick={() => handleAnswer(option)}
disabled={showResult}
className={`
w-full p-4 text-left
rounded-lg border-2 transition-all
${showResult
? option === correctAnswer
? 'border-green-500 bg-green-50 text-green-700'
: option === selectedAnswer
? 'border-red-500 bg-red-50 text-red-700'
: 'border-gray-200 bg-gray-50 text-gray-500'
: 'border-gray-200 hover:border-blue-300 hover:bg-blue-50'
}
`}
>
{option}
</button>
))}
</div>
填空題設計
{/* 句子中的填空輸入 */}
<input
type="text"
value={answer}
onChange={(e) => setAnswer(e.target.value)}
disabled={showResult}
className={`
inline-block px-2 py-1 text-center
bg-transparent focus:outline-none
disabled:bg-gray-100
${answer
? 'border-b-2 border-blue-500'
: 'border-b-2 border-dashed border-gray-400 focus:border-blue-400 focus:border-solid'
}
`}
style={{
width: `${Math.max(100, Math.max(targetWord.length * 12, answer.length * 12 + 20))}px`
}}
/>
3.4 例句重組設計
重組區域設計
{/* 答案區域 */}
<div className="
relative min-h-[120px]
bg-gray-50 rounded-lg p-4
border-2 border-dashed border-gray-300
">
{arrangedWords.length === 0 ? (
<div className="absolute inset-0 flex items-center justify-center text-gray-400 text-lg">
答案區
</div>
) : (
<div className="flex flex-wrap gap-2">
{arrangedWords.map((word, index) => (
<div
key={index}
className="
inline-flex items-center
bg-blue-100 text-blue-800
px-3 py-2 rounded-full
text-lg font-medium
cursor-pointer hover:bg-blue-200
transition-colors
"
onClick={() => removeWord(word)}
>
{word}
<span className="ml-2 text-blue-600 hover:text-blue-800">×</span>
</div>
))}
</div>
)}
</div>
{/* 可用單字區域 */}
<div className="bg-white border border-gray-200 rounded-lg p-4 min-h-[80px]">
{shuffledWords.length === 0 ? (
<div className="text-center text-gray-400">所有單字都已使用</div>
) : (
<div className="flex flex-wrap gap-2">
{shuffledWords.map((word, index) => (
<button
key={index}
onClick={() => selectWord(word)}
className="
bg-gray-100 text-gray-800
px-3 py-2 rounded-full
text-lg font-medium
cursor-pointer hover:bg-gray-200
active:bg-gray-300
transition-colors select-none
"
>
{word}
</button>
))}
</div>
)}
</div>
4. 布局設計規範
4.1 頁面布局模式
學習頁面布局
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
{/* 導航欄 */}
<Navigation showExitLearning={true} onExitLearning={handleExit} />
{/* 主要內容區 */}
<div className="max-w-4xl mx-auto px-4 py-8">
{/* 進度條 */}
<ProgressBar />
{/* 模式切換器 */}
<ModeSelector />
{/* 學習內容 */}
<LearningContent />
{/* 導航按鈕 */}
<NavigationButtons />
</div>
</div>
內容頁面布局
<div className="min-h-screen bg-gray-50">
<Navigation />
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* 頁面標題 */}
<h1 className="text-3xl font-bold mb-8">頁面標題</h1>
{/* 內容區塊 */}
<div className="max-w-4xl mx-auto space-y-6">
{/* 內容卡片 */}
</div>
</div>
</div>
4.2 響應式設計
斷點系統
/* 小屏幕 (手機) */
sm: '640px'
/* 中等屏幕 (平板) */
md: '768px'
/* 大屏幕 (桌面) */
lg: '1024px'
/* 超大屏幕 */
xl: '1280px'
響應式組件範例
{/* 網格布局響應式 */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* 項目 */}
</div>
{/* 導航響應式 */}
<div className="hidden md:flex space-x-6">
{/* 桌面版導航 */}
</div>
<div className="md:hidden">
{/* 手機版導航 */}
</div>
{/* 文字大小響應式 */}
<h1 className="text-2xl md:text-3xl font-bold">標題</h1>
5. 互動設計原則
5.1 微互動設計
懸停效果
{/* 卡片懸停 */}
<div className="
bg-white rounded-xl shadow-lg
hover:shadow-xl
transition-shadow duration-300
">
{/* 內容 */}
</div>
{/* 按鈕懸停 */}
<button className="
bg-primary text-white
hover:bg-primary-hover
transform hover:scale-105
transition-all duration-200
">
按鈕
</button>
{/* 詞彙懸停 */}
<span className="
cursor-pointer
hover:bg-blue-200 hover:shadow-sm
transform hover:-translate-y-0.5
transition-all duration-200
">
詞彙
</span>
動畫效果
{/* 載入動畫 */}
<div className="animate-spin w-4 h-4 border-2 border-white border-t-transparent rounded-full" />
{/* 淡入動畫 */}
<div className="animate-fadeIn opacity-0 animate-fade-in">
{/* 內容 */}
</div>
{/* 滑入動畫 */}
<div className="transform translate-x-full animate-slide-in">
{/* 內容 */}
</div>
5.2 狀態管理原則
視覺狀態指示
{/* 禁用狀態 */}
<button className="
opacity-50 cursor-not-allowed
bg-gray-300 text-gray-500
">
禁用按鈕
</button>
{/* 選中狀態 */}
<div className="
border-2
${isSelected
? 'border-blue-500 bg-blue-50'
: 'border-gray-200'
}
">
{/* 內容 */}
</div>
{/* 錯誤狀態 */}
<div className="
border-red-400 bg-red-50
text-red-700
">
{/* 錯誤內容 */}
</div>
5.3 回饋設計模式
即時回饋
{/* 成功提示 */}
<div className="
fixed bottom-4 right-4
bg-green-600 text-white
px-4 py-3 rounded-lg shadow-lg
animate-slide-up
">
✅ 操作成功
</div>
{/* 錯誤提示 */}
<div className="
fixed bottom-4 right-4
bg-red-600 text-white
px-4 py-3 rounded-lg shadow-lg
animate-slide-up
">
❌ 操作失敗
</div>
6. 特殊組件設計
6.1 模態對話框設計
標準模態框
{/* 遮罩層 */}
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
{/* 模態內容 */}
<div className="bg-white rounded-lg p-6 max-w-md w-full mx-4">
{/* 標題 */}
<h3 className="text-lg font-semibold mb-4">對話框標題</h3>
{/* 內容 */}
<div className="mb-4">
{/* 對話框內容 */}
</div>
{/* 按鈕區 */}
<div className="flex gap-2">
<button className="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
取消
</button>
<button className="flex-1 px-4 py-2 bg-primary text-white rounded-md hover:bg-primary-hover">
確認
</button>
</div>
</div>
</div>
圖片預覽模態框
<div
className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50"
onClick={closeModal}
>
<div className="relative max-w-4xl max-h-[90vh] mx-4">
<img
src={imageUrl}
alt="放大圖片"
className="max-w-full max-h-full rounded-lg"
/>
<button
onClick={closeModal}
className="
absolute top-4 right-4
bg-black bg-opacity-50 text-white
p-2 rounded-full
hover:bg-opacity-75
"
>
✕
</button>
</div>
</div>
6.2 導航設計
學習導航按鈕
<div className="flex gap-4 mt-6">
{/* 上一張按鈕 */}
<button
onClick={handlePrevious}
disabled={isFirst}
className="
flex-1 py-3
bg-gray-500 text-white
rounded-lg
disabled:opacity-50 disabled:cursor-not-allowed
hover:bg-gray-600
transition-colors font-medium
"
>
上一張
</button>
{/* 下一張按鈕 */}
<button
onClick={handleNext}
className="
flex-1 py-3
bg-primary text-white
rounded-lg
hover:bg-primary-dark
transition-colors font-medium
"
>
{isLast ? '完成' : '下一張'}
</button>
</div>
6.3 錯誤報告組件
{/* 錯誤報告按鈕 */}
<div className="flex justify-end mb-2">
<button
onClick={openReportModal}
className="px-3 py-2 rounded-md transition-colors text-gray-600 hover:text-gray-900"
>
🚩 回報錯誤
</button>
</div>
{/* 錯誤報告模態框 */}
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 max-w-md w-full mx-4">
<h3 className="text-lg font-semibold mb-4">回報錯誤</h3>
<div className="mb-4">
<p className="text-sm text-gray-600 mb-2">單字:{word}</p>
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-2">
錯誤類型
</label>
<select className="
w-full p-2
border border-gray-300 rounded-md
focus:ring-blue-500 focus:border-blue-500
">
<option value="">請選擇錯誤類型</option>
<option value="translation">翻譯錯誤</option>
<option value="definition">定義錯誤</option>
<option value="pronunciation">發音錯誤</option>
<option value="example">例句錯誤</option>
</select>
</div>
<div className="flex gap-2">
<button className="flex-1 px-4 py-2 border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50">
取消
</button>
<button className="flex-1 px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700">
送出回報
</button>
</div>
</div>
</div>
7. 設計令牌 (Design Tokens)
7.1 間距令牌
/* 基礎間距單位:4px */
--spacing-1: 4px; /* gap-1, p-1, m-1 */
--spacing-2: 8px; /* gap-2, p-2, m-2 */
--spacing-3: 12px; /* gap-3, p-3, m-3 */
--spacing-4: 16px; /* gap-4, p-4, m-4 */
--spacing-6: 24px; /* gap-6, p-6, m-6 */
--spacing-8: 32px; /* gap-8, p-8, m-8 */
/* 布局間距 */
--layout-xs: 16px; /* 小型組件間距 */
--layout-sm: 24px; /* 中型組件間距 */
--layout-md: 32px; /* 標準組件間距 */
--layout-lg: 48px; /* 大型區塊間距 */
--layout-xl: 64px; /* 頁面區塊間距 */
7.2 陰影令牌
/* 陰影系統 */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); /* 輕微陰影 */
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); /* 標準陰影 */
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); /* 中等陰影 */
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); /* 大陰影(卡片) */
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1); /* 超大陰影(懸停) */
7.3 過渡動畫令牌
/* 過渡時間 */
--transition-fast: 150ms; /* 快速回饋 */
--transition-normal: 300ms; /* 標準過渡 */
--transition-slow: 500ms; /* 慢速動畫 */
/* 過渡函數 */
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
8. 組件使用指南
8.1 按鈕組件使用
使用場景對照表
| 按鈕類型 | 使用場景 | CSS類別 |
|---|---|---|
| Primary | 主要動作(保存、確認、下一步) | bg-primary text-white hover:bg-primary-hover |
| Secondary | 次要動作(取消、重置) | bg-gray-200 text-gray-700 hover:bg-gray-300 |
| Danger | 危險動作(刪除、清除) | bg-red-600 text-white hover:bg-red-700 |
| Success | 成功動作(完成、提交) | bg-success text-white hover:bg-green-600 |
按鈕尺寸規範
{/* 大型按鈕 - 主要動作 */}
<button className="px-6 py-3 text-base">大按鈕</button>
{/* 標準按鈕 - 一般動作 */}
<button className="px-4 py-2 text-sm">標準按鈕</button>
{/* 小型按鈕 - 次要動作 */}
<button className="px-3 py-1 text-xs">小按鈕</button>
8.2 卡片組件使用
主要內容卡片
- 用途: 主要學習內容、重要信息展示
- 特點: 大陰影、圓角、懸停效果
- 樣式:
bg-white rounded-xl shadow-lg hover:shadow-xl
資訊展示卡片
- 用途: 次要信息、詳細說明
- 特點: 淺色背景、邊框、適中內距
- 樣式:
bg-gray-50 rounded-lg p-4 border border-gray-200
狀態回饋卡片
- 用途: 答案回饋、操作結果
- 特點: 狀態色彩、邊框強調
- 樣式:
bg-green-50 border border-green-200(成功)
8.3 表單組件使用
輸入框設計
<input className="
w-full px-4 py-3
border border-gray-300 rounded-lg
focus:ring-2 focus:ring-primary focus:border-transparent
outline-none
placeholder-gray-400
" />
選擇器設計
<select className="
w-full p-2
border border-gray-300 rounded-md
focus:ring-blue-500 focus:border-blue-500
bg-white
">
<option>選項</option>
</select>
9. 可訪問性設計
9.1 語義化HTML
{/* 使用適當的語義標籤 */}
<main role="main">
<section aria-labelledby="learning-section">
<h2 id="learning-section">學習區塊</h2>
{/* 內容 */}
</section>
</main>
{/* 按鈕語義 */}
<button
type="button"
aria-label="播放音頻"
aria-pressed={isPlaying}
>
{isPlaying ? <Pause /> : <Play />}
</button>
9.2 鍵盤導航
{/* 支援鍵盤操作 */}
<input
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleSubmit();
}
if (e.key === 'Escape') {
handleCancel();
}
}}
/>
9.3 焦點管理
{/* 明確的焦點樣式 */}
<button className="
focus:ring-2 focus:ring-primary focus:ring-offset-2
focus:outline-none
">
按鈕
</button>
10. 動畫設計規範
10.1 頁面過渡
/* 頁面淡入 */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* 滑動進入 */
@keyframes slideIn {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
/* 放大進入 */
@keyframes scaleIn {
from { transform: scale(0.9); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
10.2 互動動畫
/* 懸停上升效果 */
.hover-lift {
transition: transform 0.2s ease;
}
.hover-lift:hover {
transform: translateY(-2px);
}
/* 點擊回饋 */
.click-feedback {
transition: transform 0.1s ease;
}
.click-feedback:active {
transform: scale(0.98);
}
10.3 卡片翻轉動畫
.card-flip-container {
perspective: 1000px;
}
.card-flip {
transition: transform 0.6s ease;
transform-style: preserve-3d;
}
.card-flip.flipped {
transform: rotateY(180deg);
}
.card-flip-front,
.card-flip-back {
backface-visibility: hidden;
position: absolute;
width: 100%;
height: 100%;
}
.card-flip-back {
transform: rotateY(180deg);
}
11. 設計一致性檢查清單
11.1 視覺一致性
- 所有按鈕使用統一的顏色和尺寸系統
- 卡片陰影和圓角保持一致
- 文字層級和間距符合設計系統
- 狀態顏色使用語義化且一致
11.2 交互一致性
- 相同功能的組件使用相同的交互模式
- 懸停和點擊效果在所有組件中保持一致
- 載入狀態使用統一的視覺表現
- 錯誤處理採用一致的回饋方式
11.3 內容一致性
- 標題層級結構合理且一致
- 說明文字使用統一的語調和格式
- 圖標使用保持一致的視覺風格
- 操作流程邏輯清晰且可預測
12. 實現指南
12.1 新組件開發流程
- 設計審查: 確認設計符合系統規範
- 組件拆分: 識別可重用的設計模式
- 樣式實現: 使用設計令牌和預定義類別
- 互動測試: 驗證各種狀態和過渡效果
- 響應式測試: 確保在不同設備上的表現
- 可訪問性測試: 驗證鍵盤導航和屏幕閱讀器支援
12.2 設計系統維護
新增設計元素流程
- 需求評估: 確認是否需要新的設計模式
- 一致性檢查: 與現有系統的兼容性
- 文檔更新: 更新設計規範文檔
- 團隊同步: 與開發團隊同步新的設計規範
設計令牌更新
- 修改tailwind.config.ts: 更新顏色、間距等令牌
- 組件更新: 更新受影響的組件實現
- 測試驗證: 確保變更不會破壞現有設計
- 文檔同步: 更新設計規範文檔
13. 最佳實踐
13.1 用戶體驗原則
學習流程設計
- 循序漸進: 從簡單到複雜的學習模式安排
- 即時回饋: 每個操作都有明確的視覺回饋
- 進度可視: 清晰的進度指示和成就感
- 錯誤友好: 錯誤狀態提供建設性的指導
認知負荷管理
- 視覺層次: 使用大小、顏色、間距建立清晰的信息層次
- 內容聚焦: 每個頁面專注於單一主要任務
- 減少選擇: 避免過多的同時選項,使用漸進式披露
13.2 技術實現最佳實踐
CSS組織
{/* 使用Tailwind的組合類別 */}
const buttonClass = `
px-6 py-3
bg-primary text-white
rounded-lg
hover:bg-primary-hover
transition-colors
font-medium
disabled:opacity-50
disabled:cursor-not-allowed
`;
{/* 條件式樣式 */}
const cardClass = `
border rounded-lg p-4 transition-all duration-200
${isSelected
? 'border-blue-500 bg-blue-50 shadow-sm'
: 'border-gray-200 bg-white hover:border-gray-300'
}
`;
響應式設計模式
{/* 移動優先的響應式設計 */}
<div className="
grid grid-cols-1 gap-4
md:grid-cols-2 md:gap-6
lg:grid-cols-3 lg:gap-8
">
{/* 內容 */}
</div>
{/* 條件式顯示 */}
<div className="hidden md:flex space-x-6">
{/* 桌面版內容 */}
</div>
<div className="md:hidden">
{/* 手機版內容 */}
</div>
14. 組件庫結構
14.1 基礎組件
/components
├── ui/
│ ├── Button.tsx # 基礎按鈕組件
│ ├── Card.tsx # 基礎卡片組件
│ ├── Modal.tsx # 模態對話框
│ ├── Input.tsx # 輸入組件
│ ├── Badge.tsx # 徽章標籤
│ └── Progress.tsx # 進度條
├── layout/
│ ├── Navigation.tsx # 導航組件
│ ├── PageHeader.tsx # 頁面標題
│ └── Container.tsx # 容器組件
└── learning/
├── FlipCard.tsx # 翻卡組件
├── QuizCard.tsx # 測驗卡片
├── AudioPlayer.tsx # 音頻播放器
└── VoiceRecorder.tsx # 語音錄製
14.2 設計系統文件結構
/design-system
├── tokens/
│ ├── colors.ts # 顏色令牌
│ ├── spacing.ts # 間距令牌
│ ├── typography.ts # 字體令牌
│ └── shadows.ts # 陰影令牌
├── components/
│ ├── Button.stories.tsx # 按鈕故事書
│ ├── Card.stories.tsx # 卡片故事書
│ └── ...
└── guidelines/
├── accessibility.md # 可訪問性指南
├── responsive.md # 響應式設計指南
└── animation.md # 動畫設計指南
15. 設計演進記錄
15.1 當前版本特色
- 清新漸層背景: 營造舒適的學習氛圍
- 3D翻卡效果: 增強學習的互動體驗
- 智能狀態回饋: 即時的學習成果反饋
- 多模式學習: 適應不同學習偏好的設計
15.2 設計改進方向
- 暗色主題支援: 提供夜間學習模式
- 個人化界面: 根據用戶偏好調整界面
- 更豐富的動畫: 增加學習過程的趣味性
- 無障礙優化: 進一步提升可訪問性
文件版本: 1.0 建立日期: 2025-09-20 維護者: DramaLing 設計團隊 適用範圍: DramaLing 詞彙學習系統全產品線