@social.io/catalog 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.smartconfig.json +51 -0
  2. package/dist_bundle/bundle.js +5450 -3267
  3. package/dist_ts_web/00_commitinfo_data.js +3 -3
  4. package/dist_ts_web/elements/index.d.ts +20 -3
  5. package/dist_ts_web/elements/index.js +27 -7
  6. package/dist_ts_web/elements/sio-ai-card.d.ts +39 -0
  7. package/dist_ts_web/elements/sio-ai-card.js +229 -0
  8. package/dist_ts_web/elements/sio-avatar.d.ts +46 -0
  9. package/dist_ts_web/elements/sio-avatar.js +379 -0
  10. package/dist_ts_web/elements/sio-bucket-header.d.ts +36 -0
  11. package/dist_ts_web/elements/sio-bucket-header.js +197 -0
  12. package/dist_ts_web/elements/sio-button.d.ts +7 -3
  13. package/dist_ts_web/elements/sio-button.js +253 -152
  14. package/dist_ts_web/elements/sio-channel-rail.d.ts +37 -0
  15. package/dist_ts_web/elements/sio-channel-rail.js +275 -0
  16. package/dist_ts_web/elements/sio-chip.d.ts +25 -0
  17. package/dist_ts_web/elements/sio-chip.js +188 -0
  18. package/dist_ts_web/elements/sio-cmdk.d.ts +59 -0
  19. package/dist_ts_web/elements/sio-cmdk.js +471 -0
  20. package/dist_ts_web/elements/sio-combox.d.ts +55 -1
  21. package/dist_ts_web/elements/sio-combox.js +458 -261
  22. package/dist_ts_web/elements/sio-composer.d.ts +48 -0
  23. package/dist_ts_web/elements/sio-composer.js +357 -0
  24. package/dist_ts_web/elements/sio-conversation-selector.d.ts +41 -1
  25. package/dist_ts_web/elements/sio-conversation-selector.js +426 -238
  26. package/dist_ts_web/elements/sio-conversation-view.d.ts +34 -6
  27. package/dist_ts_web/elements/sio-conversation-view.js +738 -564
  28. package/dist_ts_web/elements/sio-dropdown-menu.d.ts +6 -6
  29. package/dist_ts_web/elements/sio-dropdown-menu.js +223 -169
  30. package/dist_ts_web/elements/sio-fab.d.ts +23 -5
  31. package/dist_ts_web/elements/sio-fab.js +259 -235
  32. package/dist_ts_web/elements/sio-glass-toolbar.d.ts +22 -0
  33. package/dist_ts_web/elements/sio-glass-toolbar.js +178 -0
  34. package/dist_ts_web/elements/sio-icon.d.ts +1 -0
  35. package/dist_ts_web/elements/sio-icon.js +254 -94
  36. package/dist_ts_web/elements/sio-image-lightbox.d.ts +3 -4
  37. package/dist_ts_web/elements/sio-image-lightbox.js +282 -191
  38. package/dist_ts_web/elements/sio-inset-list.d.ts +28 -0
  39. package/dist_ts_web/elements/sio-inset-list.js +191 -0
  40. package/dist_ts_web/elements/sio-kbd.d.ts +16 -0
  41. package/dist_ts_web/elements/sio-kbd.js +117 -0
  42. package/dist_ts_web/elements/sio-list-row.d.ts +55 -0
  43. package/dist_ts_web/elements/sio-list-row.js +462 -0
  44. package/dist_ts_web/elements/sio-message-input.d.ts +25 -4
  45. package/dist_ts_web/elements/sio-message-input.js +231 -226
  46. package/dist_ts_web/elements/sio-paper-thumb.d.ts +24 -0
  47. package/dist_ts_web/elements/sio-paper-thumb.js +293 -0
  48. package/dist_ts_web/elements/sio-pdf-viewer.d.ts +2 -0
  49. package/dist_ts_web/elements/sio-pdf-viewer.js +344 -244
  50. package/dist_ts_web/elements/sio-segmented.d.ts +32 -0
  51. package/dist_ts_web/elements/sio-segmented.js +217 -0
  52. package/dist_ts_web/elements/sio-step-timeline.d.ts +28 -0
  53. package/dist_ts_web/elements/sio-step-timeline.js +222 -0
  54. package/dist_ts_web/elements/sio-tab-bar.d.ts +36 -0
  55. package/dist_ts_web/elements/sio-tab-bar.js +232 -0
  56. package/dist_ts_web/elements/sio-unread-badge.d.ts +25 -0
  57. package/dist_ts_web/elements/sio-unread-badge.js +203 -0
  58. package/dist_ts_web/elements/sio-waveform.d.ts +34 -0
  59. package/dist_ts_web/elements/sio-waveform.js +304 -0
  60. package/dist_ts_web/elements/tokens.d.ts +70 -0
  61. package/dist_ts_web/elements/tokens.js +277 -0
  62. package/dist_ts_web/pages/firstpage.d.ts +5 -0
  63. package/dist_ts_web/pages/firstpage.js +21 -2
  64. package/dist_ts_web/pages/mainpage.d.ts +6 -0
  65. package/dist_ts_web/pages/mainpage.js +111 -39
  66. package/{license → license.md} +3 -1
  67. package/package.json +23 -29
  68. package/readme.hints.md +81 -0
  69. package/readme.md +85 -151
  70. package/ts_web/00_commitinfo_data.ts +2 -2
  71. package/ts_web/elements/index.ts +30 -7
  72. package/ts_web/elements/sio-ai-card.ts +175 -0
  73. package/ts_web/elements/sio-avatar.ts +295 -0
  74. package/ts_web/elements/sio-bucket-header.ts +157 -0
  75. package/ts_web/elements/sio-button.ts +149 -127
  76. package/ts_web/elements/sio-channel-rail.ts +243 -0
  77. package/ts_web/elements/sio-chip.ts +134 -0
  78. package/ts_web/elements/sio-cmdk.ts +461 -0
  79. package/ts_web/elements/sio-combox.ts +327 -204
  80. package/ts_web/elements/sio-composer.ts +306 -0
  81. package/ts_web/elements/sio-conversation-selector.ts +350 -228
  82. package/ts_web/elements/sio-conversation-view.ts +573 -457
  83. package/ts_web/elements/sio-dropdown-menu.ts +112 -130
  84. package/ts_web/elements/sio-fab.ts +192 -227
  85. package/ts_web/elements/sio-glass-toolbar.ts +140 -0
  86. package/ts_web/elements/sio-icon.ts +147 -25
  87. package/ts_web/elements/sio-image-lightbox.ts +62 -64
  88. package/ts_web/elements/sio-inset-list.ts +140 -0
  89. package/ts_web/elements/sio-kbd.ts +80 -0
  90. package/ts_web/elements/sio-list-row.ts +393 -0
  91. package/ts_web/elements/sio-message-input.ts +142 -221
  92. package/ts_web/elements/sio-paper-thumb.ts +244 -0
  93. package/ts_web/elements/sio-pdf-viewer.ts +58 -60
  94. package/ts_web/elements/sio-segmented.ts +183 -0
  95. package/ts_web/elements/sio-step-timeline.ts +179 -0
  96. package/ts_web/elements/sio-tab-bar.ts +195 -0
  97. package/ts_web/elements/sio-unread-badge.ts +147 -0
  98. package/ts_web/elements/sio-waveform.ts +239 -0
  99. package/ts_web/elements/tokens.ts +297 -0
  100. package/ts_web/pages/firstpage.ts +20 -1
  101. package/ts_web/pages/mainpage.ts +111 -39
  102. package/dist_bundle/bundle.js.map +0 -7
  103. package/dist_ts_web/elements/00colors.d.ts +0 -108
  104. package/dist_ts_web/elements/00colors.js +0 -137
  105. package/dist_ts_web/elements/00fonts.d.ts +0 -60
  106. package/dist_ts_web/elements/00fonts.js +0 -129
  107. package/dist_ts_web/elements/00tokens.d.ts +0 -123
  108. package/dist_ts_web/elements/00tokens.js +0 -176
  109. package/dist_ts_web/elements/sio-conversation-list.d.ts +0 -20
  110. package/dist_ts_web/elements/sio-conversation-list.js +0 -495
  111. package/dist_ts_web/elements/sio-recorder.d.ts +0 -60
  112. package/dist_ts_web/elements/sio-recorder.js +0 -173
  113. package/dist_ts_web/elements/sio-subwidget-conversations.d.ts +0 -16
  114. package/dist_ts_web/elements/sio-subwidget-conversations.js +0 -350
  115. package/dist_ts_web/elements/sio-subwidget-onboardme.d.ts +0 -7
  116. package/dist_ts_web/elements/sio-subwidget-onboardme.js +0 -243
  117. package/dist_watch/bundle.js +0 -81694
  118. package/dist_watch/bundle.js.map +0 -7
  119. package/dist_watch/index.html +0 -25
  120. package/npmextra.json +0 -19
  121. package/ts_web/elements/00colors.ts +0 -164
  122. package/ts_web/elements/00fonts.ts +0 -145
  123. package/ts_web/elements/00tokens.ts +0 -197
  124. package/ts_web/elements/sio-recorder.ts +0 -213
@@ -1,21 +1,20 @@
1
1
  import {
2
2
  DeesElement,
3
- property,
4
3
  html,
4
+ property,
5
5
  customElement,
6
- type TemplateResult,
7
- cssManager,
8
6
  css,
9
- unsafeCSS,
10
- state,
7
+ cssManager,
8
+ type TemplateResult,
11
9
  } from '@design.estate/dees-element';
12
10
 
13
- // Import design tokens
14
- import { colors, bdTheme } from './00colors.js';
15
- import { spacing, radius, shadows, transitions } from './00tokens.js';
16
- import { fontFamilies, typography } from './00fonts.js';
11
+ import { sioElementStyles } from './tokens.js';
12
+ import './sio-icon.js';
13
+ import './sio-avatar.js';
17
14
 
18
15
  // Types
16
+ export type TConversationStatus = 'new' | 'waiting' | 'needs-action' | 'resolved';
17
+
19
18
  export interface IConversation {
20
19
  id: string;
21
20
  title: string;
@@ -23,6 +22,17 @@ export interface IConversation {
23
22
  time: string;
24
23
  unread?: boolean;
25
24
  avatar?: string;
25
+ status?: TConversationStatus;
26
+ /** agent initials for the avatar circle (falls back to the title's initials) */
27
+ initials?: string;
28
+ /** agent accent color (data-driven, any CSS color) */
29
+ tint?: string;
30
+ }
31
+
32
+ /** team member shown in the welcome header's avatar stack */
33
+ export interface ITeamMember {
34
+ initials: string;
35
+ tint: string;
26
36
  }
27
37
 
28
38
  declare global {
@@ -31,10 +41,40 @@ declare global {
31
41
  }
32
42
  }
33
43
 
44
+ /**
45
+ * sio-conversation-selector — the widget's home / welcome state
46
+ * (v7 SocialIOWidget.jsx SIOWidgetHome).
47
+ *
48
+ * Gradient tint header (white text) with the 3-avatar team stack,
49
+ * "Hi there 👋 / How can we help?" greeting and the presence line;
50
+ * body cards on radius 14: recent-conversation resume rows, the solid
51
+ * tint "Send us a message" CTA and the FAQ list with 0.5px hairlines.
52
+ *
53
+ * Events (bubbles, composed):
54
+ * conversation-selected { conversation } — resume a recent thread
55
+ * new-conversation — CTA row click
56
+ * faq-selected { question } — FAQ row click
57
+ * close — phablet close chevron
58
+ */
34
59
  @customElement('sio-conversation-selector')
35
60
  export class SioConversationSelector extends DeesElement {
36
61
  public static demo = () => html`
37
- <sio-conversation-selector style="width: 320px; height: 600px;"></sio-conversation-selector>
62
+ <div
63
+ style="width: 380px; height: 620px; border-radius: 20px; overflow: hidden; background: var(--sio-surface); box-shadow: 0 24px 64px rgba(0, 0, 0, 0.22), 0 0 0 0.5px rgba(0, 0, 0, 0.08);"
64
+ >
65
+ <sio-conversation-selector
66
+ .conversations=${[
67
+ {
68
+ id: 'orbit-launch',
69
+ title: 'Lena · Orbit',
70
+ lastMessage: 'Glad that sorted it — anything else, just write!',
71
+ time: '2d',
72
+ initials: 'LP',
73
+ tint: '#FF2D55',
74
+ } satisfies IConversation,
75
+ ]}
76
+ ></sio-conversation-selector>
77
+ </div>
38
78
  `;
39
79
 
40
80
  @property({ type: Array })
@@ -43,307 +83,389 @@ export class SioConversationSelector extends DeesElement {
43
83
  @property({ type: String })
44
84
  public accessor selectedConversationId: string | null = null;
45
85
 
46
- @state()
47
- private accessor searchQuery: string = '';
86
+ /** greeting headline, first line */
87
+ @property({ type: String })
88
+ public accessor greeting = 'Hi there 👋';
89
+
90
+ /** greeting headline, second line */
91
+ @property({ type: String })
92
+ public accessor tagline = 'How can we help?';
93
+
94
+ /** presence line next to the green dot */
95
+ @property({ type: String })
96
+ public accessor replyNote = 'We typically reply in a few minutes';
97
+
98
+ /** team members for the overlapping avatar stack in the header */
99
+ @property({ type: Array })
100
+ public accessor team: ITeamMember[] = [
101
+ { initials: 'LP', tint: '#FF2D55' },
102
+ { initials: 'MV', tint: '#0A84FF' },
103
+ { initials: 'PS', tint: '#30D158' },
104
+ ];
105
+
106
+ /** FAQ quick answers */
107
+ @property({ type: Array })
108
+ public accessor faqs: string[] = [
109
+ 'Where is my order?',
110
+ 'How do refunds work?',
111
+ 'Talk to a human',
112
+ ];
48
113
 
49
114
  public static styles = [
50
- cssManager.defaultStyles,
115
+ ...sioElementStyles,
51
116
  css`
52
117
  :host {
53
118
  display: flex;
54
119
  flex-direction: column;
55
120
  height: 100%;
56
- background: ${bdTheme('card')};
57
- border-right: 1px solid ${bdTheme('border')};
58
- font-family: ${unsafeCSS(fontFamilies.sans)};
121
+ background: var(--sio-surface);
122
+ font-family: var(--sio-font-sf);
123
+ overflow: hidden;
59
124
  }
60
125
 
126
+ /* ── gradient header ─────────────────────────────────────── */
61
127
  .header {
62
- padding: ${unsafeCSS(spacing["5"])} ${unsafeCSS(spacing["4"])};
63
- border-bottom: 1px solid ${bdTheme('border')};
64
- background: ${bdTheme('background')};
128
+ position: relative;
129
+ flex-shrink: 0;
130
+ padding: 24px 22px 20px;
131
+ background: linear-gradient(
132
+ 160deg,
133
+ var(--sio-tint) 0%,
134
+ color-mix(in oklab, var(--sio-tint) 80%, black) 100%
135
+ );
136
+ color: #fff; /* on-tint constant across themes (v7 widget header) */
65
137
  }
66
138
 
67
- .header-top {
139
+ .teamStack {
68
140
  display: flex;
69
- justify-content: space-between;
70
- align-items: center;
71
- margin-bottom: ${unsafeCSS(spacing["4"])};
141
+ margin-bottom: 14px;
72
142
  }
73
143
 
74
- .title {
75
- font-size: 1.25rem;
76
- line-height: 1.2;
77
- font-weight: 600;
78
- margin: 0;
79
- color: ${bdTheme('foreground')};
80
- letter-spacing: -0.025em;
144
+ .teamStack .member {
145
+ display: inline-flex;
146
+ border-radius: 50%;
147
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9); /* white ring on gradient per v7 */
81
148
  }
82
149
 
83
- .search-box {
84
- position: relative;
150
+ .teamStack .member:not(:first-child) {
151
+ margin-left: -8px;
85
152
  }
86
153
 
87
- .search-input {
88
- width: 100%;
89
- padding: ${unsafeCSS(spacing["2.5"])} ${unsafeCSS(spacing["10"])} ${unsafeCSS(spacing["2.5"])} ${unsafeCSS(spacing["3"])};
90
- background: ${bdTheme('background')};
91
- border: 1px solid ${bdTheme('border')};
92
- border-radius: ${unsafeCSS(radius.lg)};
93
- font-size: 0.875rem;
94
- color: ${bdTheme('foreground')};
95
- outline: none;
96
- transition: ${unsafeCSS(transitions.all)};
97
- font-family: ${unsafeCSS(fontFamilies.sans)};
98
- box-shadow: ${unsafeCSS(shadows.sm)};
154
+ .greeting {
155
+ font-size: 22px;
156
+ font-weight: 700;
157
+ letter-spacing: -0.4px;
158
+ line-height: 1.15;
99
159
  }
100
160
 
101
- .search-input::placeholder {
102
- color: ${bdTheme('mutedForeground')};
103
- font-weight: 400;
161
+ .presence {
162
+ margin-top: 8px;
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 6px;
166
+ font-size: 12.5px;
167
+ color: rgba(255, 255, 255, 0.75); /* on-tint muted per v7 */
104
168
  }
105
169
 
106
- .search-input:focus {
107
- border-color: ${bdTheme('ring')};
108
- box-shadow: 0 0 0 3px ${bdTheme('ring')}20;
109
- background: ${bdTheme('background')};
170
+ .presence .dot {
171
+ width: 7px;
172
+ height: 7px;
173
+ border-radius: 4px;
174
+ background: var(--sio-green);
175
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.25);
176
+ flex-shrink: 0;
110
177
  }
111
178
 
112
- .search-icon {
179
+ .closeButton {
180
+ display: none;
113
181
  position: absolute;
114
- right: ${unsafeCSS(spacing["3"])};
115
- top: 50%;
116
- transform: translateY(-50%);
117
- color: ${bdTheme('mutedForeground')};
182
+ top: 14px;
183
+ right: 14px;
184
+ width: 30px;
185
+ height: 30px;
186
+ border-radius: 15px;
187
+ border: none;
188
+ padding: 0;
189
+ align-items: center;
190
+ justify-content: center;
191
+ background: rgba(255, 255, 255, 0.18); /* on-tint scrim per v7 */
192
+ color: #fff;
193
+ cursor: pointer;
118
194
  }
119
195
 
120
- .conversation-list {
196
+ /* ── body cards ──────────────────────────────────────────── */
197
+ .body {
121
198
  flex: 1;
199
+ min-height: 0;
200
+ padding: 16px 16px 0;
201
+ display: flex;
202
+ flex-direction: column;
203
+ gap: 10px;
122
204
  overflow-y: auto;
123
- padding: ${unsafeCSS(spacing["2"])};
124
205
  }
125
206
 
126
- .conversation-item {
127
- padding: ${unsafeCSS(spacing["3.5"])};
128
- margin-bottom: ${unsafeCSS(spacing["1.5"])};
129
- background: ${bdTheme('background')};
130
- border: 1px solid transparent;
131
- border-radius: ${unsafeCSS(radius.lg)};
132
- cursor: pointer;
133
- transition: ${unsafeCSS(transitions.all)};
134
- position: relative;
207
+ .card {
208
+ flex-shrink: 0;
209
+ border-radius: var(--sio-radius-lg);
210
+ background: var(--sio-surface-2);
211
+ overflow: hidden;
135
212
  }
136
213
 
137
- .conversation-item:hover {
138
- background: ${bdTheme('accent')};
139
- transform: translateX(2px);
140
- box-shadow: ${unsafeCSS(shadows.sm)};
214
+ .recentCard {
215
+ padding: 12px 14px;
141
216
  }
142
217
 
143
- .conversation-item.selected {
144
- background: ${bdTheme('accent')};
145
- border-color: ${bdTheme('border')};
146
- box-shadow: ${unsafeCSS(shadows.sm)};
147
- }
148
-
149
- .conversation-item.selected::before {
150
- content: '';
151
- position: absolute;
152
- left: 0;
153
- top: 50%;
154
- transform: translateY(-50%);
155
- width: 3px;
156
- height: 60%;
157
- background: ${bdTheme('primary')};
158
- border-radius: 0 3px 3px 0;
159
- animation: slideIn 200ms ease-out;
160
- }
161
-
162
- @keyframes slideIn {
163
- from {
164
- width: 0;
165
- opacity: 0;
166
- }
167
- to {
168
- width: 3px;
169
- opacity: 1;
170
- }
218
+ .cardLabel {
219
+ font-size: 11px;
220
+ font-weight: 700;
221
+ color: var(--sio-label-3);
222
+ text-transform: uppercase;
223
+ letter-spacing: 0.05px;
224
+ margin-bottom: 8px;
171
225
  }
172
226
 
173
- .conversation-header {
227
+ .recentRow {
174
228
  display: flex;
175
- justify-content: space-between;
176
229
  align-items: center;
177
- margin-bottom: ${unsafeCSS(spacing["1"])};
230
+ gap: 10px;
231
+ cursor: pointer;
178
232
  }
179
233
 
180
- .conversation-title {
181
- font-weight: 500;
182
- color: ${bdTheme('foreground')};
234
+ .recentRow + .recentRow {
235
+ margin-top: 10px;
236
+ padding-top: 10px;
237
+ border-top: var(--sio-hairline) solid var(--sio-separator);
238
+ }
239
+
240
+ .recentMain {
241
+ flex: 1;
242
+ min-width: 0;
243
+ }
244
+
245
+ .recentTitle {
246
+ font-size: 13.5px;
247
+ font-weight: 600;
248
+ color: var(--sio-label);
183
249
  display: flex;
184
250
  align-items: center;
185
- gap: ${unsafeCSS(spacing["2"])};
186
- font-size: 0.9375rem;
187
- letter-spacing: -0.01em;
251
+ gap: 6px;
188
252
  }
189
253
 
190
- .conversation-time {
191
- font-size: 0.75rem;
192
- line-height: 1.5;
193
- color: ${bdTheme('mutedForeground')};
194
- opacity: 0.8;
254
+ .unreadDot {
255
+ width: 7px;
256
+ height: 7px;
257
+ border-radius: 4px;
258
+ background: var(--sio-tint);
259
+ flex-shrink: 0;
195
260
  }
196
261
 
197
- .conversation-preview {
198
- font-size: 0.8125rem;
199
- line-height: 1.5;
200
- color: ${bdTheme('mutedForeground')};
262
+ .recentPreview {
263
+ font-size: 12.5px;
264
+ color: var(--sio-label-3);
201
265
  overflow: hidden;
202
266
  text-overflow: ellipsis;
203
267
  white-space: nowrap;
204
- margin-top: ${unsafeCSS(spacing["0.5"])};
205
268
  }
206
269
 
207
- .unread-dot {
208
- display: inline-block;
209
- width: 6px;
210
- height: 6px;
211
- background: ${bdTheme('primary')};
212
- border-radius: 50%;
213
- animation: pulse 2s ease-in-out infinite;
214
- box-shadow: 0 0 0 0 ${bdTheme('primary')};
215
- }
216
-
217
- @keyframes pulse {
218
- 0% {
219
- opacity: 1;
220
- transform: scale(1);
221
- box-shadow: 0 0 0 0 ${bdTheme('primary')}40;
222
- }
223
- 50% {
224
- opacity: 0.9;
225
- transform: scale(1.05);
226
- box-shadow: 0 0 0 4px ${bdTheme('primary')}00;
227
- }
228
- 100% {
229
- opacity: 1;
230
- transform: scale(1);
231
- box-shadow: 0 0 0 0 ${bdTheme('primary')}00;
232
- }
270
+ .recentTime {
271
+ font-size: 11px;
272
+ color: var(--sio-label-3);
273
+ font-variant-numeric: tabular-nums;
274
+ flex-shrink: 0;
233
275
  }
234
276
 
235
- .empty-state {
277
+ /* solid tint CTA row */
278
+ .cta {
279
+ flex-shrink: 0;
280
+ border-radius: var(--sio-radius-lg);
281
+ padding: 13px 14px;
282
+ background: var(--sio-tint);
283
+ color: #fff; /* on-tint constant (v7 CTA row) */
236
284
  display: flex;
237
- flex-direction: column;
238
285
  align-items: center;
239
- justify-content: center;
240
- height: 100%;
241
- padding: ${unsafeCSS(spacing["4"])};
242
- text-align: center;
243
- color: ${bdTheme('mutedForeground')};
244
- gap: ${unsafeCSS(spacing["3"])};
286
+ gap: 10px;
287
+ cursor: pointer;
288
+ border: none;
289
+ width: 100%;
290
+ text-align: left;
291
+ font-family: inherit;
292
+ transition: background 120ms ease;
293
+ }
294
+
295
+ .cta:hover {
296
+ background: var(--sio-tint-hover);
245
297
  }
246
298
 
247
- .empty-icon {
248
- font-size: 48px;
249
- opacity: 0.5;
299
+ .cta .ctaLabel {
300
+ flex: 1;
301
+ font-size: 14px;
302
+ font-weight: 600;
303
+ letter-spacing: -0.1px;
250
304
  }
251
305
 
252
- /* Scrollbar styling */
253
- .conversation-list::-webkit-scrollbar {
254
- width: 6px;
306
+ .cta .chevron {
307
+ color: rgba(255, 255, 255, 0.8);
255
308
  }
256
309
 
257
- .conversation-list::-webkit-scrollbar-track {
258
- background: transparent;
310
+ /* FAQ list card */
311
+ .faqRow {
312
+ padding: 11px 14px;
313
+ font-size: 13.5px;
314
+ color: var(--sio-label);
315
+ display: flex;
316
+ align-items: center;
317
+ gap: 8px;
318
+ cursor: pointer;
319
+ transition: background 120ms ease;
259
320
  }
260
321
 
261
- .conversation-list::-webkit-scrollbar-thumb {
262
- background: ${bdTheme('border')};
263
- border-radius: 3px;
322
+ .faqRow + .faqRow {
323
+ border-top: var(--sio-hairline) solid var(--sio-separator);
264
324
  }
265
325
 
266
- .conversation-list::-webkit-scrollbar-thumb:hover {
267
- background: ${bdTheme('mutedForeground')};
326
+ .faqRow:hover {
327
+ background: color-mix(in oklab, var(--sio-label) 4%, transparent);
328
+ }
329
+
330
+ .faqRow .question {
331
+ flex: 1;
332
+ }
333
+
334
+ .faqRow sio-icon {
335
+ color: var(--sio-label-3);
268
336
  }
269
337
  `,
338
+ // phablet full-screen: surface the close chevron
339
+ cssManager.cssForPhablet(css`
340
+ .closeButton {
341
+ display: flex;
342
+ }
343
+ `),
270
344
  ];
271
345
 
272
346
  public render(): TemplateResult {
273
- const filteredConversations = this.conversations.filter(conv =>
274
- conv.title.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
275
- conv.lastMessage.toLowerCase().includes(this.searchQuery.toLowerCase())
276
- );
277
-
278
347
  return html`
279
348
  <div class="header">
280
- <div class="header-top">
281
- <h2 class="title">Messages</h2>
282
- <sio-button
283
- type="primary"
284
- size="sm"
285
- @click=${() => this.startNewConversation()}
286
- >
287
- <sio-icon icon="plus" size="16"></sio-icon>
288
- New
289
- </sio-button>
349
+ <button class="closeButton" aria-label="Close messenger" @click=${this.handleClose}>
350
+ <sio-icon icon="chevron-down" size="18" .strokeWidth=${2.4}></sio-icon>
351
+ </button>
352
+ <div class="teamStack">
353
+ ${this.team.map(
354
+ (member) => html`
355
+ <span class="member">
356
+ <sio-avatar
357
+ initials=${member.initials}
358
+ tint=${member.tint}
359
+ size="32"
360
+ ></sio-avatar>
361
+ </span>
362
+ `,
363
+ )}
290
364
  </div>
291
- <div class="search-box">
292
- <input
293
- type="text"
294
- class="search-input"
295
- placeholder="Search conversations..."
296
- .value=${this.searchQuery}
297
- @input=${(e: Event) => this.searchQuery = (e.target as HTMLInputElement).value}
298
- />
299
- <sio-icon class="search-icon" icon="search" size="16"></sio-icon>
365
+ <div class="greeting">${this.greeting}<br />${this.tagline}</div>
366
+ <div class="presence">
367
+ <span class="dot"></span>
368
+ ${this.replyNote}
300
369
  </div>
301
370
  </div>
302
-
303
- ${filteredConversations.length > 0 ? html`
304
- <div class="conversation-list">
305
- ${filteredConversations.map(conv => html`
306
- <div
307
- class="conversation-item ${this.selectedConversationId === conv.id ? 'selected' : ''}"
308
- @click=${() => this.selectConversation(conv)}
309
- >
310
- <div class="conversation-header">
311
- <span class="conversation-title">
312
- ${conv.title}
313
- ${conv.unread ? html`<span class="unread-dot"></span>` : ''}
314
- </span>
315
- <span class="conversation-time">${conv.time}</span>
371
+
372
+ <div class="body">
373
+ ${this.conversations.length > 0
374
+ ? html`
375
+ <div class="card recentCard">
376
+ <div class="cardLabel">Recent</div>
377
+ ${this.conversations.map(
378
+ (conversation) => html`
379
+ <div class="recentRow" @click=${() => this.selectConversation(conversation)}>
380
+ <sio-avatar
381
+ initials=${conversation.initials || this.deriveInitials(conversation.title)}
382
+ tint=${conversation.tint || 'var(--sio-tint)'}
383
+ size="30"
384
+ ></sio-avatar>
385
+ <div class="recentMain">
386
+ <div class="recentTitle">
387
+ ${conversation.title}
388
+ ${conversation.unread ? html`<span class="unreadDot"></span>` : ''}
389
+ </div>
390
+ <div class="recentPreview">${conversation.lastMessage}</div>
391
+ </div>
392
+ <span class="recentTime">${conversation.time}</span>
393
+ </div>
394
+ `,
395
+ )}
316
396
  </div>
317
- <div class="conversation-preview">${conv.lastMessage}</div>
318
- </div>
319
- `)}
320
- </div>
321
- ` : html`
322
- <div class="empty-state">
323
- <sio-icon class="empty-icon" icon="message-square"></sio-icon>
324
- <h3>${this.searchQuery ? 'No matching conversations' : 'No conversations yet'}</h3>
325
- <p>${this.searchQuery ? 'Try a different search term' : 'Start a new conversation to get started'}</p>
326
- </div>
327
- `}
397
+ `
398
+ : ''}
399
+
400
+ <button class="cta" @click=${this.startNewConversation}>
401
+ <sio-icon icon="pencil" size="16" .strokeWidth=${1.8}></sio-icon>
402
+ <span class="ctaLabel">Send us a message</span>
403
+ <sio-icon class="chevron" icon="chevron-right" size="13" .strokeWidth=${2}></sio-icon>
404
+ </button>
405
+
406
+ ${this.faqs.length > 0
407
+ ? html`
408
+ <div class="card">
409
+ ${this.faqs.map(
410
+ (question) => html`
411
+ <div class="faqRow" @click=${() => this.selectFaq(question)}>
412
+ <span class="question">${question}</span>
413
+ <sio-icon icon="chevron-right" size="12" .strokeWidth=${2}></sio-icon>
414
+ </div>
415
+ `,
416
+ )}
417
+ </div>
418
+ `
419
+ : ''}
420
+ </div>
328
421
  `;
329
422
  }
330
423
 
424
+ private deriveInitials(title: string): string {
425
+ return title
426
+ .split(/[\s·]+/)
427
+ .filter((part) => part.length > 0)
428
+ .slice(0, 2)
429
+ .map((part) => part[0].toUpperCase())
430
+ .join('');
431
+ }
432
+
331
433
  private selectConversation(conversation: IConversation) {
332
434
  this.selectedConversationId = conversation.id;
333
-
334
- // Dispatch event for parent components
335
- this.dispatchEvent(new CustomEvent('conversation-selected', {
336
- detail: { conversation },
337
- bubbles: true,
338
- composed: true
339
- }));
435
+ this.dispatchEvent(
436
+ new CustomEvent('conversation-selected', {
437
+ detail: { conversation },
438
+ bubbles: true,
439
+ composed: true,
440
+ }),
441
+ );
340
442
  }
341
443
 
342
- private startNewConversation() {
343
- // Dispatch event for parent components to handle new conversation creation
344
- this.dispatchEvent(new CustomEvent('new-conversation', {
345
- bubbles: true,
346
- composed: true
347
- }));
444
+ private startNewConversation = () => {
445
+ this.dispatchEvent(
446
+ new CustomEvent('new-conversation', {
447
+ bubbles: true,
448
+ composed: true,
449
+ }),
450
+ );
451
+ };
452
+
453
+ private selectFaq(question: string) {
454
+ this.dispatchEvent(
455
+ new CustomEvent('faq-selected', {
456
+ detail: { question },
457
+ bubbles: true,
458
+ composed: true,
459
+ }),
460
+ );
348
461
  }
349
- }
462
+
463
+ private handleClose = () => {
464
+ this.dispatchEvent(
465
+ new CustomEvent('close', {
466
+ bubbles: true,
467
+ composed: true,
468
+ }),
469
+ );
470
+ };
471
+ }