dramaling-app/docs/02_design/ui-ux/component-showcase.html

722 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drama Ling 設計系統 - 組件展示</title>
<link rel="stylesheet" href="design-system.css">
<style>
/* 展示頁面專用樣式 */
body {
background: linear-gradient(135deg, var(--background-primary), var(--background-secondary));
min-height: 100vh;
}
.showcase-header {
background: var(--card-background);
border-bottom: 1px solid var(--divider);
padding: var(--space-8) 0;
margin-bottom: var(--space-8);
}
.showcase-title {
font-size: var(--text-3xl);
font-weight: 700;
text-align: center;
background: linear-gradient(135deg, var(--primary-teal), var(--accent-violet));
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: var(--space-4);
}
.showcase-subtitle {
text-align: center;
color: var(--text-secondary);
font-size: var(--text-lg);
}
.section {
margin-bottom: var(--space-16);
}
.section-title {
font-size: var(--text-2xl);
font-weight: 700;
color: var(--text-primary);
margin-bottom: var(--space-6);
padding-bottom: var(--space-2);
border-bottom: 2px solid var(--primary-teal);
}
.component-group {
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-8);
margin-bottom: var(--space-6);
border: 1px solid var(--divider);
}
.component-title {
font-size: var(--text-xl);
font-weight: 600;
color: var(--primary-teal);
margin-bottom: var(--space-4);
}
.component-description {
color: var(--text-secondary);
margin-bottom: var(--space-6);
line-height: 1.6;
}
.component-demo {
background: rgba(255, 255, 255, 0.05);
border-radius: var(--radius-lg);
padding: var(--space-6);
margin-bottom: var(--space-4);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.demo-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--space-4);
}
.demo-item {
background: rgba(0, 0, 0, 0.2);
padding: var(--space-4);
border-radius: var(--radius-md);
text-align: center;
}
.color-palette {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: var(--space-3);
}
.color-swatch {
height: 80px;
border-radius: var(--radius-md);
display: flex;
align-items: end;
padding: var(--space-2);
color: white;
font-size: var(--text-xs);
font-weight: 600;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.typography-demo {
display: grid;
gap: var(--space-3);
}
.font-sample {
padding: var(--space-3);
background: rgba(255, 255, 255, 0.05);
border-radius: var(--radius-md);
border-left: 4px solid var(--primary-teal);
}
.code-preview {
background: var(--background-dark);
border-radius: var(--radius-md);
padding: var(--space-4);
margin-top: var(--space-4);
overflow-x: auto;
}
.code-preview code {
font-family: var(--font-mono);
font-size: var(--text-sm);
color: #61dafb;
}
.interactive-demo {
display: flex;
flex-wrap: wrap;
gap: var(--space-4);
align-items: center;
}
.demo-controls {
display: flex;
gap: var(--space-2);
margin-top: var(--space-4);
flex-wrap: wrap;
}
/* 特殊展示組件 */
.experience-demo {
width: 100%;
max-width: 400px;
}
.dialogue-demo {
max-width: 500px;
margin: 0 auto;
}
.product-demo {
max-width: 300px;
}
.voice-demo {
display: flex;
justify-content: center;
}
/* 響應式調整 */
@media (max-width: 768px) {
.demo-grid {
grid-template-columns: 1fr;
}
.interactive-demo {
flex-direction: column;
align-items: stretch;
}
.showcase-header {
padding: var(--space-6) 0;
}
.showcase-title {
font-size: var(--text-2xl);
}
}
</style>
</head>
<body>
<div class="showcase-header">
<div class="container">
<h1 class="showcase-title">Drama Ling 設計系統</h1>
<p class="showcase-subtitle">企業級組件庫展示 v4.0</p>
</div>
</div>
<div class="container">
<!-- 色彩系統 -->
<section class="section">
<h2 class="section-title">🎨 色彩系統</h2>
<div class="component-group">
<h3 class="component-title">主要品牌色彩</h3>
<p class="component-description">Drama Ling 的核心品牌識別色彩,用於主要界面元素和品牌表達。</p>
<div class="component-demo">
<div class="color-palette">
<div class="color-swatch" style="background: var(--primary-teal);">主要青綠</div>
<div class="color-swatch" style="background: var(--primary-teal-light);">青綠-淺</div>
<div class="color-swatch" style="background: var(--primary-teal-dark);">青綠-深</div>
<div class="color-swatch" style="background: var(--secondary-purple);">輔助紫色</div>
<div class="color-swatch" style="background: var(--accent-violet);">強調紫色</div>
</div>
</div>
<div class="code-preview">
<code>
/* 主要品牌色彩使用 */<br>
.primary-button { background: var(--primary-teal); }<br>
.accent-text { color: var(--accent-violet); }<br>
.brand-gradient { background: linear-gradient(135deg, var(--primary-teal), var(--accent-violet)); }
</code>
</div>
</div>
<div class="component-group">
<h3 class="component-title">功能性色彩</h3>
<p class="component-description">用於表達系統狀態和用戶回饋的功能性色彩。</p>
<div class="component-demo">
<div class="color-palette">
<div class="color-swatch" style="background: var(--success-green);">成功綠色</div>
<div class="color-swatch" style="background: var(--error-red);">錯誤紅色</div>
<div class="color-swatch" style="background: var(--warning-yellow);">警告黃色</div>
<div class="color-swatch" style="background: var(--info-cyan);">資訊藍色</div>
</div>
</div>
</div>
<div class="component-group">
<h3 class="component-title">遊戲化色彩</h3>
<p class="component-description">專為遊戲化元素設計的特殊色彩系統。</p>
<div class="component-demo">
<div class="color-palette">
<div class="color-swatch" style="background: var(--gold);">金色成就</div>
<div class="color-swatch" style="background: var(--silver);">銀色成就</div>
<div class="color-swatch" style="background: var(--bronze);">銅色成就</div>
<div class="color-swatch" style="background: var(--diamond);">鑽石特效</div>
<div class="color-swatch" style="background: var(--level-beginner);">初學者</div>
<div class="color-swatch" style="background: var(--level-expert);">專家級</div>
</div>
</div>
</div>
</section>
<!-- 字體系統 -->
<section class="section">
<h2 class="section-title">📝 字體系統</h2>
<div class="component-group">
<h3 class="component-title">響應式字體大小</h3>
<p class="component-description">Mobile First 設計,自適應不同螢幕尺寸的字體系統。</p>
<div class="component-demo">
<div class="typography-demo">
<div class="font-sample" style="font-size: var(--text-4xl);">超大標題 (4xl) - 主要頁面標題</div>
<div class="font-sample" style="font-size: var(--text-3xl);">大標題 (3xl) - 區塊標題</div>
<div class="font-sample" style="font-size: var(--text-2xl);">中標題 (2xl) - 卡片標題</div>
<div class="font-sample" style="font-size: var(--text-xl);">小標題 (xl) - 組件標題</div>
<div class="font-sample" style="font-size: var(--text-lg);">大文字 (lg) - 重要內容</div>
<div class="font-sample" style="font-size: var(--text-base);">基礎文字 (base) - 正文內容</div>
<div class="font-sample" style="font-size: var(--text-sm);">小文字 (sm) - 輔助資訊</div>
<div class="font-sample" style="font-size: var(--text-xs);">超小文字 (xs) - 標籤提示</div>
</div>
</div>
</div>
</section>
<!-- 按鈕組件 -->
<section class="section">
<h2 class="section-title">🔘 按鈕組件</h2>
<div class="component-group">
<h3 class="component-title">基礎按鈕</h3>
<p class="component-description">支援多種狀態和樣式的按鈕組件系統。</p>
<div class="component-demo">
<div class="interactive-demo">
<button class="btn btn-primary">主要按鈕</button>
<button class="btn btn-secondary">次要按鈕</button>
<button class="btn btn-primary" disabled>禁用狀態</button>
</div>
<div class="demo-controls">
<button class="btn btn-primary" onclick="simulateLoading(this)">載入測試</button>
<button class="btn btn-secondary" onclick="simulateHover(this)">懸停測試</button>
</div>
</div>
<div class="code-preview">
<code>
&lt;button class="btn btn-primary"&gt;主要按鈕&lt;/button&gt;<br>
&lt;button class="btn btn-secondary"&gt;次要按鈕&lt;/button&gt;<br>
&lt;button class="btn btn-primary" disabled&gt;禁用狀態&lt;/button&gt;
</code>
</div>
</div>
</section>
<!-- 遊戲化組件 -->
<section class="section">
<h2 class="section-title">🎮 遊戲化組件</h2>
<div class="component-group">
<h3 class="component-title">經驗值系統</h3>
<p class="component-description">視覺化展示用戶學習進度的經驗值和等級系統。</p>
<div class="component-demo">
<div class="experience-demo">
<div class="level-indicator">
<div class="level-number">15</div>
<span>中級學習者</span>
</div>
<div style="margin: var(--space-4) 0;">
<div class="experience-bar-container">
<div class="experience-bar-fill" style="width: 68%;" id="expBar"></div>
</div>
<div style="margin-top: var(--space-2); font-size: var(--text-sm); color: var(--text-secondary);">
2,850 / 4,200 EXP
</div>
</div>
<div class="demo-controls">
<button class="btn btn-secondary" onclick="animateExp()">模擬獲得經驗</button>
</div>
</div>
</div>
</div>
<div class="component-group">
<h3 class="component-title">關卡狀態指示器</h3>
<p class="component-description">用於學習地圖的關卡狀態視覺指示系統。</p>
<div class="component-demo">
<div class="interactive-demo">
<div class="demo-item">
<div class="level-status-indicator locked">🔒</div>
<div style="margin-top: var(--space-2); font-size: var(--text-xs);">鎖定狀態</div>
</div>
<div class="demo-item">
<div class="level-status-indicator available">▶️</div>
<div style="margin-top: var(--space-2); font-size: var(--text-xs);">可進行</div>
</div>
<div class="demo-item">
<div class="level-status-indicator in-progress">🔄</div>
<div style="margin-top: var(--space-2); font-size: var(--text-xs);">進行中</div>
</div>
<div class="demo-item">
<div class="level-status-indicator completed"></div>
<div style="margin-top: var(--space-2); font-size: var(--text-xs);">已完成</div>
</div>
</div>
</div>
</div>
<div class="component-group">
<h3 class="component-title">成就徽章系統</h3>
<p class="component-description">激勵用戶持續學習的成就和徽章系統。</p>
<div class="component-demo">
<div class="achievement-container">
<div class="achievement-badge unlocked">
<div class="achievement-icon">🏆</div>
<div class="achievement-title">對話大師</div>
<div class="achievement-description">完成100次對話練習</div>
</div>
<div class="achievement-badge unlocked">
<div class="achievement-icon">📚</div>
<div class="achievement-title">詞彙達人</div>
<div class="achievement-description">掌握500個詞彙</div>
</div>
<div class="achievement-badge locked">
<div class="achievement-icon">🚀</div>
<div class="achievement-title">進階學習者</div>
<div class="achievement-description">達到高級程度</div>
</div>
</div>
</div>
</div>
</section>
<!-- 學習功能組件 -->
<section class="section">
<h2 class="section-title">🎯 學習功能組件</h2>
<div class="component-group">
<h3 class="component-title">語音輸入介面</h3>
<p class="component-description">沉浸式語音學習體驗的核心交互組件。</p>
<div class="component-demo">
<div class="voice-demo">
<div class="voice-input-container" id="voiceContainer">
<div class="voice-button" id="voiceButton">🎤</div>
<div class="voice-waveform" id="voiceWaveform">
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
<div class="waveform-bar"></div>
</div>
<div style="text-align: center; color: var(--text-secondary);">
點擊麥克風開始語音輸入
</div>
</div>
</div>
<div class="demo-controls">
<button class="btn btn-secondary" onclick="toggleVoiceRecording()">模擬錄音</button>
<button class="btn btn-secondary" onclick="resetVoiceDemo()">重置狀態</button>
</div>
</div>
</div>
<div class="component-group">
<h3 class="component-title">對話氣泡系統</h3>
<p class="component-description">情境對話練習的對話氣泡設計系統。</p>
<div class="component-demo">
<div class="dialogue-demo">
<div class="dialogue-container">
<div class="dialogue-message system">
情境:在咖啡店點餐
</div>
<div class="dialogue-message assistant">
Hello! Welcome to our coffee shop. What would you like to order today?
</div>
<div class="dialogue-message user">
I'd like a large cappuccino, please.
<div class="message-timestamp">14:32</div>
<div class="message-status read"></div>
</div>
<div class="dialogue-message assistant">
Excellent choice! Would you like any pastries with that?
</div>
</div>
</div>
<div class="demo-controls">
<button class="btn btn-secondary" onclick="addDialogueMessage()">新增對話</button>
</div>
</div>
</div>
</section>
<!-- 商業功能組件 -->
<section class="section">
<h2 class="section-title">🛒 商業功能組件</h2>
<div class="component-group">
<h3 class="component-title">商品卡片系統</h3>
<p class="component-description">道具商店的商品展示和購買引導組件。</p>
<div class="component-demo">
<div class="demo-grid">
<div class="product-demo">
<div class="product-card">
<div class="product-icon">💡</div>
<div class="product-title">回覆提示道具</div>
<div class="product-description">AI智慧引導幫助您在對話中不再卡關</div>
<div class="product-tags" style="display: flex; gap: var(--space-2); margin: var(--space-4) 0; flex-wrap: wrap;">
<div class="product-tag bestseller">熱銷</div>
<div class="product-tag new">新品</div>
</div>
<div class="product-price">
<div class="price-value">
<span class="price-currency">💎</span>
<span>30</span>
</div>
<div class="price-discount">-20%</div>
</div>
<button class="btn btn-primary" style="width: 100%; margin-top: var(--space-4);">
立即購買
</button>
</div>
</div>
<div class="product-demo">
<div class="product-card">
<div class="product-icon">❤️</div>
<div class="product-title">生命保護罩</div>
<div class="product-description">闖關失敗不扣命條,保護珍貴生命</div>
<div class="product-tags" style="display: flex; gap: var(--space-2); margin: var(--space-4) 0; flex-wrap: wrap;">
<div class="product-tag limited">限時</div>
</div>
<div class="product-price">
<div class="price-value">
<span class="price-currency">💎</span>
<span>200</span>
</div>
</div>
<button class="btn btn-primary" style="width: 100%; margin-top: var(--space-4);">
立即購買
</button>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- 輸入框組件 -->
<section class="section">
<h2 class="section-title">📝 表單組件</h2>
<div class="component-group">
<h3 class="component-title">輸入框系統</h3>
<p class="component-description">支援多種狀態和驗證的輸入框組件。</p>
<div class="component-demo">
<div class="demo-grid">
<div>
<label class="input-label">一般輸入框</label>
<input type="text" class="input-field" placeholder="請輸入內容">
</div>
<div>
<label class="input-label required">必填輸入框</label>
<input type="text" class="input-field" placeholder="此欄位為必填">
</div>
<div>
<label class="input-label">成功狀態</label>
<input type="text" class="input-field success" value="正確的輸入">
</div>
<div>
<label class="input-label">錯誤狀態</label>
<input type="text" class="input-field error" value="錯誤的輸入">
</div>
</div>
</div>
<div class="code-preview">
<code>
&lt;label class="input-label required"&gt;必填輸入框&lt;/label&gt;<br>
&lt;input type="text" class="input-field" placeholder="此欄位為必填"&gt;<br><br>
&lt;input type="text" class="input-field success" value="正確的輸入"&gt;<br>
&lt;input type="text" class="input-field error" value="錯誤的輸入"&gt;
</code>
</div>
</div>
</section>
<!-- 工具類別 -->
<section class="section">
<h2 class="section-title">🔧 工具類別</h2>
<div class="component-group">
<h3 class="component-title">間距和佈局</h3>
<p class="component-description">快速佈局和間距調整的工具類別。</p>
<div class="component-demo">
<div class="demo-grid">
<div class="demo-item">
<div class="flex items-center justify-center p-4" style="background: var(--primary-teal); border-radius: var(--radius-md);">
Flexbox 中心對齊
</div>
</div>
<div class="demo-item">
<div class="grid grid-cols-2 gap-2">
<div style="background: var(--accent-violet); padding: var(--space-2); border-radius: var(--radius-sm); text-align: center;">Grid 1</div>
<div style="background: var(--accent-violet); padding: var(--space-2); border-radius: var(--radius-sm); text-align: center;">Grid 2</div>
</div>
</div>
<div class="demo-item">
<div class="text-center p-6 m-4" style="background: var(--success-green); border-radius: var(--radius-md);">
間距工具類別
</div>
</div>
</div>
</div>
<div class="code-preview">
<code>
&lt;div class="flex items-center justify-center"&gt;Flexbox&lt;/div&gt;<br>
&lt;div class="grid grid-cols-2 gap-4"&gt;Grid 佈局&lt;/div&gt;<br>
&lt;div class="text-center p-6 m-4"&gt;間距工具&lt;/div&gt;
</code>
</div>
</div>
</section>
</div>
<script>
// 交互演示功能
function simulateLoading(button) {
const originalText = button.textContent;
button.textContent = '載入中...';
button.disabled = true;
setTimeout(() => {
button.textContent = originalText;
button.disabled = false;
}, 2000);
}
function simulateHover(button) {
button.style.transform = 'translateY(-2px)';
button.style.boxShadow = '0 8px 25px rgba(0, 229, 204, 0.3)';
setTimeout(() => {
button.style.transform = '';
button.style.boxShadow = '';
}, 1000);
}
function animateExp() {
const expBar = document.getElementById('expBar');
const currentWidth = 68;
const targetWidth = Math.min(100, currentWidth + Math.random() * 20);
expBar.style.width = targetWidth + '%';
if (targetWidth >= 100) {
setTimeout(() => {
expBar.style.width = '15%';
alert('🎉 升級了!恭喜達到新等級!');
}, 1000);
}
}
let voiceRecording = false;
function toggleVoiceRecording() {
const container = document.getElementById('voiceContainer');
const button = document.getElementById('voiceButton');
const waveform = document.getElementById('voiceWaveform');
voiceRecording = !voiceRecording;
if (voiceRecording) {
container.classList.add('active');
button.classList.add('recording');
button.textContent = '⏹️';
waveform.classList.add('active');
} else {
container.classList.remove('active');
button.classList.remove('recording');
button.textContent = '🎤';
waveform.classList.remove('active');
}
}
function resetVoiceDemo() {
const container = document.getElementById('voiceContainer');
const button = document.getElementById('voiceButton');
const waveform = document.getElementById('voiceWaveform');
voiceRecording = false;
container.classList.remove('active');
button.classList.remove('recording');
button.textContent = '🎤';
waveform.classList.remove('active');
}
function addDialogueMessage() {
const container = document.querySelector('.dialogue-container');
const messages = [
{ type: 'user', text: 'Could I also get a chocolate croissant?' },
{ type: 'assistant', text: 'Of course! That will be $8.50 in total. Would you like that for here or to go?' },
{ type: 'user', text: 'For here, please. Thank you!' }
];
const randomMessage = messages[Math.floor(Math.random() * messages.length)];
const messageDiv = document.createElement('div');
messageDiv.className = `dialogue-message ${randomMessage.type}`;
messageDiv.innerHTML = randomMessage.text;
if (randomMessage.type === 'user') {
messageDiv.innerHTML += '<div class="message-timestamp">' + new Date().toLocaleTimeString('zh-TW', {hour: '2-digit', minute: '2-digit'}) + '</div>';
messageDiv.innerHTML += '<div class="message-status read"></div>';
}
container.appendChild(messageDiv);
container.scrollTop = container.scrollHeight;
}
// 自動演示效果
setInterval(() => {
const expBar = document.getElementById('expBar');
if (expBar && Math.random() < 0.3) {
const currentWidth = parseFloat(expBar.style.width) || 68;
const newWidth = Math.min(100, currentWidth + Math.random() * 2);
expBar.style.width = newWidth + '%';
}
}, 5000);
</script>
</body>
</html>