/** * ds-ai-chat-sidebar.js * AI Chat Sidebar wrapper component * Wraps ds-chat-panel with collapse/expand toggle and context binding * MVP2: Right sidebar integrated with 3-column layout */ import contextStore from '../../stores/context-store.js'; import { useUserStore } from '../../stores/user-store.js'; class DSAiChatSidebar extends HTMLElement { constructor() { super(); this.userStore = useUserStore(); const preferences = this.userStore.getPreferences(); this.isCollapsed = preferences.chatCollapsedState !== false; // Default to collapsed this.currentProject = null; this.currentTeam = null; this.currentPage = null; } connectedCallback() { this.render(); this.setupEventListeners(); this.initializeContextSubscriptions(); } initializeContextSubscriptions() { // Subscribe to context changes to update chat panel context this.unsubscribe = contextStore.subscribe(({ state }) => { this.currentProject = state.project; this.currentTeam = state.team; this.currentPage = state.page; // Update chat panel with current context const chatPanel = this.querySelector('ds-chat-panel'); if (chatPanel && chatPanel.setContext) { chatPanel.setContext({ project: this.currentProject, team: this.currentTeam, page: this.currentPage }); } }); // Get initial context const context = contextStore.getState(); if (context) { this.currentProject = context.currentProject || context.project || null; this.currentTeam = context.teamId || context.team || null; this.currentPage = context.page || null; } } render() { const buttonClass = this.isCollapsed ? 'rotating' : ''; this.innerHTML = ` `; } async setupEventListeners() { // Handle both expanded and collapsed toggle buttons const toggleBtn = this.querySelector('#toggle-collapse-btn'); const toggleBtnCollapsed = this.querySelector('#toggle-collapse-btn-collapsed'); const attachToggleListener = (btn) => { if (btn) { btn.addEventListener('click', () => { this.toggleCollapse(); }); btn.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); btn.click(); } }); } }; attachToggleListener(toggleBtn); attachToggleListener(toggleBtnCollapsed); // Hydrate chat panel on first connection const chatContainer = this.querySelector('#chat-panel-container'); if (chatContainer && chatContainer.children.length === 0) { try { // Import component registry to load chat panel const { hydrateComponent } = await import('../../config/component-registry.js'); await hydrateComponent('ds-chat-panel', chatContainer); console.log('[DSAiChatSidebar] Chat panel loaded'); // Set initial context on chat panel const chatPanel = chatContainer.querySelector('ds-chat-panel'); if (chatPanel && chatPanel.setContext) { chatPanel.setContext({ project: this.currentProject, team: this.currentTeam, page: this.currentPage }); } } catch (error) { console.error('[DSAiChatSidebar] Failed to load chat panel:', error); chatContainer.innerHTML = `
Failed to load chat panel
`; } } } toggleCollapse() { this.isCollapsed = !this.isCollapsed; // Persist chat collapsed state to userStore this.userStore.updatePreferences({ chatCollapsedState: this.isCollapsed }); // Update CSS class for smooth CSS transition (avoid re-render for better UX) if (this.isCollapsed) { this.classList.add('collapsed'); } else { this.classList.remove('collapsed'); } // Update button classes for rotation animation const btns = this.querySelectorAll('.ai-chat-toggle-btn'); btns.forEach(btn => { if (this.isCollapsed) { btn.classList.add('rotating'); } else { btn.classList.remove('rotating'); } btn.setAttribute('aria-expanded', String(!this.isCollapsed)); }); // Update header and content visibility with inline styles const header = this.querySelector('[style*="padding: 12px"]'); const content = this.querySelector('.chat-content'); if (header) { if (this.isCollapsed) { header.style.display = 'none'; } else { header.style.display = 'flex'; } } if (content) { if (this.isCollapsed) { content.style.display = 'none'; } else { content.style.display = 'flex'; } } // Toggle collapsed button visibility let collapsedBtn = this.querySelector('#toggle-collapse-btn-collapsed'); if (!collapsedBtn && this.isCollapsed) { // Create the collapsed button if needed this.render(); this.setupEventListeners(); } else if (collapsedBtn && !this.isCollapsed) { // Remove the collapsed button if needed this.render(); this.setupEventListeners(); } // Dispatch event for layout adjustment this.dispatchEvent(new CustomEvent('chat-sidebar-toggled', { detail: { isCollapsed: this.isCollapsed }, bubbles: true, composed: true })); } disconnectedCallback() { if (this.unsubscribe) { this.unsubscribe(); } } } customElements.define('ds-ai-chat-sidebar', DSAiChatSidebar);