@happyvertical/smrt-messages 0.34.4 → 0.34.6

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 (32) hide show
  1. package/dist/manifest.json +2 -2
  2. package/dist/smrt-knowledge.json +4 -4
  3. package/dist/svelte/components/AccountCard.svelte +22 -13
  4. package/dist/svelte/components/AttachmentChip.svelte +26 -7
  5. package/dist/svelte/components/AttachmentChip.svelte.d.ts +0 -3
  6. package/dist/svelte/components/AttachmentChip.svelte.d.ts.map +1 -1
  7. package/dist/svelte/components/AttachmentUpload.svelte +12 -5
  8. package/dist/svelte/components/AttachmentUpload.svelte.d.ts.map +1 -1
  9. package/dist/svelte/components/ComposeForm.svelte +24 -45
  10. package/dist/svelte/components/ComposeForm.svelte.d.ts.map +1 -1
  11. package/dist/svelte/components/EmailAccountManager.svelte +57 -78
  12. package/dist/svelte/components/EmailAccountManager.svelte.d.ts.map +1 -1
  13. package/dist/svelte/components/EmailFilterManager.svelte +75 -95
  14. package/dist/svelte/components/EmailFilterManager.svelte.d.ts.map +1 -1
  15. package/dist/svelte/components/FolderNav.svelte +22 -15
  16. package/dist/svelte/components/FolderNav.svelte.d.ts.map +1 -1
  17. package/dist/svelte/components/ForwardForm.svelte +13 -29
  18. package/dist/svelte/components/ForwardForm.svelte.d.ts.map +1 -1
  19. package/dist/svelte/components/MessageCard.svelte +13 -6
  20. package/dist/svelte/components/MessageCard.svelte.d.ts.map +1 -1
  21. package/dist/svelte/components/MessageDetail.svelte +19 -12
  22. package/dist/svelte/components/MessageFilters.svelte +18 -14
  23. package/dist/svelte/components/MessageFilters.svelte.d.ts.map +1 -1
  24. package/dist/svelte/components/MessageToolbar.svelte +28 -20
  25. package/dist/svelte/components/MessageToolbar.svelte.d.ts.map +1 -1
  26. package/dist/svelte/components/RecipientInput.svelte +15 -6
  27. package/dist/svelte/components/RecipientInput.svelte.d.ts.map +1 -1
  28. package/dist/svelte/components/ReplyForm.svelte +13 -29
  29. package/dist/svelte/components/ReplyForm.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/ThreadView.svelte +19 -12
  31. package/dist/svelte/components/ThreadView.svelte.d.ts.map +1 -1
  32. package/package.json +8 -7
@@ -3,6 +3,7 @@
3
3
  * MessageFilters - Filter/sort controls bar
4
4
  */
5
5
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
6
+ import { Button } from '@happyvertical/smrt-ui/ui';
6
7
  import { M } from '../i18n.messages.js';
7
8
  import type {
8
9
  AccountData,
@@ -85,7 +86,7 @@ const _hasActiveFilters = $derived(
85
86
  onkeydown={(e) => { if (e.key === 'Enter') handleSearch(); }}
86
87
  aria-label={t(M['messages.message_filters.search_label'])}
87
88
  />
88
- <button class="search-btn" type="button" onclick={handleSearch}>Search</button>
89
+ <Button variant="primary" class="search-btn" onclick={handleSearch}>Search</Button>
89
90
  </div>
90
91
 
91
92
  <div class="filter-row">
@@ -139,9 +140,9 @@ const _hasActiveFilters = $derived(
139
140
  </label>
140
141
 
141
142
  {#if _hasActiveFilters}
142
- <button class="clear-btn" type="button" onclick={clearFilters}>
143
+ <Button variant="ghost" size="sm" class="clear-btn" onclick={clearFilters}>
143
144
  {t(M['messages.message_filters.clear_filters'])}
144
- </button>
145
+ </Button>
145
146
  {/if}
146
147
  </div>
147
148
  </div>
@@ -177,18 +178,16 @@ const _hasActiveFilters = $derived(
177
178
  outline-offset: -1px;
178
179
  }
179
180
 
180
- .search-btn {
181
+ /*
182
+ * Search now renders through smrt-ui's <Button variant="primary">. The variant
183
+ * owns the filled-primary background + hover; `.search-row :global(.search-btn)`
184
+ * only re-asserts the original small radius and label font/padding by piercing
185
+ * the Button child scope (issue #1589).
186
+ */
187
+ .search-row :global(.search-btn) {
181
188
  padding: 0.5rem 1rem;
182
- border: none;
183
189
  border-radius: var(--smrt-radius-small, 0.25rem);
184
- background: var(--smrt-color-primary, #005ac1);
185
- color: var(--smrt-color-on-primary, #fff);
186
190
  font: var(--smrt-typography-label-large-font, 500 0.875rem / 1.25 sans-serif);
187
- cursor: pointer;
188
- }
189
-
190
- .search-btn:hover {
191
- opacity: 0.9;
192
191
  }
193
192
 
194
193
  .filter-row {
@@ -216,13 +215,18 @@ const _hasActiveFilters = $derived(
216
215
  cursor: pointer;
217
216
  }
218
217
 
219
- .clear-btn {
218
+ /*
219
+ * Clear filters now renders through smrt-ui's <Button variant="ghost">.
220
+ * `.filter-row :global(.clear-btn)` anchors on the real `.filter-row` element
221
+ * and pierces the Button child scope to keep the underlined text-link look
222
+ * (issue #1589).
223
+ */
224
+ .filter-row :global(.clear-btn) {
220
225
  padding: 0.25rem 0.5rem;
221
226
  border: none;
222
227
  background: none;
223
228
  font: var(--smrt-typography-label-medium-font, 500 0.75rem / 1.33 sans-serif);
224
229
  color: var(--smrt-color-primary, #005ac1);
225
- cursor: pointer;
226
230
  text-decoration: underline;
227
231
  }
228
232
  </style>
@@ -1 +1 @@
1
- {"version":3,"file":"MessageFilters.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/MessageFilters.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,WAAW,EACZ,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAgHD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"MessageFilters.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/MessageFilters.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,WAAW,EACZ,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,cAAc,CAAC,EAAE,WAAW,EAAE,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACvD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAiHD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -3,6 +3,7 @@
3
3
  * MessageToolbar - Bulk action toolbar
4
4
  */
5
5
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
6
+ import { Button } from '@happyvertical/smrt-ui/ui';
6
7
  import type { Snippet } from 'svelte';
7
8
  import { M } from '../i18n.messages.js';
8
9
  import type { BulkAction } from '../types.js';
@@ -33,37 +34,37 @@ const {
33
34
  {#if selectedCount > 0}
34
35
  <span class="count">{t(M['messages.message_toolbar.count_selected'], { selectedCount, totalCount })}</span>
35
36
  {#if onclearselection}
36
- <button class="link-btn" type="button" onclick={onclearselection}>
37
+ <Button variant="ghost" size="sm" class="link-btn" onclick={onclearselection}>
37
38
  Clear
38
- </button>
39
+ </Button>
39
40
  {/if}
40
41
  {:else}
41
42
  <span class="count">{totalCount} messages</span>
42
43
  {/if}
43
44
  {#if onselectall && selectedCount < totalCount}
44
- <button class="link-btn" type="button" onclick={onselectall}>
45
+ <Button variant="ghost" size="sm" class="link-btn" onclick={onselectall}>
45
46
  {t(M['messages.message_toolbar.select_all'])}
46
- </button>
47
+ </Button>
47
48
  {/if}
48
49
  </div>
49
50
 
50
51
  {#if selectedCount > 0 && onaction}
51
52
  <div class="actions">
52
- <button class="action-btn" type="button" onclick={() => onaction?.('markRead')}>
53
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onaction?.('markRead')}>
53
54
  {t(M['messages.message_toolbar.mark_read'])}
54
- </button>
55
- <button class="action-btn" type="button" onclick={() => onaction?.('markUnread')}>
55
+ </Button>
56
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onaction?.('markUnread')}>
56
57
  {t(M['messages.message_toolbar.mark_unread'])}
57
- </button>
58
- <button class="action-btn" type="button" onclick={() => onaction?.('flag')}>
58
+ </Button>
59
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onaction?.('flag')}>
59
60
  Flag
60
- </button>
61
- <button class="action-btn" type="button" onclick={() => onaction?.('unflag')}>
61
+ </Button>
62
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onaction?.('unflag')}>
62
63
  Unflag
63
- </button>
64
- <button class="action-btn action-btn--danger" type="button" onclick={() => onaction?.('delete')}>
64
+ </Button>
65
+ <Button variant="ghost" size="sm" class="action-btn action-btn--danger" onclick={() => onaction?.('delete')}>
65
66
  Delete
66
- </button>
67
+ </Button>
67
68
  {#if extraActions}
68
69
  {@render extraActions()}
69
70
  {/if}
@@ -94,12 +95,20 @@ const {
94
95
  color: var(--smrt-color-on-surface-variant, #43474e);
95
96
  }
96
97
 
97
- .link-btn {
98
+ /*
99
+ * The link and action buttons now render through smrt-ui's <Button
100
+ * variant="ghost">. The <button> is emitted inside the Button child, so a
101
+ * plain scoped rule would not match — anchoring on the real `.selection-info`
102
+ * / `.actions` elements and piercing with `:global(...)` keeps the original
103
+ * text-link / outlined-surface styling (issue #1589). The destructive button's
104
+ * modifier is `action-btn--danger`, NOT `danger`, so it never collides with
105
+ * Button's own `.danger` variant class.
106
+ */
107
+ .selection-info :global(.link-btn) {
98
108
  border: none;
99
109
  background: none;
100
110
  font: var(--smrt-typography-label-medium-font, 500 0.75rem / 1.33 sans-serif);
101
111
  color: var(--smrt-color-primary, #005ac1);
102
- cursor: pointer;
103
112
  text-decoration: underline;
104
113
  padding: 0;
105
114
  }
@@ -110,21 +119,20 @@ const {
110
119
  flex-wrap: wrap;
111
120
  }
112
121
 
113
- .action-btn {
122
+ .actions :global(.action-btn) {
114
123
  padding: 0.25rem 0.625rem;
115
124
  border: 1px solid var(--smrt-color-outline, #72787e);
116
125
  border-radius: var(--smrt-radius-small, 0.25rem);
117
126
  background: var(--smrt-color-surface, #fefbff);
118
127
  color: var(--smrt-color-on-surface, #1a1c1e);
119
128
  font: var(--smrt-typography-label-small-font, 500 0.6875rem / 1 sans-serif);
120
- cursor: pointer;
121
129
  }
122
130
 
123
- .action-btn:hover {
131
+ .actions :global(.action-btn):hover {
124
132
  background: var(--smrt-color-surface-variant, #e1e2ec);
125
133
  }
126
134
 
127
- .action-btn--danger {
135
+ .actions :global(.action-btn--danger) {
128
136
  color: var(--smrt-color-error, #ba1a1a);
129
137
  border-color: var(--smrt-color-error, #ba1a1a);
130
138
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MessageToolbar.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/MessageToolbar.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,KAAK;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAoED,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"MessageToolbar.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/MessageToolbar.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,KAAK;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAqED,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -10,6 +10,8 @@ export interface Props {
10
10
  </script>
11
11
 
12
12
  <script lang="ts">
13
+ import { Button } from '@happyvertical/smrt-ui/ui';
14
+
13
15
  let {
14
16
  label = 'To',
15
17
  recipients = [],
@@ -61,11 +63,12 @@ export interface Props {
61
63
  {#each recipients as recipient, i}
62
64
  <span class="chip" class:invalid={!recipient.isValid}>
63
65
  <span class="chip-text">{recipient.name || recipient.address}</span>
64
- <button
66
+ <Button
67
+ variant="ghost"
68
+ size="sm"
65
69
  class="chip-remove"
66
70
  onclick={() => removeRecipient(i)}
67
- type="button"
68
- >×</button>
71
+ >×</Button>
69
72
  </span>
70
73
  {/each}
71
74
  <input
@@ -122,17 +125,23 @@ export interface Props {
122
125
  color: var(--smrt-color-on-error-container, #410002);
123
126
  }
124
127
 
125
- .chip-remove {
128
+ /*
129
+ * The chip remove button now renders through smrt-ui's <Button variant="ghost">.
130
+ * `.chips-container :global(.chip-remove)` anchors on the real `.chips-container`
131
+ * element and pierces the Button child scope to keep the compact icon styling.
132
+ * `color: inherit` keeps it matching the chip text color (including the invalid
133
+ * chip's error color) — issue #1589.
134
+ */
135
+ .chips-container :global(.chip-remove) {
126
136
  background: none;
127
137
  border: none;
128
- cursor: pointer;
129
138
  padding: 0 var(--smrt-spacing-1, 4px);
130
139
  font-size: var(--smrt-typography-label-large-size, 14px);
131
140
  color: inherit;
132
141
  opacity: 0.7;
133
142
  }
134
143
 
135
- .chip-remove:hover {
144
+ .chips-container :global(.chip-remove):hover {
136
145
  opacity: 1;
137
146
  }
138
147
 
@@ -1 +1 @@
1
- {"version":3,"file":"RecipientInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/RecipientInput.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmED,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"RecipientInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/RecipientInput.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAwED,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -11,6 +11,7 @@ export interface Props {
11
11
 
12
12
  <script lang="ts">
13
13
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
14
+ import { Button } from '@happyvertical/smrt-ui/ui';
14
15
  import { M } from '../i18n.js';
15
16
 
16
17
  const { t } = useI18n();
@@ -77,17 +78,16 @@ export interface Props {
77
78
  {/if}
78
79
 
79
80
  <div class="actions">
80
- <button
81
- type="button"
82
- class="btn-primary"
81
+ <Button
82
+ variant="primary"
83
83
  disabled={isSending || !body.trim()}
84
84
  onclick={handleSend}
85
85
  >
86
86
  {isSending ? 'Sending...' : 'Send Reply'}
87
- </button>
88
- <button type="button" class="btn-text" onclick={() => oncancel?.()}>
87
+ </Button>
88
+ <Button variant="ghost" class="btn-text" onclick={() => oncancel?.()}>
89
89
  Cancel
90
- </button>
90
+ </Button>
91
91
  </div>
92
92
  </div>
93
93
 
@@ -155,29 +155,13 @@ export interface Props {
155
155
  gap: var(--smrt-spacing-2, 8px);
156
156
  }
157
157
 
158
- .btn-primary {
159
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-6, 24px);
160
- border-radius: var(--smrt-radius-full, 20px);
161
- border: none;
162
- background: var(--smrt-color-primary, #6750a4);
163
- color: var(--smrt-color-on-primary, #fff);
164
- font-family: var(--smrt-font-family, system-ui);
165
- font-size: var(--smrt-typography-label-large-size, 14px);
166
- cursor: pointer;
167
- }
168
-
169
- .btn-primary:disabled {
170
- opacity: 0.6;
171
- cursor: not-allowed;
172
- }
173
-
174
- .btn-text {
175
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
176
- border: none;
177
- background: transparent;
158
+ /*
159
+ * Send Reply now uses Button's primary variant directly (dead .btn-primary CSS
160
+ * removed). The Cancel button keeps its neutral on-surface-variant text via
161
+ * `.actions :global(.btn-text)` (Button's ghost uses the primary color) —
162
+ * issue #1589.
163
+ */
164
+ .actions :global(.btn-text) {
178
165
  color: var(--smrt-color-on-surface-variant, #49454f);
179
- font-family: var(--smrt-font-family, system-ui);
180
- font-size: var(--smrt-typography-label-large-size, 14px);
181
- cursor: pointer;
182
166
  }
183
167
  </style>
@@ -1 +1 @@
1
- {"version":3,"file":"ReplyForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ReplyForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,KAAK;IACpB,eAAe,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAoFD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ReplyForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ReplyForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,KAAK;IACpB,eAAe,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAsFD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -3,6 +3,7 @@
3
3
  * ThreadView - Conversation thread with collapsible messages
4
4
  */
5
5
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
6
+ import { Button } from '@happyvertical/smrt-ui/ui';
6
7
  import { M } from '../i18n.messages.js';
7
8
  import type { MessageData } from '../types.js';
8
9
  import MessageDetail from './MessageDetail.svelte';
@@ -101,9 +102,10 @@ const _sortedMessages = $derived(
101
102
  role="listitem"
102
103
  >
103
104
  {#if collapsed.has(message.id)}
104
- <button
105
+ <Button
106
+ variant="ghost"
107
+ fullWidth
105
108
  class="collapsed-header"
106
- type="button"
107
109
  onclick={() => toggleCollapse(message.id)}
108
110
  >
109
111
  <span class="collapsed-sender">
@@ -117,19 +119,19 @@ const _sortedMessages = $derived(
117
119
  ? new Date(message.date).toLocaleDateString()
118
120
  : message.date?.toLocaleDateString() || ''}
119
121
  </span>
120
- </button>
122
+ </Button>
121
123
  {:else}
122
124
  <div class="message-wrapper">
123
125
  {#if messages.length > 1}
124
- <button
126
+ <Button
127
+ variant="ghost"
125
128
  class="collapse-btn"
126
- type="button"
127
129
  onclick={() => toggleCollapse(message.id)}
128
130
  title={t(M['messages.thread_view.collapse'])}
129
131
  aria-label={t(M['messages.thread_view.collapse_message'])}
130
132
  >
131
133
 
132
- </button>
134
+ </Button>
133
135
  {/if}
134
136
  {#if onmessageclick}
135
137
  <div
@@ -187,13 +189,19 @@ const _sortedMessages = $derived(
187
189
  position: relative;
188
190
  }
189
191
 
190
- .collapse-btn {
192
+ /*
193
+ * The collapse toggle and collapsed header now render through smrt-ui's
194
+ * <Button variant="ghost">. The <button> is emitted inside the Button child,
195
+ * so anchoring on the real `.message-wrapper` / `.thread-message` elements and
196
+ * piercing with `:global(...)` keeps the original positioning and styling
197
+ * (issue #1589).
198
+ */
199
+ .message-wrapper :global(.collapse-btn) {
191
200
  position: absolute;
192
201
  top: 0.75rem;
193
202
  right: 0.75rem;
194
203
  border: none;
195
204
  background: none;
196
- cursor: pointer;
197
205
  font-size: var(--smrt-typography-label-medium-size, 0.75rem);
198
206
  color: var(--smrt-color-on-surface-variant, #43474e);
199
207
  z-index: 1;
@@ -201,11 +209,11 @@ const _sortedMessages = $derived(
201
209
  border-radius: var(--smrt-radius-small, 0.25rem);
202
210
  }
203
211
 
204
- .collapse-btn:hover {
212
+ .message-wrapper :global(.collapse-btn):hover {
205
213
  background: var(--smrt-color-surface-variant, #e1e2ec);
206
214
  }
207
215
 
208
- .collapsed-header {
216
+ .thread-message :global(.collapsed-header) {
209
217
  display: flex;
210
218
  align-items: center;
211
219
  gap: 0.75rem;
@@ -214,13 +222,12 @@ const _sortedMessages = $derived(
214
222
  border: 1px solid var(--smrt-color-outline-variant, #c4c6d0);
215
223
  border-radius: var(--smrt-radius-medium, 0.5rem);
216
224
  background: var(--smrt-color-surface-variant, #e1e2ec);
217
- cursor: pointer;
218
225
  text-align: left;
219
226
  color: inherit;
220
227
  font: inherit;
221
228
  }
222
229
 
223
- .collapsed-header:hover {
230
+ .thread-message :global(.collapsed-header):hover {
224
231
  background: color-mix(in srgb, var(--smrt-color-surface-variant, #e1e2ec) 92%, var(--smrt-color-shadow, #000));
225
232
  }
226
233
 
@@ -1 +1 @@
1
- {"version":3,"file":"ThreadView.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ThreadView.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1C;AAqID,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ThreadView.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ThreadView.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1C;AAsID,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-messages",
3
- "version": "0.34.4",
3
+ "version": "0.34.6",
4
4
  "description": "Unified multi-channel messaging with STI-based hierarchies",
5
5
  "type": "module",
6
+ "smrtRawPrimitives": "strict-buttons",
6
7
  "main": "./dist/index.js",
7
8
  "types": "./dist/index.d.ts",
8
9
  "files": [
@@ -39,11 +40,11 @@
39
40
  "@happyvertical/messages": "^0.74.7",
40
41
  "@happyvertical/sql": "^0.74.7",
41
42
  "@happyvertical/utils": "^0.74.7",
42
- "@happyvertical/smrt-core": "0.34.4",
43
- "@happyvertical/smrt-types": "0.34.4",
44
- "@happyvertical/smrt-tenancy": "0.34.4",
45
- "@happyvertical/smrt-ui": "0.34.4",
46
- "@happyvertical/smrt-secrets": "0.34.4"
43
+ "@happyvertical/smrt-types": "0.34.6",
44
+ "@happyvertical/smrt-secrets": "0.34.6",
45
+ "@happyvertical/smrt-tenancy": "0.34.6",
46
+ "@happyvertical/smrt-core": "0.34.6",
47
+ "@happyvertical/smrt-ui": "0.34.6"
47
48
  },
48
49
  "peerDependencies": {
49
50
  "@happyvertical/encryption": "*",
@@ -66,7 +67,7 @@
66
67
  "typescript": "^5.9.3",
67
68
  "vite": "^7.3.1",
68
69
  "vitest": "^4.0.17",
69
- "@happyvertical/smrt-vitest": "0.34.4"
70
+ "@happyvertical/smrt-vitest": "0.34.6"
70
71
  },
71
72
  "keywords": [
72
73
  "email",