730 lines
21 KiB
HTML
730 lines
21 KiB
HTML
<!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/tokens/design-tokens.css">
|
||
<link rel="stylesheet" href="../../assets/styles/base.css">
|
||
<link rel="stylesheet" href="../../assets/styles/components.css">
|
||
<style>
|
||
body {
|
||
background: var(--background-primary);
|
||
padding: var(--space-8);
|
||
min-height: 100vh;
|
||
}
|
||
|
||
.demo-container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.demo-header {
|
||
text-align: center;
|
||
margin-bottom: var(--space-8);
|
||
}
|
||
|
||
.demo-title {
|
||
font-size: var(--text-3xl);
|
||
font-weight: 700;
|
||
color: var(--primary-teal);
|
||
margin-bottom: var(--space-4);
|
||
}
|
||
|
||
.demo-subtitle {
|
||
font-size: var(--text-lg);
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.demo-section {
|
||
margin-bottom: var(--space-10);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: var(--text-xl);
|
||
font-weight: 600;
|
||
color: var(--text-primary);
|
||
margin-bottom: var(--space-4);
|
||
padding-bottom: var(--space-2);
|
||
border-bottom: 2px solid var(--primary-teal);
|
||
}
|
||
|
||
.demo-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||
gap: var(--space-4);
|
||
margin-bottom: var(--space-6);
|
||
}
|
||
|
||
/* 模態框樣式 */
|
||
.modal-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
backdrop-filter: blur(4px);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 999;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.modal-overlay.active {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
.modal {
|
||
background: var(--card-background);
|
||
border-radius: var(--radius-2xl);
|
||
padding: var(--space-8);
|
||
max-width: 500px;
|
||
width: 90%;
|
||
max-height: 90vh;
|
||
overflow-y: auto;
|
||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||
transform: scale(0.9) translateY(20px);
|
||
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
}
|
||
|
||
.modal-overlay.active .modal {
|
||
transform: scale(1) translateY(0);
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: var(--space-6);
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: var(--text-xl);
|
||
font-weight: 700;
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.modal-close {
|
||
width: 32px;
|
||
height: 32px;
|
||
background: transparent;
|
||
border: none;
|
||
color: var(--text-tertiary);
|
||
cursor: pointer;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all 0.2s ease;
|
||
font-size: 20px;
|
||
}
|
||
|
||
.modal-close:hover {
|
||
background: var(--background-secondary);
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
.modal-body {
|
||
color: var(--text-secondary);
|
||
line-height: 1.6;
|
||
margin-bottom: var(--space-6);
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
gap: var(--space-3);
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
/* 成功模態框 */
|
||
.modal-success {
|
||
border-top: 4px solid var(--success-green);
|
||
}
|
||
|
||
.modal-success .modal-icon {
|
||
width: 80px;
|
||
height: 80px;
|
||
background: linear-gradient(135deg, rgba(76, 175, 80, 0.1), rgba(76, 175, 80, 0.05));
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 0 auto var(--space-6);
|
||
font-size: 40px;
|
||
}
|
||
|
||
/* 警告模態框 */
|
||
.modal-warning {
|
||
border-top: 4px solid var(--warning-yellow);
|
||
}
|
||
|
||
.modal-warning .modal-icon {
|
||
width: 80px;
|
||
height: 80px;
|
||
background: linear-gradient(135deg, rgba(243, 156, 18, 0.1), rgba(243, 156, 18, 0.05));
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 0 auto var(--space-6);
|
||
font-size: 40px;
|
||
}
|
||
|
||
/* 確認模態框 */
|
||
.modal-confirm {
|
||
border-top: 4px solid var(--primary-teal);
|
||
}
|
||
|
||
/* 表單模態框 */
|
||
.modal-form .modal-body {
|
||
padding: 0;
|
||
}
|
||
|
||
/* 圖片模態框 */
|
||
.modal-image {
|
||
padding: 0;
|
||
background: transparent;
|
||
max-width: 90%;
|
||
}
|
||
|
||
.modal-image img {
|
||
width: 100%;
|
||
border-radius: var(--radius-2xl);
|
||
}
|
||
|
||
/* 底部抽屜 */
|
||
.drawer {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background: var(--card-background);
|
||
border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
|
||
padding: var(--space-6);
|
||
transform: translateY(100%);
|
||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||
z-index: 999;
|
||
box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
.drawer.active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.drawer-handle {
|
||
width: 40px;
|
||
height: 4px;
|
||
background: var(--divider);
|
||
border-radius: var(--radius-full);
|
||
margin: 0 auto var(--space-4);
|
||
}
|
||
|
||
/* Toast 通知 */
|
||
.toast-container {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
z-index: 1000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-3);
|
||
}
|
||
|
||
.toast {
|
||
background: var(--card-background);
|
||
border-radius: var(--radius-lg);
|
||
padding: var(--space-4) var(--space-5);
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
min-width: 300px;
|
||
transform: translateX(400px);
|
||
opacity: 0;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.toast.show {
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
}
|
||
|
||
.toast-icon {
|
||
flex-shrink: 0;
|
||
font-size: 24px;
|
||
}
|
||
|
||
.toast-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.toast-title {
|
||
font-weight: 600;
|
||
color: var(--text-primary);
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.toast-message {
|
||
font-size: var(--text-sm);
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.toast-close {
|
||
flex-shrink: 0;
|
||
background: transparent;
|
||
border: none;
|
||
color: var(--text-tertiary);
|
||
cursor: pointer;
|
||
padding: var(--space-1);
|
||
}
|
||
|
||
.toast-success {
|
||
border-left: 4px solid var(--success-green);
|
||
}
|
||
|
||
.toast-error {
|
||
border-left: 4px solid var(--error-red);
|
||
}
|
||
|
||
.toast-warning {
|
||
border-left: 4px solid var(--warning-yellow);
|
||
}
|
||
|
||
.toast-info {
|
||
border-left: 4px solid var(--info-cyan);
|
||
}
|
||
|
||
/* 彈出選單 */
|
||
.dropdown {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
|
||
.dropdown-menu {
|
||
position: absolute;
|
||
top: calc(100% + var(--space-2));
|
||
left: 0;
|
||
background: var(--card-background);
|
||
border: 1px solid var(--divider);
|
||
border-radius: var(--radius-lg);
|
||
padding: var(--space-2);
|
||
min-width: 200px;
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transform: translateY(-10px);
|
||
transition: all 0.2s ease;
|
||
z-index: 100;
|
||
}
|
||
|
||
.dropdown.active .dropdown-menu {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.dropdown-item {
|
||
display: block;
|
||
width: 100%;
|
||
padding: var(--space-3) var(--space-4);
|
||
background: transparent;
|
||
border: none;
|
||
border-radius: var(--radius-md);
|
||
text-align: left;
|
||
color: var(--text-primary);
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
font-size: var(--text-sm);
|
||
}
|
||
|
||
.dropdown-item:hover {
|
||
background: var(--background-secondary);
|
||
transform: translateX(4px);
|
||
}
|
||
|
||
.dropdown-item.active {
|
||
background: linear-gradient(135deg, rgba(0, 229, 204, 0.1), rgba(0, 229, 204, 0.05));
|
||
color: var(--primary-teal);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.dropdown-divider {
|
||
height: 1px;
|
||
background: var(--divider);
|
||
margin: var(--space-2) 0;
|
||
}
|
||
|
||
/* 工具提示 */
|
||
.tooltip-wrapper {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
|
||
.tooltip {
|
||
position: absolute;
|
||
bottom: calc(100% + var(--space-2));
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: var(--background-dark);
|
||
color: var(--text-primary);
|
||
padding: var(--space-2) var(--space-3);
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--text-xs);
|
||
white-space: nowrap;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
transition: all 0.2s ease;
|
||
pointer-events: none;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.tooltip::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 100%;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
border: 6px solid transparent;
|
||
border-top-color: var(--background-dark);
|
||
}
|
||
|
||
.tooltip-wrapper:hover .tooltip {
|
||
opacity: 1;
|
||
visibility: visible;
|
||
}
|
||
|
||
/* 返回按鈕 */
|
||
.back-link {
|
||
position: fixed;
|
||
bottom: 20px;
|
||
right: 20px;
|
||
background: var(--primary-teal);
|
||
color: var(--background-dark);
|
||
padding: var(--space-3) var(--space-4);
|
||
border-radius: var(--radius-full);
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
box-shadow: 0 4px 16px rgba(0, 229, 204, 0.3);
|
||
z-index: 100;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.back-link:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 24px rgba(0, 229, 204, 0.4);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="demo-container">
|
||
<!-- 頁面標題 -->
|
||
<div class="demo-header">
|
||
<h1 class="demo-title">🎭 互動元件展示</h1>
|
||
<p class="demo-subtitle">模態框、通知、下拉選單等互動元件</p>
|
||
</div>
|
||
|
||
<!-- 模態框示例 -->
|
||
<section class="demo-section">
|
||
<h2 class="section-title">模態框 Modals</h2>
|
||
<div class="demo-grid">
|
||
<button class="btn btn-primary" onclick="openModal('basicModal')">基礎模態框</button>
|
||
<button class="btn btn-success" onclick="openModal('successModal')">成功模態框</button>
|
||
<button class="btn btn-warning" onclick="openModal('warningModal')">警告模態框</button>
|
||
<button class="btn btn-secondary" onclick="openModal('formModal')">表單模態框</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Toast 通知示例 -->
|
||
<section class="demo-section">
|
||
<h2 class="section-title">Toast 通知</h2>
|
||
<div class="demo-grid">
|
||
<button class="btn btn-success" onclick="showToast('success')">成功通知</button>
|
||
<button class="btn btn-danger" onclick="showToast('error')">錯誤通知</button>
|
||
<button class="btn btn-warning" onclick="showToast('warning')">警告通知</button>
|
||
<button class="btn btn-primary" onclick="showToast('info')">資訊通知</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 下拉選單示例 -->
|
||
<section class="demo-section">
|
||
<h2 class="section-title">下拉選單 Dropdown</h2>
|
||
<div class="demo-grid">
|
||
<div class="dropdown">
|
||
<button class="btn btn-secondary" onclick="toggleDropdown(this.parentElement)">
|
||
選擇選項 ▼
|
||
</button>
|
||
<div class="dropdown-menu">
|
||
<button class="dropdown-item active">選項 1</button>
|
||
<button class="dropdown-item">選項 2</button>
|
||
<button class="dropdown-item">選項 3</button>
|
||
<div class="dropdown-divider"></div>
|
||
<button class="dropdown-item">其他選項</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dropdown">
|
||
<button class="btn btn-primary" onclick="toggleDropdown(this.parentElement)">
|
||
用戶選單 ▼
|
||
</button>
|
||
<div class="dropdown-menu">
|
||
<button class="dropdown-item">👤 個人資料</button>
|
||
<button class="dropdown-item">⚙️ 設定</button>
|
||
<button class="dropdown-item">📊 統計</button>
|
||
<div class="dropdown-divider"></div>
|
||
<button class="dropdown-item">🚪 登出</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 工具提示示例 -->
|
||
<section class="demo-section">
|
||
<h2 class="section-title">工具提示 Tooltips</h2>
|
||
<div class="demo-grid">
|
||
<div class="tooltip-wrapper">
|
||
<button class="btn btn-primary">懸停顯示提示</button>
|
||
<div class="tooltip">這是一個工具提示</div>
|
||
</div>
|
||
|
||
<div class="tooltip-wrapper">
|
||
<span class="badge badge-info">資訊徽章</span>
|
||
<div class="tooltip">點擊查看更多資訊</div>
|
||
</div>
|
||
|
||
<div class="tooltip-wrapper">
|
||
<button class="btn btn-icon btn-secondary">❓</button>
|
||
<div class="tooltip">需要幫助嗎?</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 底部抽屜示例 -->
|
||
<section class="demo-section">
|
||
<h2 class="section-title">底部抽屜 Drawer</h2>
|
||
<button class="btn btn-primary" onclick="toggleDrawer()">打開底部抽屜</button>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- 基礎模態框 -->
|
||
<div class="modal-overlay" id="basicModal" onclick="closeModalOnOverlay(event)">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h3 class="modal-title">基礎模態框</h3>
|
||
<button class="modal-close" onclick="closeModal('basicModal')">✕</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
這是一個基礎的模態框範例。你可以在這裡放置任何內容,包括文字、圖片、表單等。
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-secondary btn-sm" onclick="closeModal('basicModal')">取消</button>
|
||
<button class="btn btn-primary btn-sm">確認</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 成功模態框 -->
|
||
<div class="modal-overlay" id="successModal" onclick="closeModalOnOverlay(event)">
|
||
<div class="modal modal-success">
|
||
<div class="modal-icon">✓</div>
|
||
<div class="modal-header" style="justify-content: center;">
|
||
<h3 class="modal-title">操作成功!</h3>
|
||
</div>
|
||
<div class="modal-body" style="text-align: center;">
|
||
你的操作已成功完成。所有變更都已儲存。
|
||
</div>
|
||
<div class="modal-footer" style="justify-content: center;">
|
||
<button class="btn btn-success" onclick="closeModal('successModal')">太棒了!</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 警告模態框 -->
|
||
<div class="modal-overlay" id="warningModal" onclick="closeModalOnOverlay(event)">
|
||
<div class="modal modal-warning">
|
||
<div class="modal-icon">⚠</div>
|
||
<div class="modal-header" style="justify-content: center;">
|
||
<h3 class="modal-title">確認刪除?</h3>
|
||
</div>
|
||
<div class="modal-body" style="text-align: center;">
|
||
此操作無法復原。確定要刪除這個項目嗎?
|
||
</div>
|
||
<div class="modal-footer" style="justify-content: center;">
|
||
<button class="btn btn-secondary" onclick="closeModal('warningModal')">取消</button>
|
||
<button class="btn btn-danger">刪除</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 表單模態框 -->
|
||
<div class="modal-overlay" id="formModal" onclick="closeModalOnOverlay(event)">
|
||
<div class="modal modal-form">
|
||
<div class="modal-header">
|
||
<h3 class="modal-title">編輯個人資料</h3>
|
||
<button class="modal-close" onclick="closeModal('formModal')">✕</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="input-group">
|
||
<label class="input-label">姓名</label>
|
||
<input type="text" class="input-field" placeholder="請輸入姓名" value="王小明">
|
||
</div>
|
||
<div class="input-group">
|
||
<label class="input-label">電子郵件</label>
|
||
<input type="email" class="input-field" placeholder="example@email.com" value="wang@example.com">
|
||
</div>
|
||
<div class="input-group">
|
||
<label class="input-label">簡介</label>
|
||
<textarea class="input-field textarea" placeholder="介紹一下自己...">我是一個熱愛學習的人!</textarea>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-secondary btn-sm" onclick="closeModal('formModal')">取消</button>
|
||
<button class="btn btn-primary btn-sm">儲存變更</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 底部抽屜 -->
|
||
<div class="drawer" id="bottomDrawer">
|
||
<div class="drawer-handle"></div>
|
||
<h3 style="margin-bottom: var(--space-4); color: var(--text-primary);">選擇學習模式</h3>
|
||
<div style="display: grid; gap: var(--space-3);">
|
||
<button class="btn btn-primary" style="width: 100%;">📖 詞彙學習</button>
|
||
<button class="btn btn-secondary" style="width: 100%;">🗣️ 口說練習</button>
|
||
<button class="btn btn-secondary" style="width: 100%;">💬 對話練習</button>
|
||
<button class="btn btn-text" style="width: 100%;" onclick="toggleDrawer()">取消</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Toast 容器 -->
|
||
<div class="toast-container" id="toastContainer"></div>
|
||
|
||
<!-- 返回連結 -->
|
||
<a href="../../index.html" class="back-link">← 返回元件庫</a>
|
||
|
||
<script>
|
||
// 開啟模態框
|
||
function openModal(modalId) {
|
||
const modal = document.getElementById(modalId);
|
||
modal.classList.add('active');
|
||
document.body.style.overflow = 'hidden';
|
||
}
|
||
|
||
// 關閉模態框
|
||
function closeModal(modalId) {
|
||
const modal = document.getElementById(modalId);
|
||
modal.classList.remove('active');
|
||
document.body.style.overflow = '';
|
||
}
|
||
|
||
// 點擊遮罩關閉
|
||
function closeModalOnOverlay(event) {
|
||
if (event.target.classList.contains('modal-overlay')) {
|
||
event.target.classList.remove('active');
|
||
document.body.style.overflow = '';
|
||
}
|
||
}
|
||
|
||
// 顯示 Toast
|
||
function showToast(type) {
|
||
const toastContainer = document.getElementById('toastContainer');
|
||
|
||
const toastData = {
|
||
success: { icon: '✓', title: '成功!', message: '操作已成功完成' },
|
||
error: { icon: '✕', title: '錯誤', message: '發生錯誤,請稍後再試' },
|
||
warning: { icon: '⚠', title: '警告', message: '請注意這個重要訊息' },
|
||
info: { icon: 'ℹ', title: '提示', message: '這是一條有用的資訊' }
|
||
};
|
||
|
||
const data = toastData[type];
|
||
|
||
const toast = document.createElement('div');
|
||
toast.className = `toast toast-${type}`;
|
||
toast.innerHTML = `
|
||
<span class="toast-icon">${data.icon}</span>
|
||
<div class="toast-content">
|
||
<div class="toast-title">${data.title}</div>
|
||
<div class="toast-message">${data.message}</div>
|
||
</div>
|
||
<button class="toast-close" onclick="removeToast(this.parentElement)">✕</button>
|
||
`;
|
||
|
||
toastContainer.appendChild(toast);
|
||
|
||
// 觸發動畫
|
||
setTimeout(() => {
|
||
toast.classList.add('show');
|
||
}, 10);
|
||
|
||
// 自動移除
|
||
setTimeout(() => {
|
||
removeToast(toast);
|
||
}, 5000);
|
||
}
|
||
|
||
// 移除 Toast
|
||
function removeToast(toast) {
|
||
toast.classList.remove('show');
|
||
setTimeout(() => {
|
||
toast.remove();
|
||
}, 300);
|
||
}
|
||
|
||
// 切換下拉選單
|
||
function toggleDropdown(dropdown) {
|
||
// 關閉其他下拉選單
|
||
document.querySelectorAll('.dropdown').forEach(d => {
|
||
if (d !== dropdown) {
|
||
d.classList.remove('active');
|
||
}
|
||
});
|
||
|
||
dropdown.classList.toggle('active');
|
||
}
|
||
|
||
// 切換底部抽屜
|
||
function toggleDrawer() {
|
||
const drawer = document.getElementById('bottomDrawer');
|
||
drawer.classList.toggle('active');
|
||
|
||
// 添加遮罩
|
||
if (drawer.classList.contains('active')) {
|
||
const overlay = document.createElement('div');
|
||
overlay.className = 'modal-overlay active';
|
||
overlay.id = 'drawerOverlay';
|
||
overlay.style.zIndex = '998';
|
||
overlay.onclick = toggleDrawer;
|
||
document.body.appendChild(overlay);
|
||
} else {
|
||
const overlay = document.getElementById('drawerOverlay');
|
||
if (overlay) {
|
||
overlay.remove();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 點擊外部關閉下拉選單
|
||
document.addEventListener('click', (e) => {
|
||
if (!e.target.closest('.dropdown')) {
|
||
document.querySelectorAll('.dropdown').forEach(d => {
|
||
d.classList.remove('active');
|
||
});
|
||
}
|
||
});
|
||
|
||
// ESC 鍵關閉模態框
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Escape') {
|
||
document.querySelectorAll('.modal-overlay.active').forEach(modal => {
|
||
modal.classList.remove('active');
|
||
});
|
||
document.body.style.overflow = '';
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |