This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/src/js/sw/surfaces/chat/sidebar.js
gobha 8d8a118232 Changeset 0.37.10 (#222)
Co-authored-by: gobha <jasafpro@gmail.com>
Co-committed-by: gobha <jasafpro@gmail.com>
2026-03-21 23:39:23 +00:00

110 lines
4.4 KiB
JavaScript

// ==========================================
// Chat Surface — Sidebar Component
// ==========================================
// Search bar, new chat, channels section, chats section with folders.
// Footer has UserMenu (avatar) — all navigation lives in the menu flyout.
import { SidebarChannels } from './sidebar-channels.js';
import { SidebarChats } from './sidebar-chats.js';
import { UserMenu } from '../../shell/user-menu.js';
const html = window.html;
const { useCallback } = window.hooks;
const PLUS_SVG = html`
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"/>
<line x1="5" y1="12" x2="19" y2="12"/>
</svg>`;
const SEARCH_SVG = html`
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"/>
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
</svg>`;
const COLLAPSE_SVG = html`
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2"/>
<line x1="9" y1="3" x2="9" y2="21"/>
</svg>`;
/**
* @param {{
* sidebar: ReturnType<import('./use-sidebar.js').useSidebar>,
* activeId: string|null,
* onSelectChat: (id: string) => void,
* onSelectChannel: (id: string) => void,
* onNewChat: () => void,
* onCollapse: () => void,
* }} props
*/
export function Sidebar({ sidebar, activeId, onSelectChat, onSelectChannel, onNewChat, onCollapse }) {
const _onSearch = useCallback((e) => {
sidebar.setSearch(e.target.value);
}, [sidebar.setSearch]);
return html`
<div class="sw-chat-surface__sidebar" role="navigation" aria-label="Chat sidebar">
${/* Header: new chat + collapse */''}
<div class="sw-chat-surface__sidebar-header">
<button class="sw-chat-surface__new-chat-btn"
onClick=${onNewChat}
title="New chat"
aria-label="Start new chat">
${PLUS_SVG}
<span>New Chat</span>
</button>
<button class="sw-chat-surface__collapse-btn"
onClick=${onCollapse}
title="Collapse sidebar"
aria-label="Collapse sidebar">
${COLLAPSE_SVG}
</button>
</div>
${/* Search */''}
<div class="sw-chat-surface__search-wrap">
<span class="sw-chat-surface__search-icon">${SEARCH_SVG}</span>
<input class="sw-chat-surface__search"
type="text"
placeholder="Search\u2026"
value=${sidebar.search}
onInput=${_onSearch}
aria-label="Search chats and channels" />
</div>
${/* Scrollable content */''}
<div class="sw-chat-surface__sidebar-body">
<${SidebarChannels}
channels=${sidebar.channels}
activeId=${activeId}
collapsed=${sidebar.collapsed.channels}
onToggle=${() => sidebar.toggleCollapsed('channels')}
onSelect=${onSelectChannel} />
<${SidebarChats}
chatsByFolder=${sidebar.chatsByFolder}
folders=${sidebar.folders}
activeId=${activeId}
collapsed=${sidebar.collapsed.chats}
onToggle=${() => sidebar.toggleCollapsed('chats')}
onSelect=${onSelectChat}
onRename=${sidebar.renameChat}
onDelete=${sidebar.deleteChat}
onMoveToFolder=${sidebar.moveToFolder}
onCreateFolder=${sidebar.createFolder}
onRenameFolder=${sidebar.renameFolder}
onDeleteFolder=${sidebar.deleteFolder} />
</div>
${/* Footer: UserMenu only */''}
<div class="sw-chat-surface__sidebar-footer">
<${UserMenu} placement="up-right" />
</div>
</div>`;
}