import { DeesElement, property, html, customElement, type TemplateResult, cssManager, css, unsafeCSS, state, } from '@design.estate/dees-element'; // Import design tokens import { colors, bdTheme } from './00colors.js'; import { spacing, radius, shadows, transitions } from './00tokens.js'; import { fontFamilies, typography } from './00fonts.js'; // Types export interface IConversation { id: string; title: string; lastMessage: string; time: string; unread?: boolean; avatar?: string; } declare global { interface HTMLElementTagNameMap { 'sio-conversation-selector': SioConversationSelector; } } @customElement('sio-conversation-selector') export class SioConversationSelector extends DeesElement { public static demo = () => html` `; @property({ type: Array }) public conversations: IConversation[] = []; @property({ type: String }) public selectedConversationId: string | null = null; @state() private searchQuery: string = ''; public static styles = [ cssManager.defaultStyles, css` :host { display: flex; flex-direction: column; height: 100%; background: ${bdTheme('card')}; border-right: 1px solid ${bdTheme('border')}; font-family: ${unsafeCSS(fontFamilies.sans)}; } .header { padding: ${unsafeCSS(spacing[4])}; border-bottom: 1px solid ${bdTheme('border')}; } .title { font-size: 1.125rem; line-height: 1.5; font-weight: 600; margin: 0 0 ${unsafeCSS(spacing[3])} 0; color: ${bdTheme('foreground')}; } .search-box { position: relative; } .search-input { width: 100%; padding: ${unsafeCSS(spacing[2])} ${unsafeCSS(spacing[10])} ${unsafeCSS(spacing[2])} ${unsafeCSS(spacing[3])}; background: ${bdTheme('muted')}; border: 1px solid ${bdTheme('border')}; border-radius: ${unsafeCSS(radius.md)}; font-size: 14px; color: ${bdTheme('foreground')}; outline: none; transition: ${unsafeCSS(transitions.all)}; font-family: ${unsafeCSS(fontFamilies.sans)}; } .search-input::placeholder { color: ${bdTheme('mutedForeground')}; } .search-input:focus { background: ${bdTheme('background')}; border-color: ${bdTheme('ring')}; } .search-icon { position: absolute; right: ${unsafeCSS(spacing[3])}; top: 50%; transform: translateY(-50%); color: ${bdTheme('mutedForeground')}; } .conversation-list { flex: 1; overflow-y: auto; padding: ${unsafeCSS(spacing[2])}; } .conversation-item { padding: ${unsafeCSS(spacing[3])}; margin-bottom: ${unsafeCSS(spacing[2])}; background: ${bdTheme('background')}; border: 1px solid ${bdTheme('border')}; border-radius: ${unsafeCSS(radius.md)}; cursor: pointer; transition: ${unsafeCSS(transitions.all)}; } .conversation-item:hover { background: ${bdTheme('accent')}; } .conversation-item.selected { background: ${bdTheme('accent')}; border-color: ${bdTheme('primary')}; } .conversation-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: ${unsafeCSS(spacing[1])}; } .conversation-title { font-weight: 600; color: ${bdTheme('foreground')}; display: flex; align-items: center; gap: ${unsafeCSS(spacing[2])}; } .conversation-time { font-size: 0.75rem; line-height: 1.5; color: ${bdTheme('mutedForeground')}; } .conversation-preview { font-size: 0.875rem; line-height: 1.5; color: ${bdTheme('mutedForeground')}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .unread-dot { display: inline-block; width: 8px; height: 8px; background: ${bdTheme('primary')}; border-radius: 50%; } .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; padding: ${unsafeCSS(spacing[4])}; text-align: center; color: ${bdTheme('mutedForeground')}; gap: ${unsafeCSS(spacing[3])}; } .empty-icon { font-size: 48px; opacity: 0.5; } /* Scrollbar styling */ .conversation-list::-webkit-scrollbar { width: 6px; } .conversation-list::-webkit-scrollbar-track { background: transparent; } .conversation-list::-webkit-scrollbar-thumb { background: ${bdTheme('border')}; border-radius: 3px; } .conversation-list::-webkit-scrollbar-thumb:hover { background: ${bdTheme('mutedForeground')}; } `, ]; public render(): TemplateResult { const filteredConversations = this.conversations.filter(conv => conv.title.toLowerCase().includes(this.searchQuery.toLowerCase()) || conv.lastMessage.toLowerCase().includes(this.searchQuery.toLowerCase()) ); return html`

Messages

${filteredConversations.length > 0 ? html`
${filteredConversations.map(conv => html`
this.selectConversation(conv)} >
${conv.title} ${conv.unread ? html`` : ''} ${conv.time}
${conv.lastMessage}
`)}
` : html`

${this.searchQuery ? 'No matching conversations' : 'No conversations yet'}

${this.searchQuery ? 'Try a different search term' : 'Start a new conversation to get started'}

`} `; } private selectConversation(conversation: IConversation) { this.selectedConversationId = conversation.id; // Dispatch event for parent components this.dispatchEvent(new CustomEvent('conversation-selected', { detail: { conversation }, bubbles: true, composed: true })); } }