diff --git a/docs/ui-ux-optimization/progress-tracker.md b/docs/ui-ux-optimization/progress-tracker.md new file mode 100644 index 00000000..eb2396a4 --- /dev/null +++ b/docs/ui-ux-optimization/progress-tracker.md @@ -0,0 +1,157 @@ +# Settings Modal Optimization Progress Tracker + +## Project Overview +**Goal**: Optimize Settings Modal UI/UX with left navigation sidebar +**Started**: 2026-02-23 +**Current Phase**: P0 - Left Navigation Sidebar + +--- + +## Phase 0: Left Navigation Sidebar (P0) + +### Status: Completed ✓ + +### Completion Notes +- All CSS changes implemented +- HTML structure restructured successfully +- JavaScript navigation functionality added +- Translation keys added and synchronized +- Ready for testing and review + +### Tasks + +#### 1. CSS Changes +- [x] Add two-column layout styles + - [x] `.settings-modal` flex layout + - [x] `.settings-nav` sidebar styles + - [x] `.settings-content` content area styles + - [x] `.settings-nav-item` navigation item styles + - [x] `.settings-nav-item.active` active state styles +- [x] Adjust modal width to 950px +- [x] Add smooth scroll behavior +- [x] Add responsive styles for mobile +- [x] Ensure dark theme compatibility + +#### 2. HTML Changes +- [x] Restructure modal HTML + - [x] Wrap content in two-column container + - [x] Add navigation sidebar structure + - [x] Add navigation items for each section + - [x] Add ID anchors to each section +- [x] Update section grouping if needed + +#### 3. JavaScript Changes +- [x] Add navigation click handlers +- [x] Implement smooth scroll to section +- [x] Add scroll spy for active nav highlighting +- [x] Handle nav item click events +- [x] Update SettingsManager initialization + +#### 4. Translation Keys +- [x] Add translation keys for navigation groups + - [x] `settings.nav.general` + - [x] `settings.nav.interface` + - [x] `settings.nav.download` + - [x] `settings.nav.advanced` + +#### 4. Testing +- [x] Verify navigation clicks work +- [x] Verify active highlighting works +- [x] Verify smooth scrolling works +- [ ] Test on mobile viewport (deferred to final QA) +- [ ] Test dark/light theme (deferred to final QA) +- [x] Verify all existing settings work +- [x] Verify save/load functionality + +### Blockers +None currently + +### Notes +- Started implementation on 2026-02-23 +- Following existing design system and CSS variables + +--- + +## Phase 1: Section Collapse/Expand (P1) + +### Status: Planned + +### Tasks +- [ ] Add collapse/expand toggle to section headers +- [ ] Add chevron icon with rotation animation +- [ ] Implement localStorage for state persistence +- [ ] Add CSS animations for smooth transitions + +--- + +## Phase 2: Search Bar (P1) + +### Status: Planned + +### Tasks +- [ ] Add search input to header area +- [ ] Implement real-time filtering +- [ ] Add highlight for matched terms +- [ ] Handle empty search results + +--- + +## Phase 3: Visual Hierarchy (P2) + +### Status: Planned + +### Tasks +- [ ] Add accent border to section headers +- [ ] Bold setting labels +- [ ] Increase section spacing + +--- + +## Phase 4: Quick Actions (P3) + +### Status: Planned + +### Tasks +- [ ] Add reset to defaults button +- [ ] Add export config button +- [ ] Add import config button +- [ ] Implement corresponding functionality + +--- + +## Change Log + +### 2026-02-23 +- Created project documentation +- Started Phase 0 implementation +- Analyzed existing code structure +- Implemented two-column layout with left navigation sidebar +- Added CSS styles for navigation and responsive design +- Restructured HTML to support new layout +- Added JavaScript navigation functionality with scroll spy +- Added translation keys for navigation groups +- Synchronized translations across all language files +- Tested in browser - navigation working correctly + +--- + +## Testing Checklist + +### Functional Testing +- [ ] All settings save correctly +- [ ] All settings load correctly +- [ ] Navigation scrolls to correct section +- [ ] Active nav updates on scroll +- [ ] Mobile responsive layout + +### Visual Testing +- [ ] Design matches existing UI +- [ ] Dark theme looks correct +- [ ] Light theme looks correct +- [ ] Animations are smooth +- [ ] No layout shifts or jumps + +### Cross-browser Testing +- [ ] Chrome/Chromium +- [ ] Firefox +- [ ] Safari (if available) diff --git a/docs/ui-ux-optimization/settings-modal-optimization-proposal.md b/docs/ui-ux-optimization/settings-modal-optimization-proposal.md new file mode 100644 index 00000000..3d005bc2 --- /dev/null +++ b/docs/ui-ux-optimization/settings-modal-optimization-proposal.md @@ -0,0 +1,205 @@ +# Settings Modal UI/UX Optimization + +## Overview +随着Settings功能的不断增加,当前的单列表长页面设计已难以高效浏览和定位设置项。本方案旨在通过专业的UI/UX优化,在保持原有设计语言的前提下,大幅提升用户体验。 + +## Goals +1. **提升浏览效率**:用户能够快速定位和修改设置 +2. **保持设计一致性**:延续现有的颜色、间距、动画系统 +3. **渐进式增强**:分阶段实施,降低风险 +4. **向后兼容**:不影响现有功能逻辑 + +## Design Principles +- **贴近原有设计语言**:使用现有CSS变量和样式模式 +- **最小化风格改动**:在提升UX的同时保持视觉风格稳定 +- **渐进增强**:优先核心功能,次要功能逐步添加 + +--- + +## Optimization Phases + +### Phase 0: 左侧导航栏 + 两栏布局 (P0) +**Status**: In Progress + +#### Goals +- 解决核心痛点:设置项过多导致的浏览困难 +- 建立清晰的视觉层次和信息架构 + +#### Implementation Details + +##### Layout Changes +``` +┌─────────────────────────────────────────────────────────────┐ +│ Settings [×] │ +├──────────────┬──────────────────────────────────────────────┤ +│ NAVIGATION │ CONTENT │ +│ │ │ +│ ▶ General │ ┌─────────────────────────────────────────┐ │ +│ Interface │ │ Section: General │ │ +│ Download │ │ ┌─────────────────────────────────────┐ │ │ +│ Advanced │ │ │ Setting Item 1 │ │ │ +│ │ │ └─────────────────────────────────────┘ │ │ +│ │ │ ┌─────────────────────────────────────┐ │ │ +│ │ │ │ Setting Item 2 │ │ │ +│ │ │ └─────────────────────────────────────┘ │ │ +│ │ └─────────────────────────────────────────┘ │ +│ │ │ +│ │ ┌─────────────────────────────────────────┐ │ +│ │ │ Section: Interface │ │ +│ │ │ ... │ │ +│ │ └─────────────────────────────────────────┘ │ +└──────────────┴──────────────────────────────────────────────┘ +``` + +##### Technical Specifications +- **Modal Width**: 从700px扩展至950px +- **Left Sidebar**: 200px固定宽度,独立滚动 +- **Right Content**: flex: 1,独立滚动 +- **Height**: 固定80vh,确保内容可见 +- **Responsive**: 移动端自动切换为单栏布局 + +##### Navigation Items +基于当前Settings结构,导航项分为4组: + +1. **通用** (General) + - Language + - Storage Location + +2. **界面** (Interface) + - Layout Settings + - Video Settings + - Content Filtering + +3. **下载** (Download) + - Download Path Templates + - Example Images + - Update Flags + +4. **高级** (Advanced) + - Priority Tags + - Auto-organize + - Metadata Archive + - Proxy Settings + - Misc + +##### Interactive Features +- **点击导航**:平滑滚动到对应Section +- **当前高亮**:根据滚动位置高亮当前Section +- **平滑滚动**:使用scroll-behavior: smooth + +##### CSS Variables Usage +延续使用现有变量系统: +- `--lora-accent`: 高亮色 +- `--lora-border`: 边框色 +- `--card-bg`: 卡片背景 +- `--text-color`: 文字颜色 +- `--space-1` to `--space-4`: 间距系统 +- `--border-radius-xs/sm`: 圆角系统 + +--- + +### Phase 1: Section折叠/展开 (P1) +**Status**: Planned + +#### Goals +- 进一步减少视觉负担 +- 允许用户自定义信息密度 + +#### Implementation Details +- 点击Section标题折叠/展开 +- 添加chevron图标旋转动画 +- 记忆用户折叠状态(localStorage) + +--- + +### Phase 2: 顶部搜索栏 (P1) +**Status**: Planned + +#### Goals +- 快速定位特定设置项 +- 支持关键词搜索设置标签和描述 + +#### Implementation Details +- 实时过滤显示匹配项 +- 高亮匹配的关键词 +- 使用现有的text-input-wrapper样式 + +--- + +### Phase 3: 视觉层次优化 (P2) +**Status**: Planned + +#### Goals +- 提升可读性 +- 强化Section的视觉区分 + +#### Implementation Details +- Section标题左侧添加accent色边框 +- 设置项标签加粗处理 +- 增大Section间距 + +--- + +### Phase 4: 快速操作按钮 (P3) +**Status**: Planned + +#### Goals +- 增强功能完整性 +- 提供批量操作能力 + +#### Implementation Details +- 重置为默认按钮 +- 导出配置按钮 +- 导入配置按钮 + +--- + +## Files to Modify + +### Phase 0 Files +1. `static/css/components/modal/settings-modal.css` + - 新增两栏布局样式 + - 新增导航栏样式 + - 调整Modal尺寸 + +2. `templates/components/modals/settings_modal.html` + - 重构HTML结构为两栏布局 + - 添加导航列表 + - 为Section添加ID锚点 + +3. `static/js/managers/SettingsManager.js` + - 添加导航点击处理 + - 添加滚动监听高亮 + - 添加平滑滚动行为 + +--- + +## Success Criteria + +### Phase 0 +- [ ] Modal显示为两栏布局 +- [ ] 左侧导航可点击跳转 +- [ ] 当前Section在导航中高亮 +- [ ] 滚动时高亮状态同步更新 +- [ ] 移动端响应式正常 +- [ ] 所有现有功能正常工作 +- [ ] 设计风格与原有UI一致 + +--- + +## Timeline + +| Phase | Estimated Time | Status | +|-------|---------------|--------| +| P0 | 2-3 hours | In Progress | +| P1 | 1-2 hours | Planned | +| P2 | 1-2 hours | Planned | +| P3 | 1 hour | Planned | + +--- + +## Notes +- 所有修改优先使用现有CSS变量 +- 保持向后兼容,不破坏现有功能 +- 每次Phase完成后进行功能测试 +- 遵循现有代码风格和命名约定 diff --git a/locales/de.json b/locales/de.json index 7348568b..2a4c0200 100644 --- a/locales/de.json +++ b/locales/de.json @@ -269,6 +269,12 @@ "storageLocation": "Einstellungsort", "proxySettings": "Proxy-Einstellungen" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "Portabler Modus", "locationHelp": "Aktiviere, um settings.json im Repository zu belassen; deaktiviere, um es im Benutzerkonfigurationsordner zu speichern." diff --git a/locales/en.json b/locales/en.json index de1be8a7..9129c8b7 100644 --- a/locales/en.json +++ b/locales/en.json @@ -269,6 +269,12 @@ "storageLocation": "Settings Location", "proxySettings": "Proxy Settings" }, + "nav": { + "general": "General", + "interface": "Interface", + "download": "Download", + "advanced": "Advanced" + }, "storage": { "locationLabel": "Portable mode", "locationHelp": "Enable to keep settings.json inside the repository; disable to store it in your user config directory." diff --git a/locales/es.json b/locales/es.json index 17db9023..13662b7e 100644 --- a/locales/es.json +++ b/locales/es.json @@ -269,6 +269,12 @@ "storageLocation": "Ubicación de ajustes", "proxySettings": "Configuración de proxy" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "Modo portátil", "locationHelp": "Activa para mantener settings.json dentro del repositorio; desactívalo para guardarlo en tu directorio de configuración de usuario." diff --git a/locales/fr.json b/locales/fr.json index 1f13574b..89f1315c 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -269,6 +269,12 @@ "storageLocation": "Emplacement des paramètres", "proxySettings": "Paramètres du proxy" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "Mode portable", "locationHelp": "Activez pour garder settings.json dans le dépôt ; désactivez pour le placer dans votre dossier de configuration utilisateur." diff --git a/locales/he.json b/locales/he.json index 99ff5d72..01ad3ed0 100644 --- a/locales/he.json +++ b/locales/he.json @@ -269,6 +269,12 @@ "storageLocation": "מיקום ההגדרות", "proxySettings": "הגדרות פרוקסי" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "מצב נייד", "locationHelp": "הפעל כדי לשמור את settings.json בתוך המאגר; בטל כדי לשמור אותו בתיקיית ההגדרות של המשתמש." diff --git a/locales/ja.json b/locales/ja.json index 86ac9664..dd7004d1 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -269,6 +269,12 @@ "storageLocation": "設定の場所", "proxySettings": "プロキシ設定" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "ポータブルモード", "locationHelp": "有効にすると settings.json をリポジトリ内に保持し、無効にするとユーザー設定ディレクトリに格納します。" diff --git a/locales/ko.json b/locales/ko.json index 09d544c6..d3ffcdde 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -269,6 +269,12 @@ "storageLocation": "설정 위치", "proxySettings": "프록시 설정" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "휴대용 모드", "locationHelp": "활성화하면 settings.json을 리포지토리에 유지하고, 비활성화하면 사용자 구성 디렉터리에 저장합니다." @@ -1624,4 +1630,4 @@ "retry": "다시 시도" } } -} \ No newline at end of file +} diff --git a/locales/ru.json b/locales/ru.json index a9539df5..29788e47 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -269,6 +269,12 @@ "storageLocation": "Расположение настроек", "proxySettings": "Настройки прокси" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "Портативный режим", "locationHelp": "Включите, чтобы хранить settings.json в репозитории; выключите, чтобы сохранить его в папке конфигурации пользователя." diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 7ff14955..e4346b84 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -269,6 +269,12 @@ "storageLocation": "设置位置", "proxySettings": "代理设置" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "便携模式", "locationHelp": "开启可将 settings.json 保存在仓库中;关闭则保存在用户配置目录。" diff --git a/locales/zh-TW.json b/locales/zh-TW.json index bd599fcc..ebb43375 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -269,6 +269,12 @@ "storageLocation": "設定位置", "proxySettings": "代理設定" }, + "nav": { + "general": "[TODO: Translate] General", + "interface": "[TODO: Translate] Interface", + "download": "[TODO: Translate] Download", + "advanced": "[TODO: Translate] Advanced" + }, "storage": { "locationLabel": "可攜式模式", "locationHelp": "啟用可將 settings.json 保存在儲存庫中;停用則保存在使用者設定目錄。" diff --git a/static/css/components/modal/settings-modal.css b/static/css/components/modal/settings-modal.css index de1c5ef9..54bcfad2 100644 --- a/static/css/components/modal/settings-modal.css +++ b/static/css/components/modal/settings-modal.css @@ -20,7 +20,101 @@ } .settings-modal { - max-width: 700px; /* Further increased from 600px for more space */ + max-width: 950px; + width: 90vw; + max-height: 85vh; + display: flex; + flex-direction: column; +} + +.settings-modal .modal-body { + display: flex; + flex-direction: row; + flex: 1; + overflow: hidden; + min-height: 0; +} + +/* Navigation Sidebar */ +.settings-nav { + width: 200px; + flex-shrink: 0; + border-right: 1px solid var(--lora-border); + padding: var(--space-2); + overflow-y: auto; + background: rgba(0, 0, 0, 0.02); +} + +[data-theme="dark"] .settings-nav { + background: rgba(255, 255, 255, 0.02); +} + +.settings-nav-title { + font-size: 0.85em; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--text-color); + opacity: 0.6; + margin-bottom: var(--space-2); + padding: 0 var(--space-1); +} + +.settings-nav-list { + list-style: none; + padding: 0; + margin: 0; +} + +.settings-nav-group { + margin-bottom: var(--space-2); +} + +.settings-nav-group-title { + font-size: 0.8em; + font-weight: 500; + color: var(--text-color); + opacity: 0.8; + padding: var(--space-1) var(--space-1); + margin-bottom: var(--space-1); +} + +.settings-nav-item { + display: block; + width: 100%; + padding: 8px 12px; + border: none; + background: transparent; + color: var(--text-color); + text-align: left; + font-size: 0.9em; + cursor: pointer; + border-radius: var(--border-radius-xs); + transition: all 0.2s ease; + margin-bottom: 2px; +} + +.settings-nav-item:hover { + background: rgba(var(--lora-accent-rgb, 79, 70, 229), 0.1); + color: var(--lora-accent); +} + +.settings-nav-item.active { + background: var(--lora-accent); + color: white; + font-weight: 500; +} + +/* Content Area */ +.settings-content { + flex: 1; + overflow-y: auto; + padding: var(--space-3); + scroll-behavior: smooth; +} + +.settings-content .settings-form { + padding-bottom: var(--space-4); } .settings-header { @@ -701,6 +795,55 @@ input:checked + .toggle-slider:before { } } +/* Responsive: Mobile - Single column layout */ +@media (max-width: 768px) { + .settings-modal { + width: 95vw; + max-height: 90vh; + } + + .settings-modal .modal-body { + flex-direction: column; + } + + .settings-nav { + width: 100%; + max-height: 200px; + border-right: none; + border-bottom: 1px solid var(--lora-border); + padding: var(--space-1); + } + + .settings-nav-list { + display: flex; + flex-wrap: wrap; + gap: var(--space-1); + } + + .settings-nav-group { + display: flex; + flex-wrap: wrap; + gap: var(--space-1); + margin-bottom: 0; + } + + .settings-nav-group-title { + display: none; + } + + .settings-nav-item { + width: auto; + white-space: nowrap; + font-size: 0.85em; + padding: 6px 10px; + margin-bottom: 0; + } + + .settings-content { + padding: var(--space-2); + } +} + /* Dark theme specific adjustments */ [data-theme="dark"] .base-model-select, [data-theme="dark"] .path-value-input { diff --git a/static/js/managers/SettingsManager.js b/static/js/managers/SettingsManager.js index 2c34d726..ad1e36b5 100644 --- a/static/js/managers/SettingsManager.js +++ b/static/js/managers/SettingsManager.js @@ -364,10 +364,81 @@ export class SettingsManager { } this.setupPriorityTagInputs(); + this.initializeNavigation(); this.initialized = true; } + initializeNavigation() { + const settingsContent = document.querySelector('.settings-content'); + const navItems = document.querySelectorAll('.settings-nav-item'); + + if (!settingsContent || navItems.length === 0) return; + + // Handle navigation item clicks + navItems.forEach(item => { + item.addEventListener('click', (e) => { + const targetId = item.dataset.target; + if (!targetId) return; + + const targetSection = document.getElementById(targetId); + if (targetSection) { + targetSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + + // Update active state + navItems.forEach(nav => nav.classList.remove('active')); + item.classList.add('active'); + }); + }); + + // Setup scroll spy + const sections = document.querySelectorAll('.settings-section, .setting-item[id^="section-"]'); + + const updateActiveNav = () => { + const scrollTop = settingsContent.scrollTop; + const contentHeight = settingsContent.clientHeight; + + let currentSection = null; + let minDistance = Infinity; + + sections.forEach(section => { + const sectionTop = section.offsetTop - settingsContent.offsetTop; + const distance = Math.abs(sectionTop - scrollTop); + + if (distance < minDistance) { + minDistance = distance; + currentSection = section; + } + }); + + if (currentSection) { + const sectionId = currentSection.id; + navItems.forEach(item => { + item.classList.remove('active'); + if (item.dataset.target === sectionId) { + item.classList.add('active'); + } + }); + } + }; + + // Use requestAnimationFrame for performance + let ticking = false; + settingsContent.addEventListener('scroll', () => { + if (!ticking) { + window.requestAnimationFrame(() => { + updateActiveNav(); + ticking = false; + }); + ticking = true; + } + }); + + // Initial update + updateActiveNav(); + } + async openSettingsFileLocation() { try { const response = await fetch('/api/lm/settings/open-location', { diff --git a/templates/components/modals/settings_modal.html b/templates/components/modals/settings_modal.html index 00a5b1db..78f4b726 100644 --- a/templates/components/modals/settings_modal.html +++ b/templates/components/modals/settings_modal.html @@ -12,8 +12,44 @@ -
-
+