Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/components/sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,37 @@ function _checkMultiInstances(el) {
}).catch(() => {})
}

const LS_SIDEBAR_COLLAPSED = 'clawpanel_sidebar_collapsed'

function _isDesktopSidebarCollapsed() {
try { return localStorage.getItem(LS_SIDEBAR_COLLAPSED) === '1' } catch { return false }
}

function _setDesktopSidebarCollapsed(collapsed) {
try { localStorage.setItem(LS_SIDEBAR_COLLAPSED, collapsed ? '1' : '0') } catch {}
const sidebar = document.getElementById('sidebar')
if (sidebar) {
sidebar.classList.toggle('sidebar-collapsed', !!collapsed)
}
const btn = document.getElementById('btn-sidebar-collapse')
if (btn) btn.textContent = collapsed ? '»' : '«'
}

export function renderSidebar(el) {
const current = getCurrentRoute()

const inst = getActiveInstance()
const isLocal = inst.type === 'local'
const showSwitcher = !isLocal || _hasMultipleInstances

const collapsed = _isDesktopSidebarCollapsed()
let html = `
<div class="sidebar-header">
<div class="sidebar-logo">
<img src="/images/logo.png" alt="ClawPanel">
</div>
<span class="sidebar-title">ClawPanel</span>
<button class="sidebar-collapse-btn" id="btn-sidebar-collapse" title="折叠/展开">${collapsed ? '»' : '«'}</button>
<button class="sidebar-close-btn" id="btn-sidebar-close" title="关闭菜单">&times;</button>
</div>
${showSwitcher ? `<div class="instance-switcher" id="instance-switcher">
Expand Down Expand Up @@ -172,6 +190,9 @@ export function renderSidebar(el) {

el.innerHTML = html

// 应用折叠态(桌面端)
_setDesktopSidebarCollapsed(collapsed)

// 首次渲染时异步检测多实例
if (!_delegated) _checkMultiInstances(el)

Expand All @@ -191,6 +212,13 @@ export function renderSidebar(el) {
_closeMobileSidebar()
return
}
// 侧边栏折叠
const collapseBtn = e.target.closest('#btn-sidebar-collapse')
if (collapseBtn) {
_setDesktopSidebarCollapsed(!_isDesktopSidebarCollapsed())
// 不需要整体重渲染
return
}
// 主题切换
const themeBtn = e.target.closest('#btn-theme-toggle')
if (themeBtn) {
Expand Down
10 changes: 6 additions & 4 deletions src/pages/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,20 @@ export async function render() {
<div class="chat-sidebar" id="chat-sidebar">
<div class="chat-sidebar-header">
<span>会话列表</span>
<button class="chat-sidebar-btn" id="btn-new-session" title="新建会话">
<div class="chat-sidebar-header-actions">
<button class="chat-sidebar-btn" id="btn-toggle-sidebar" title="会话列表">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<button class="chat-sidebar-btn" id="btn-new-session" title="新建会话">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
</button>
</div>
</div>
<div class="chat-session-list" id="chat-session-list"></div>
</div>
<div class="chat-main">
<div class="chat-header">
<div class="chat-status">
<button class="chat-toggle-sidebar" id="btn-toggle-sidebar" title="会话列表">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
</button>
<span class="status-dot" id="chat-status-dot"></span>
<span class="chat-title" id="chat-title">聊天</span>
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/style/chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@
font-weight: 600;
color: var(--text-secondary);
border-bottom: 1px solid var(--border);
gap: 8px;
}

.chat-sidebar-header-actions {
display: flex;
align-items: center;
gap: 6px;
}

.chat-sidebar-btn {
Expand Down
53 changes: 52 additions & 1 deletion src/style/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,38 @@
overflow: hidden;
}

/* 桌面端折叠态 */
#sidebar.sidebar-collapsed {
width: var(--sidebar-collapsed);
}
#sidebar.sidebar-collapsed .sidebar-title,
#sidebar.sidebar-collapsed .nav-section-title,
#sidebar.sidebar-collapsed .nav-item span,
#sidebar.sidebar-collapsed .sidebar-meta,
#sidebar.sidebar-collapsed .instance-switcher {
display: none;
}
#sidebar.sidebar-collapsed .sidebar-header {
justify-content: center;
}
#sidebar.sidebar-collapsed .nav-item {
justify-content: center;
padding-left: 0;
padding-right: 0;
}
#sidebar.sidebar-collapsed .nav-item svg {
opacity: 0.9;
}
#sidebar.sidebar-collapsed .sidebar-footer {
padding: var(--space-sm) 6px;
}
#sidebar.sidebar-collapsed #btn-theme-toggle {
justify-content: center;
}
#sidebar.sidebar-collapsed #btn-theme-toggle span {
display: none;
}

.sidebar-header {
padding: var(--space-lg) var(--space-lg);
display: flex;
Expand Down Expand Up @@ -475,9 +507,25 @@
font-weight: 600;
color: var(--text-primary);
}
.sidebar-collapse-btn {
margin-left: auto;
font-size: 14px;
color: var(--text-secondary);
background: none;
border: 1px solid var(--border-secondary);
cursor: pointer;
padding: 2px 8px;
border-radius: 8px;
line-height: 1.2;
}
.sidebar-collapse-btn:hover {
color: var(--text-primary);
background: var(--bg-glass-hover);
}

.sidebar-close-btn {
display: none;
margin-left: auto;
margin-left: 6px;
font-size: 22px;
color: var(--text-tertiary);
background: none;
Expand Down Expand Up @@ -511,6 +559,9 @@
.mobile-topbar {
display: flex;
}
.sidebar-collapse-btn {
display: none;
}
.sidebar-close-btn {
display: block;
}
Expand Down