diff --git a/.changeset/funny-jeans-attack.md b/.changeset/funny-jeans-attack.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/funny-jeans-attack.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/server/public/chat.html b/server/public/chat.html index 4c8cac36b4..590d19713b 100644 --- a/server/public/chat.html +++ b/server/public/chat.html @@ -644,104 +644,301 @@ } } - /* Thread Sidebar */ + /* Chat Sidebar - Vertical Tab Layout */ .page-layout { display: flex; flex: 1; overflow: hidden; } - .thread-sidebar { + .chat-sidebar { width: 280px; border-right: 1px solid var(--color-border); background: var(--color-bg-card); - display: none; + display: flex; flex-direction: column; flex-shrink: 0; + height: 100%; } - .thread-sidebar.visible { - display: flex; + /* Hide sidebar for unauthenticated users */ + .chat-sidebar:not(.visible) { + display: none; } - .thread-sidebar-header { - padding: 16px; + /* Sidebar navigation tabs */ + .sidebar-nav { + padding: 12px; border-bottom: 1px solid var(--color-border); + } + + .sidebar-tab { + width: 100%; display: flex; align-items: center; - justify-content: space-between; + gap: 10px; + padding: 10px 12px; + border: none; + border-radius: var(--radius-lg); + background: transparent; + color: var(--color-text-secondary); + font-size: 14px; + font-family: inherit; + cursor: pointer; + transition: all 0.15s; + text-align: left; } - .thread-sidebar-header h3 { - font-size: 14px; - font-weight: 600; - color: var(--color-text-heading); - margin: 0; + .sidebar-tab:hover { + background: var(--color-bg-subtle); + color: var(--color-text); + } + + .sidebar-tab.active { + background: var(--color-primary-50); + color: var(--color-brand); + font-weight: 500; } - .new-chat-btn { + .sidebar-tab svg { + width: 18px; + height: 18px; + flex-shrink: 0; + } + + .sidebar-tab--new { background: var(--color-brand); color: white; + margin-top: 8px; + } + + .sidebar-tab--new:hover { + background: var(--color-brand-hover); + color: white; + } + + /* Sidebar sections */ + .sidebar-section { + display: flex; + flex-direction: column; + } + + .sidebar-section-header { + padding: 12px 16px 8px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--color-text-muted); + display: flex; + align-items: center; + justify-content: space-between; + } + + .sidebar-section-header button { + background: none; border: none; - padding: 6px 12px; - border-radius: 6px; - font-size: 12px; + padding: 0; cursor: pointer; + color: var(--color-text-muted); display: flex; align-items: center; gap: 4px; } - .new-chat-btn:hover { - background: var(--color-brand-hover); + .sidebar-section-header button:hover { + color: var(--color-text); } - .thread-list { - flex: 1; - overflow-y: auto; - padding: 8px; + .sidebar-section-header .badge { + background: var(--color-bg-subtle); + color: var(--color-text-muted); + font-size: 10px; + padding: 2px 6px; + border-radius: 10px; + font-weight: 500; } - .thread-item { - padding: 12px; - border-radius: 8px; + .sidebar-section-header svg { + width: 14px; + height: 14px; + transition: transform 0.2s; + } + + .sidebar-section--collapsed .sidebar-section-header svg { + transform: rotate(-90deg); + } + + .sidebar-section--collapsed .sidebar-section-content { + display: none; + } + + /* Active tabs list */ + .sidebar-active-list { + padding: 0 8px 8px; + } + + .sidebar-active-list:empty::after { + content: 'No active chats'; + display: block; + padding: 12px 8px; + text-align: center; + color: var(--color-text-muted); + font-size: 12px; + } + + /* Tab items in sidebar */ + .tab-item { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 12px; + border-radius: var(--radius-lg); cursor: pointer; - margin-bottom: 4px; transition: background 0.15s; - border: 1px solid transparent; + position: relative; } - .thread-item:hover { + .tab-item:hover { background: var(--color-bg-subtle); } - .thread-item.active { + .tab-item.active { background: var(--color-primary-50); - border-color: var(--color-primary-200); } - .thread-item-title { + .tab-item-indicator { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; + } + + .tab-item-indicator--thinking { + background: var(--color-warning-500); + animation: pulse 1.5s ease-in-out infinite; + } + + .tab-item-indicator--ready { + background: var(--color-success-500); + } + + .tab-item-indicator--idle { + background: var(--color-gray-300); + } + + @keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.6; transform: scale(0.85); } + } + + .tab-item-content { + flex: 1; + min-width: 0; + } + + .tab-item-title { font-size: 13px; font-weight: 500; color: var(--color-text); - margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - .thread-item-preview { - font-size: 12px; + .tab-item-meta { + font-size: 11px; + color: var(--color-text-muted); + margin-top: 2px; + } + + .tab-item-close { + width: 20px; + height: 20px; + border: none; + background: transparent; color: var(--color-text-muted); + cursor: pointer; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.15s, background 0.15s; + } + + .tab-item:hover .tab-item-close { + opacity: 1; + } + + .tab-item-close:hover { + background: var(--color-bg-subtle); + color: var(--color-text); + } + + .tab-item-close svg { + width: 14px; + height: 14px; + } + + .tab-item-badge { + position: absolute; + top: 6px; + right: 6px; + min-width: 18px; + height: 18px; + background: var(--color-brand); + color: white; + font-size: 10px; + font-weight: 600; + border-radius: 9px; + display: flex; + align-items: center; + justify-content: center; + padding: 0 5px; + } + + /* History section */ + .sidebar-history { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + border-top: 1px solid var(--color-border); + } + + .sidebar-history-list { + flex: 1; + overflow-y: auto; + padding: 0 8px 8px; + } + + .history-item { + padding: 10px 12px; + border-radius: var(--radius-lg); + cursor: pointer; + transition: background 0.15s; + } + + .history-item:hover { + background: var(--color-bg-subtle); + } + + .history-item-title { + font-size: 13px; + color: var(--color-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + display: flex; + align-items: center; + gap: 6px; } - .thread-item-meta { + .history-item-meta { font-size: 11px; color: var(--color-text-muted); - margin-top: 4px; + margin-top: 2px; display: flex; justify-content: space-between; } @@ -755,7 +952,6 @@ border-radius: 4px; background: var(--color-bg-subtle); color: var(--color-text-muted); - margin-left: 6px; vertical-align: middle; } @@ -769,7 +965,15 @@ height: 10px; } - .thread-toggle-btn { + .history-empty { + text-align: center; + padding: 24px 16px; + color: var(--color-text-muted); + font-size: 13px; + } + + /* Mobile sidebar toggle */ + .sidebar-toggle-btn { position: fixed; left: 16px; bottom: calc(100px + env(safe-area-inset-bottom, 0px)); @@ -787,29 +991,27 @@ box-shadow: var(--shadow-sm); } - /* In native app mode, position closer to bottom since there's no status bar */ - body.native-app .thread-toggle-btn { + body.native-app .sidebar-toggle-btn { bottom: calc(80px + env(safe-area-inset-bottom, 0px)); } - .thread-toggle-btn:hover { + .sidebar-toggle-btn:hover { background: var(--color-bg-subtle); border-color: var(--color-brand); } - .thread-toggle-btn.visible { - display: flex; - } - - .thread-empty { - text-align: center; - padding: 24px 16px; - color: var(--color-text-muted); - font-size: 13px; + .sidebar-toggle-btn .badge { + background: var(--color-brand); + color: white; + font-size: 10px; + padding: 2px 6px; + border-radius: 10px; + font-weight: 600; } + /* Show toggle button on mobile for authenticated users */ @media (max-width: 768px) { - .thread-sidebar { + .chat-sidebar.visible { position: fixed; left: 0; top: 0; @@ -818,7 +1020,19 @@ box-shadow: var(--shadow-lg); } - .thread-sidebar-overlay { + .chat-sidebar.visible:not(.mobile-open) { + display: none; + } + + .chat-sidebar.visible.mobile-open { + display: flex; + } + + .sidebar-toggle-btn.visible { + display: flex; + } + + .sidebar-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.3); @@ -826,11 +1040,22 @@ display: none; } - .thread-sidebar-overlay.visible { + .sidebar-overlay.visible { display: block; } } + /* Desktop: always show sidebar for authenticated users */ + @media (min-width: 769px) { + .chat-sidebar.visible { + display: flex; + } + + .sidebar-toggle-btn { + display: none !important; + } + } + /* Native app mode - hide site nav, chat header, and status indicator (app provides its own) */ body.native-app #adcp-nav, body.native-app .chat-header, @@ -845,38 +1070,97 @@ body.native-app .messages-container { padding-top: 16px; } + + /* Native app mode - sidebar adjustments for safe areas */ + body.native-app .chat-sidebar { + padding-top: env(safe-area-inset-top, 0px); + padding-bottom: env(safe-area-inset-bottom, 0px); + } + + body.native-app .chat-sidebar .sidebar-nav { + padding-top: calc(12px + env(safe-area-inset-top, 0px)); + } + + /* Native app mobile - ensure sidebar works with safe areas */ + @media (max-width: 768px) { + body.native-app .chat-sidebar.visible { + padding-left: env(safe-area-inset-left, 0px); + } + + body.native-app .sidebar-overlay { + /* Extend overlay behind safe areas */ + top: calc(-1 * env(safe-area-inset-top, 0px)); + left: calc(-1 * env(safe-area-inset-left, 0px)); + right: calc(-1 * env(safe-area-inset-right, 0px)); + bottom: calc(-1 * env(safe-area-inset-bottom, 0px)); + } + } + + /* Native app mode - adjust input area for safe areas */ + body.native-app .input-container { + padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px)); + }
- -