@social.io/catalog 1.3.0 → 2.1.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 (130) hide show
  1. package/.smartconfig.json +51 -0
  2. package/dist_bundle/bundle.js +5455 -3248
  3. package/dist_ts_web/00_commitinfo_data.js +3 -3
  4. package/dist_ts_web/elements/index.d.ts +21 -3
  5. package/dist_ts_web/elements/index.js +28 -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 +38 -0
  15. package/dist_ts_web/elements/sio-channel-rail.js +288 -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-logo-render.d.ts +42 -0
  45. package/dist_ts_web/elements/sio-logo-render.js +306 -0
  46. package/dist_ts_web/elements/sio-logo.d.ts +64 -0
  47. package/dist_ts_web/elements/sio-logo.js +393 -0
  48. package/dist_ts_web/elements/sio-message-input.d.ts +25 -4
  49. package/dist_ts_web/elements/sio-message-input.js +231 -226
  50. package/dist_ts_web/elements/sio-paper-thumb.d.ts +24 -0
  51. package/dist_ts_web/elements/sio-paper-thumb.js +293 -0
  52. package/dist_ts_web/elements/sio-pdf-viewer.d.ts +2 -0
  53. package/dist_ts_web/elements/sio-pdf-viewer.js +344 -244
  54. package/dist_ts_web/elements/sio-segmented.d.ts +32 -0
  55. package/dist_ts_web/elements/sio-segmented.js +217 -0
  56. package/dist_ts_web/elements/sio-step-timeline.d.ts +28 -0
  57. package/dist_ts_web/elements/sio-step-timeline.js +222 -0
  58. package/dist_ts_web/elements/sio-tab-bar.d.ts +36 -0
  59. package/dist_ts_web/elements/sio-tab-bar.js +232 -0
  60. package/dist_ts_web/elements/sio-unread-badge.d.ts +25 -0
  61. package/dist_ts_web/elements/sio-unread-badge.js +203 -0
  62. package/dist_ts_web/elements/sio-waveform.d.ts +34 -0
  63. package/dist_ts_web/elements/sio-waveform.js +304 -0
  64. package/dist_ts_web/elements/tokens.d.ts +70 -0
  65. package/dist_ts_web/elements/tokens.js +277 -0
  66. package/dist_ts_web/pages/firstpage.d.ts +5 -0
  67. package/dist_ts_web/pages/firstpage.js +21 -2
  68. package/dist_ts_web/pages/mainpage.d.ts +6 -0
  69. package/dist_ts_web/pages/mainpage.js +111 -39
  70. package/{license → license.md} +3 -1
  71. package/package.json +23 -29
  72. package/readme.hints.md +82 -0
  73. package/readme.md +113 -146
  74. package/ts_web/00_commitinfo_data.ts +2 -2
  75. package/ts_web/elements/index.ts +31 -7
  76. package/ts_web/elements/sio-ai-card.ts +175 -0
  77. package/ts_web/elements/sio-avatar.ts +295 -0
  78. package/ts_web/elements/sio-bucket-header.ts +157 -0
  79. package/ts_web/elements/sio-button.ts +149 -127
  80. package/ts_web/elements/sio-channel-rail.ts +256 -0
  81. package/ts_web/elements/sio-chip.ts +134 -0
  82. package/ts_web/elements/sio-cmdk.ts +461 -0
  83. package/ts_web/elements/sio-combox.ts +327 -204
  84. package/ts_web/elements/sio-composer.ts +306 -0
  85. package/ts_web/elements/sio-conversation-selector.ts +350 -228
  86. package/ts_web/elements/sio-conversation-view.ts +573 -457
  87. package/ts_web/elements/sio-dropdown-menu.ts +112 -130
  88. package/ts_web/elements/sio-fab.ts +192 -227
  89. package/ts_web/elements/sio-glass-toolbar.ts +140 -0
  90. package/ts_web/elements/sio-icon.ts +147 -25
  91. package/ts_web/elements/sio-image-lightbox.ts +62 -64
  92. package/ts_web/elements/sio-inset-list.ts +140 -0
  93. package/ts_web/elements/sio-kbd.ts +80 -0
  94. package/ts_web/elements/sio-list-row.ts +393 -0
  95. package/ts_web/elements/sio-logo-render.ts +367 -0
  96. package/ts_web/elements/sio-logo.ts +311 -0
  97. package/ts_web/elements/sio-message-input.ts +142 -221
  98. package/ts_web/elements/sio-paper-thumb.ts +244 -0
  99. package/ts_web/elements/sio-pdf-viewer.ts +58 -60
  100. package/ts_web/elements/sio-segmented.ts +183 -0
  101. package/ts_web/elements/sio-step-timeline.ts +179 -0
  102. package/ts_web/elements/sio-tab-bar.ts +195 -0
  103. package/ts_web/elements/sio-unread-badge.ts +147 -0
  104. package/ts_web/elements/sio-waveform.ts +239 -0
  105. package/ts_web/elements/tokens.ts +297 -0
  106. package/ts_web/pages/firstpage.ts +20 -1
  107. package/ts_web/pages/mainpage.ts +111 -39
  108. package/dist_bundle/bundle.js.map +0 -7
  109. package/dist_ts_web/elements/00colors.d.ts +0 -108
  110. package/dist_ts_web/elements/00colors.js +0 -137
  111. package/dist_ts_web/elements/00fonts.d.ts +0 -60
  112. package/dist_ts_web/elements/00fonts.js +0 -129
  113. package/dist_ts_web/elements/00tokens.d.ts +0 -123
  114. package/dist_ts_web/elements/00tokens.js +0 -176
  115. package/dist_ts_web/elements/sio-conversation-list.d.ts +0 -20
  116. package/dist_ts_web/elements/sio-conversation-list.js +0 -495
  117. package/dist_ts_web/elements/sio-recorder.d.ts +0 -60
  118. package/dist_ts_web/elements/sio-recorder.js +0 -173
  119. package/dist_ts_web/elements/sio-subwidget-conversations.d.ts +0 -16
  120. package/dist_ts_web/elements/sio-subwidget-conversations.js +0 -350
  121. package/dist_ts_web/elements/sio-subwidget-onboardme.d.ts +0 -7
  122. package/dist_ts_web/elements/sio-subwidget-onboardme.js +0 -243
  123. package/dist_watch/bundle.js +0 -81694
  124. package/dist_watch/bundle.js.map +0 -7
  125. package/dist_watch/index.html +0 -25
  126. package/npmextra.json +0 -19
  127. package/ts_web/elements/00colors.ts +0 -164
  128. package/ts_web/elements/00fonts.ts +0 -145
  129. package/ts_web/elements/00tokens.ts +0 -197
  130. package/ts_web/elements/sio-recorder.ts +0 -213
@@ -0,0 +1,295 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ property,
5
+ state,
6
+ customElement,
7
+ css,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+
11
+ import { sioElementStyles } from './tokens.js';
12
+ import './sio-icon.js';
13
+
14
+ export type TSioAvatarPresence = 'none' | 'online';
15
+ export type TSioAvatarChannelBadge = 'none' | 'mail' | 'chats' | 'calls' | 'letters';
16
+
17
+ declare global {
18
+ interface HTMLElementTagNameMap {
19
+ 'sio-avatar': SioAvatar;
20
+ 'sio-avatar-stack': SioAvatarStack;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * channel badge recipes — 18px glyph circle bottom-right of the avatar,
26
+ * solid channel color with a 2px surface ring (v7 SIOUniRow).
27
+ */
28
+ const channelBadgeRecipes: Record<
29
+ Exclude<TSioAvatarChannelBadge, 'none'>,
30
+ { icon: string; color: string }
31
+ > = {
32
+ mail: { icon: 'envelope', color: 'var(--sio-ch-mail)' },
33
+ chats: { icon: 'message-circle', color: 'var(--sio-ch-chats)' },
34
+ calls: { icon: 'phone', color: 'var(--sio-ch-calls)' },
35
+ letters: { icon: 'file-text', color: 'var(--sio-ch-letters)' },
36
+ };
37
+
38
+ /**
39
+ * sio-avatar — initials on a tinted circle (v7 `.sio-avatar`).
40
+ *
41
+ * The tint is data-driven (each person carries their own accent color),
42
+ * so it is passed in as a prop; it defaults to the system tint token.
43
+ * Optional presence dot (online) and channel badge, both ringed with
44
+ * 2px of surface color so they read on top of list rows.
45
+ */
46
+ @customElement('sio-avatar')
47
+ export class SioAvatar extends DeesElement {
48
+ public static demo = () => html`
49
+ <div style="display: flex; flex-direction: column; gap: 20px;">
50
+ <div style="display: flex; gap: 14px; align-items: center;">
51
+ <sio-avatar initials="LP" tint="#FF6B8A" size="56"></sio-avatar>
52
+ <sio-avatar initials="MV" tint="#0A84FF" size="44"></sio-avatar>
53
+ <sio-avatar initials="PS" tint="#30D158"></sio-avatar>
54
+ <sio-avatar initials="L" tint="#5E6AD2" size="34"></sio-avatar>
55
+ <sio-avatar initials="FA" tint="#A2845E" size="28"></sio-avatar>
56
+ <sio-avatar initials="JW" tint="#FF9F0A" size="20"></sio-avatar>
57
+ </div>
58
+ <div style="display: flex; gap: 14px; align-items: center;">
59
+ <sio-avatar initials="LP" tint="#FF6B8A" size="44" presence="online"></sio-avatar>
60
+ <sio-avatar initials="MV" tint="#0A84FF" size="40" channelBadge="mail"></sio-avatar>
61
+ <sio-avatar initials="LP" tint="#FF6B8A" size="40" channelBadge="chats"></sio-avatar>
62
+ <sio-avatar initials="PS" tint="#30D158" size="40" channelBadge="calls"></sio-avatar>
63
+ <sio-avatar initials="FA" tint="#A2845E" size="40" channelBadge="letters"></sio-avatar>
64
+ </div>
65
+ <div style="display: flex; gap: 24px; align-items: center;">
66
+ <sio-avatar-stack size="32">
67
+ <sio-avatar initials="LP" tint="#FF6B8A" size="32"></sio-avatar>
68
+ <sio-avatar initials="MV" tint="#0A84FF" size="32"></sio-avatar>
69
+ <sio-avatar initials="PS" tint="#30D158" size="32"></sio-avatar>
70
+ </sio-avatar-stack>
71
+ <sio-avatar-stack max="3" size="24">
72
+ <sio-avatar initials="LP" tint="#FF6B8A" size="24"></sio-avatar>
73
+ <sio-avatar initials="MV" tint="#0A84FF" size="24"></sio-avatar>
74
+ <sio-avatar initials="PS" tint="#30D158" size="24"></sio-avatar>
75
+ <sio-avatar initials="JW" tint="#FF9F0A" size="24"></sio-avatar>
76
+ <sio-avatar initials="AK" tint="#5E6AD2" size="24"></sio-avatar>
77
+ </sio-avatar-stack>
78
+ </div>
79
+ </div>
80
+ `;
81
+
82
+ @property({ type: String })
83
+ public accessor initials = '';
84
+
85
+ /** person accent color (data-driven); any CSS color, tokens welcome */
86
+ @property({ type: String })
87
+ public accessor tint = 'var(--sio-tint)';
88
+
89
+ @property({ type: Number })
90
+ public accessor size = 40;
91
+
92
+ @property({ type: String })
93
+ public accessor presence: TSioAvatarPresence = 'none';
94
+
95
+ @property({ type: String })
96
+ public accessor channelBadge: TSioAvatarChannelBadge = 'none';
97
+
98
+ public static styles = [
99
+ ...sioElementStyles,
100
+ css`
101
+ :host {
102
+ display: inline-flex;
103
+ flex-shrink: 0;
104
+ }
105
+
106
+ .wrapper {
107
+ position: relative;
108
+ flex-shrink: 0;
109
+ display: inline-flex;
110
+ }
111
+
112
+ /* v7 .sio-avatar — initials on tinted circle, white per design */
113
+ .avatar {
114
+ border-radius: 50%;
115
+ display: inline-flex;
116
+ align-items: center;
117
+ justify-content: center;
118
+ flex-shrink: 0;
119
+ font-family: var(--sio-font-sf);
120
+ font-weight: 600;
121
+ letter-spacing: -0.2px;
122
+ color: #fff; /* on-tint constant across themes (v7 .sio-avatar) */
123
+ user-select: none;
124
+ }
125
+
126
+ .presence {
127
+ position: absolute;
128
+ right: -1px;
129
+ bottom: -1px;
130
+ border-radius: 50%;
131
+ background: var(--sio-green);
132
+ border: 2px solid var(--sio-surface);
133
+ }
134
+
135
+ .channelBadge {
136
+ position: absolute;
137
+ right: -3px;
138
+ bottom: -3px;
139
+ width: 18px;
140
+ height: 18px;
141
+ border-radius: 9px;
142
+ color: #fff; /* glyph on solid channel color */
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: center;
146
+ border: 2px solid var(--sio-surface);
147
+ }
148
+ `,
149
+ ];
150
+
151
+ public render(): TemplateResult {
152
+ const fontSize = Math.round(this.size * 0.4);
153
+ const presenceSize = Math.max(8, Math.round(this.size * 0.27));
154
+ const badge = this.channelBadge !== 'none' ? channelBadgeRecipes[this.channelBadge] : null;
155
+ return html`
156
+ <div class="wrapper">
157
+ <div
158
+ class="avatar"
159
+ style="width: ${this.size}px; height: ${this.size}px; font-size: ${fontSize}px; background: ${this.tint};"
160
+ >
161
+ ${this.initials}
162
+ </div>
163
+ ${this.presence === 'online'
164
+ ? html`<div class="presence" style="width: ${presenceSize}px; height: ${presenceSize}px;"></div>`
165
+ : ''}
166
+ ${badge
167
+ ? html`
168
+ <div class="channelBadge" style="background: ${badge.color};">
169
+ <sio-icon icon=${badge.icon} size="10"></sio-icon>
170
+ </div>
171
+ `
172
+ : ''}
173
+ </div>
174
+ `;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * sio-avatar-stack — overlapping avatar row (thread participants).
180
+ * Slotted sio-avatar elements overlap by -8px, each ringed with 2px of
181
+ * surface color; avatars beyond `max` collapse into a "+N" bubble.
182
+ */
183
+ @customElement('sio-avatar-stack')
184
+ export class SioAvatarStack extends DeesElement {
185
+ public static demo = () => html`
186
+ <div style="display: flex; gap: 24px; align-items: center;">
187
+ <sio-avatar-stack size="32">
188
+ <sio-avatar initials="LP" tint="#FF6B8A" size="32"></sio-avatar>
189
+ <sio-avatar initials="MV" tint="#0A84FF" size="32"></sio-avatar>
190
+ <sio-avatar initials="PS" tint="#30D158" size="32"></sio-avatar>
191
+ </sio-avatar-stack>
192
+ <sio-avatar-stack max="3" size="28">
193
+ <sio-avatar initials="LP" tint="#FF6B8A" size="28"></sio-avatar>
194
+ <sio-avatar initials="MV" tint="#0A84FF" size="28"></sio-avatar>
195
+ <sio-avatar initials="PS" tint="#30D158" size="28"></sio-avatar>
196
+ <sio-avatar initials="JW" tint="#FF9F0A" size="28"></sio-avatar>
197
+ <sio-avatar initials="AK" tint="#5E6AD2" size="28"></sio-avatar>
198
+ <sio-avatar initials="RB" tint="#A2845E" size="28"></sio-avatar>
199
+ </sio-avatar-stack>
200
+ <sio-avatar-stack max="2" size="24">
201
+ <sio-avatar initials="LP" tint="#FF6B8A" size="24"></sio-avatar>
202
+ <sio-avatar initials="MV" tint="#0A84FF" size="24"></sio-avatar>
203
+ <sio-avatar initials="PS" tint="#30D158" size="24"></sio-avatar>
204
+ <sio-avatar initials="JW" tint="#FF9F0A" size="24"></sio-avatar>
205
+ </sio-avatar-stack>
206
+ </div>
207
+ `;
208
+
209
+ /** visible avatars before collapsing into "+N" */
210
+ @property({ type: Number })
211
+ public accessor max = 4;
212
+
213
+ /** diameter of the "+N" overflow bubble — match the slotted avatar size */
214
+ @property({ type: Number })
215
+ public accessor size = 28;
216
+
217
+ @state()
218
+ private accessor overflowCount = 0;
219
+
220
+ public static styles = [
221
+ ...sioElementStyles,
222
+ css`
223
+ :host {
224
+ display: inline-flex;
225
+ align-items: center;
226
+ }
227
+
228
+ ::slotted(sio-avatar) {
229
+ border-radius: 50%;
230
+ box-shadow: 0 0 0 2px var(--sio-surface);
231
+ }
232
+
233
+ ::slotted(sio-avatar:not(:first-child)) {
234
+ margin-left: -8px;
235
+ }
236
+
237
+ ::slotted(sio-avatar[data-sio-stack-overflow]) {
238
+ display: none;
239
+ }
240
+
241
+ .overflow {
242
+ display: inline-flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ flex-shrink: 0;
246
+ margin-left: -8px;
247
+ border-radius: 50%;
248
+ background: var(--sio-surface-2);
249
+ color: var(--sio-label-2);
250
+ font-family: var(--sio-font-sf);
251
+ font-weight: 600;
252
+ font-variant-numeric: tabular-nums;
253
+ box-shadow: 0 0 0 2px var(--sio-surface);
254
+ user-select: none;
255
+ }
256
+ `,
257
+ ];
258
+
259
+ public render(): TemplateResult {
260
+ const overflowFontSize = Math.max(9, Math.round(this.size * 0.36));
261
+ return html`
262
+ <slot @slotchange=${this.recomputeStack}></slot>
263
+ ${this.overflowCount > 0
264
+ ? html`
265
+ <span
266
+ class="overflow"
267
+ style="width: ${this.size}px; height: ${this.size}px; font-size: ${overflowFontSize}px;"
268
+ >
269
+ +${this.overflowCount}
270
+ </span>
271
+ `
272
+ : ''}
273
+ `;
274
+ }
275
+
276
+ public updated(changedProperties: Map<PropertyKey, unknown>) {
277
+ if (changedProperties.has('max')) {
278
+ this.recomputeStack();
279
+ }
280
+ }
281
+
282
+ private recomputeStack = () => {
283
+ const slot = this.shadowRoot?.querySelector('slot');
284
+ if (!slot) {
285
+ return;
286
+ }
287
+ const avatars = slot
288
+ .assignedElements()
289
+ .filter((element) => element.tagName.toLowerCase() === 'sio-avatar');
290
+ avatars.forEach((element, index) => {
291
+ element.toggleAttribute('data-sio-stack-overflow', index >= this.max);
292
+ });
293
+ this.overflowCount = Math.max(0, avatars.length - this.max);
294
+ };
295
+ }
@@ -0,0 +1,157 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ property,
5
+ customElement,
6
+ css,
7
+ type TemplateResult,
8
+ } from '@design.estate/dees-element';
9
+ import { sioElementStyles, sioTabularNums } from './tokens.js';
10
+
11
+ /**
12
+ * Known tint keys resolve to v7 palette tokens; anything else is passed
13
+ * through verbatim so callers can hand in `var(--sio-…)` references.
14
+ */
15
+ export type TSioBucketTint =
16
+ | 'now'
17
+ | 'today'
18
+ | 'later'
19
+ | 'done'
20
+ | 'feed'
21
+ | 'paper'
22
+ | 'people'
23
+ | 'mail'
24
+ | 'chats'
25
+ | 'calls'
26
+ | 'letters'
27
+ | 'tint'
28
+ | string;
29
+
30
+ const bucketTintVars: Record<string, string> = {
31
+ now: 'var(--sio-bucket-now)',
32
+ today: 'var(--sio-bucket-today)',
33
+ later: 'var(--sio-bucket-later)',
34
+ done: 'var(--sio-bucket-done)',
35
+ feed: 'var(--sio-lane-feed)',
36
+ paper: 'var(--sio-lane-paper)',
37
+ people: 'var(--sio-lane-people)',
38
+ mail: 'var(--sio-ch-mail)',
39
+ chats: 'var(--sio-ch-chats)',
40
+ calls: 'var(--sio-ch-calls)',
41
+ letters: 'var(--sio-ch-letters)',
42
+ tint: 'var(--sio-tint)',
43
+ };
44
+
45
+ declare global {
46
+ interface HTMLElementTagNameMap {
47
+ 'sio-bucket-header': SioBucketHeader;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * sio-bucket-header — triage bucket band of the unified feed
53
+ * (design source: SIOBucketHeader in SocialIOUnified.jsx).
54
+ *
55
+ * 6px color dot + uppercase 13/700 tinted label + tabular count,
56
+ * optional right-aligned subtitle, on a faint 2% label-tint band.
57
+ * A default slot after the subtitle takes custom trailing content.
58
+ */
59
+ @customElement('sio-bucket-header')
60
+ export class SioBucketHeader extends DeesElement {
61
+ public static demo = () => html`
62
+ <div style="max-width: 420px; font-family: var(--sio-font-sf); background: var(--sio-bg); border-radius: 12px; overflow: hidden;">
63
+ <sio-bucket-header label="Now" count="2" tint="now" subtitle="needs reply today"></sio-bucket-header>
64
+ <div style="background: var(--sio-surface); height: 44px;"></div>
65
+ <sio-bucket-header label="Today" count="4" tint="today"></sio-bucket-header>
66
+ <div style="background: var(--sio-surface); height: 44px;"></div>
67
+ <sio-bucket-header label="Later" count="7" tint="later"></sio-bucket-header>
68
+ <div style="background: var(--sio-surface); height: 44px;"></div>
69
+ <sio-bucket-header label="Done" count="12" tint="done" subtitle="cleared this week"></sio-bucket-header>
70
+ <div style="background: var(--sio-surface); height: 44px;"></div>
71
+ <sio-bucket-header label="Yesterday" count="3" tint="tint"></sio-bucket-header>
72
+ <div style="background: var(--sio-surface); height: 44px;"></div>
73
+ </div>
74
+ `;
75
+
76
+ /** Bucket label — rendered uppercase, 13px / 700, tinted. */
77
+ @property({ type: String })
78
+ public accessor label = '';
79
+
80
+ /** Item count — rendered as "· n" with tabular-nums. Omit to hide. */
81
+ @property({ type: Number })
82
+ public accessor count: number | undefined = undefined;
83
+
84
+ /** Optional right-aligned subtitle on the band (e.g. "needs reply today"). */
85
+ @property({ type: String })
86
+ public accessor subtitle = '';
87
+
88
+ /**
89
+ * Bucket tint: now | today | later | done, lane keys (feed/paper/people),
90
+ * channel keys (mail/chats/calls/letters), 'tint', or any CSS color value.
91
+ */
92
+ @property({ type: String })
93
+ public accessor tint: TSioBucketTint = 'later';
94
+
95
+ public static styles = [
96
+ ...sioElementStyles,
97
+ css`
98
+ :host {
99
+ display: block;
100
+ font-family: var(--sio-font-sf);
101
+ }
102
+ .header {
103
+ padding: 16px 16px 8px;
104
+ display: flex;
105
+ align-items: baseline;
106
+ gap: 8px;
107
+ /* faint band — ~2% label ink over the grouped background */
108
+ background: color-mix(in oklab, var(--sio-label) 2%, transparent);
109
+ }
110
+ .dot {
111
+ width: 6px;
112
+ height: 6px;
113
+ border-radius: 3px;
114
+ background: var(--_bucket-tint);
115
+ flex-shrink: 0;
116
+ }
117
+ .label {
118
+ font-size: 13px;
119
+ font-weight: 700;
120
+ color: var(--_bucket-tint);
121
+ letter-spacing: 0.02em;
122
+ text-transform: uppercase;
123
+ }
124
+ .count {
125
+ font-size: 11px;
126
+ color: var(--sio-label-3);
127
+ ${sioTabularNums}
128
+ }
129
+ .spacer {
130
+ flex: 1;
131
+ }
132
+ .subtitle {
133
+ font-size: 11px;
134
+ color: var(--sio-label-3);
135
+ }
136
+ `,
137
+ ];
138
+
139
+ private get resolvedTint(): string {
140
+ return bucketTintVars[this.tint] ?? this.tint;
141
+ }
142
+
143
+ public render(): TemplateResult {
144
+ return html`
145
+ <div class="header" style="--_bucket-tint: ${this.resolvedTint}">
146
+ <div class="dot"></div>
147
+ <span class="label">${this.label}</span>
148
+ ${typeof this.count === 'number' && !Number.isNaN(this.count)
149
+ ? html`<span class="count">· ${this.count}</span>`
150
+ : html``}
151
+ <span class="spacer"></span>
152
+ ${this.subtitle ? html`<span class="subtitle">${this.subtitle}</span>` : html``}
153
+ <slot></slot>
154
+ </div>
155
+ `;
156
+ }
157
+ }