@happyvertical/smrt-messages 0.34.5 → 0.34.7

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 +19 -7
  8. package/dist/svelte/components/AttachmentUpload.svelte.d.ts.map +1 -1
  9. package/dist/svelte/components/ComposeForm.svelte +66 -75
  10. package/dist/svelte/components/ComposeForm.svelte.d.ts.map +1 -1
  11. package/dist/svelte/components/EmailAccountManager.svelte +81 -115
  12. package/dist/svelte/components/EmailAccountManager.svelte.d.ts.map +1 -1
  13. package/dist/svelte/components/EmailFilterManager.svelte +94 -127
  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 +16 -48
  18. package/dist/svelte/components/ForwardForm.svelte.d.ts.map +1 -1
  19. package/dist/svelte/components/MessageCard.svelte +14 -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 +47 -43
  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 +32 -9
  27. package/dist/svelte/components/RecipientInput.svelte.d.ts.map +1 -1
  28. package/dist/svelte/components/ReplyForm.svelte +16 -48
  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
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782261256603,
3
+ "timestamp": 1782290123485,
4
4
  "packageName": "@happyvertical/smrt-messages",
5
- "packageVersion": "0.34.5",
5
+ "packageVersion": "0.34.7",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-messages:AccountCollection": {
8
8
  "name": "accountcollection",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-24T00:34:17.992Z",
3
+ "generatedAt": "2026-06-24T08:35:23.962Z",
4
4
  "packageName": "@happyvertical/smrt-messages",
5
- "packageVersion": "0.34.5",
5
+ "packageVersion": "0.34.7",
6
6
  "sourceManifestPath": "dist/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "037dffc41f063fc3dbe896dbcbcbe5f8074af5777dbdb5bf2216f91df7273106",
10
- "packageJson": "db17137f6ce1821a78b18f29d654e6485266fe906e4d53eea1a15e4e53a1d773",
9
+ "manifest": "b04155056eca2221ce9e7a3f2fcc2177b71deb6895a44888b1d4a8a5a54b820b",
10
+ "packageJson": "e975d74552f6fc6f75ea081adbeb86da80d5d9927acd94950c09fdc04fd6fd03",
11
11
  "agents": "32563a30ceeb21bd8732042f894e2a148fd83727caffc1eec7c97540005c6fdc"
12
12
  },
13
13
  "exports": [
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * AccountCard - Individual account card with status and actions
4
4
  */
5
- import { Card } from '@happyvertical/smrt-ui/ui';
5
+ import { Button, Card } from '@happyvertical/smrt-ui/ui';
6
6
  import type { AccountData } from '../types.js';
7
7
  import AccountAvatar from './AccountAvatar.svelte';
8
8
 
@@ -51,24 +51,24 @@ const _lastSyncFormatted = $derived.by(() => {
51
51
 
52
52
  <div class="actions">
53
53
  {#if onsync && account.isActive}
54
- <button class="action-btn" type="button" onclick={() => onsync?.(account)}>
54
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onsync?.(account)}>
55
55
  Sync
56
- </button>
56
+ </Button>
57
57
  {/if}
58
58
  {#if account.isActive && ondeactivate}
59
- <button class="action-btn" type="button" onclick={() => ondeactivate?.(account)}>
59
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => ondeactivate?.(account)}>
60
60
  Deactivate
61
- </button>
61
+ </Button>
62
62
  {/if}
63
63
  {#if !account.isActive && onactivate}
64
- <button class="action-btn" type="button" onclick={() => onactivate?.(account)}>
64
+ <Button variant="ghost" size="sm" class="action-btn" onclick={() => onactivate?.(account)}>
65
65
  Activate
66
- </button>
66
+ </Button>
67
67
  {/if}
68
68
  {#if onremove}
69
- <button class="action-btn action-btn--danger" type="button" onclick={() => onremove?.(account)}>
69
+ <Button variant="ghost" size="sm" class="action-btn action-btn--danger" onclick={() => onremove?.(account)}>
70
70
  Remove
71
- </button>
71
+ </Button>
72
72
  {/if}
73
73
  </div>
74
74
  </div>
@@ -152,21 +152,30 @@ const _lastSyncFormatted = $derived.by(() => {
152
152
  gap: 0.375rem;
153
153
  }
154
154
 
155
- .action-btn {
155
+ /*
156
+ * The action buttons now render through smrt-ui's <Button variant="ghost">.
157
+ * Svelte scopes `.action-btn` to this component, but the <button> is emitted
158
+ * inside the Button child, so a plain `.action-btn {}` rule would not match —
159
+ * `.actions :global(.action-btn)` anchors on `.actions` (a real element here)
160
+ * and pierces into the child (issue #1589). These overrides keep the original
161
+ * outlined-surface look (border/radius/color); the modifier class is
162
+ * `action-btn--danger`, NOT `danger`, so it never collides with Button's own
163
+ * `.danger` variant class.
164
+ */
165
+ .actions :global(.action-btn) {
156
166
  padding: 0.375rem 0.75rem;
157
167
  border: 1px solid var(--smrt-color-outline, #72787e);
158
168
  border-radius: var(--smrt-radius-small, 0.25rem);
159
169
  background: var(--smrt-color-surface, #fefbff);
160
170
  color: var(--smrt-color-on-surface, #1a1c1e);
161
171
  font: var(--smrt-typography-label-medium-font, 500 0.75rem / 1.33 sans-serif);
162
- cursor: pointer;
163
172
  }
164
173
 
165
- .action-btn:hover {
174
+ .actions :global(.action-btn):hover {
166
175
  background: var(--smrt-color-surface-variant, #e1e2ec);
167
176
  }
168
177
 
169
- .action-btn--danger {
178
+ .actions :global(.action-btn--danger) {
170
179
  color: var(--smrt-color-error, #ba1a1a);
171
180
  border-color: var(--smrt-color-error, #ba1a1a);
172
181
  }
@@ -2,6 +2,7 @@
2
2
  /**
3
3
  * AttachmentChip - File chip with icon, name, and size
4
4
  */
5
+ import { Button } from '@happyvertical/smrt-ui/ui';
5
6
  import type { AttachmentData } from '../types.js';
6
7
 
7
8
  export interface Props {
@@ -33,16 +34,16 @@ const _formattedSize = $derived.by(() => {
33
34
  </script>
34
35
 
35
36
  {#if onclick}
36
- <button
37
- class="chip"
38
- type="button"
37
+ <Button
38
+ variant="ghost"
39
+ class="chip chip--button"
39
40
  onclick={() => onclick?.(attachment)}
40
41
  title={`${attachment.filename} (${_formattedSize})`}
41
42
  >
42
43
  <span class="icon">{_icon}</span>
43
44
  <span class="name">{attachment.filename}</span>
44
45
  <span class="size">{_formattedSize}</span>
45
- </button>
46
+ </Button>
46
47
  {:else}
47
48
  <span class="chip" title={`${attachment.filename} (${_formattedSize})`}>
48
49
  <span class="icon">{_icon}</span>
@@ -66,16 +67,34 @@ const _formattedSize = $derived.by(() => {
66
67
  max-width: 200px;
67
68
  }
68
69
 
69
- button.chip {
70
+ /*
71
+ * The interactive chip now renders through smrt-ui's <Button variant="ghost">.
72
+ * The <button> is emitted inside the Button child carrying Button's scope hash,
73
+ * so the local `.chip` rule above no longer reaches it. `:global(.chip--button)`
74
+ * pierces that scope to give the button the same chip styling plus the
75
+ * pressable affordances; `chip--button` is a non-colliding modifier (issue
76
+ * #1589). The non-interactive `<span class="chip">` branch still uses the
77
+ * scoped `.chip` rule above.
78
+ */
79
+ :global(.chip.chip--button) {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ gap: 0.375rem;
83
+ padding: 0.25rem 0.625rem;
84
+ border-radius: var(--smrt-radius-small, 0.25rem);
85
+ background: var(--smrt-color-surface-variant, #e1e2ec);
86
+ color: var(--smrt-color-on-surface-variant, #43474e);
87
+ font: var(--smrt-typography-label-medium-font, 500 0.75rem / 1.33 sans-serif);
70
88
  cursor: pointer;
89
+ max-width: 200px;
71
90
  transition: background var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
72
91
  }
73
92
 
74
- button.chip:hover {
93
+ :global(.chip.chip--button):hover {
75
94
  background: color-mix(in srgb, var(--smrt-color-surface-variant, #e1e2ec) 92%, var(--smrt-color-shadow, #000));
76
95
  }
77
96
 
78
- button.chip:focus-visible {
97
+ :global(.chip.chip--button):focus-visible {
79
98
  outline: 2px solid var(--smrt-color-primary, #005ac1);
80
99
  outline-offset: 1px;
81
100
  }
@@ -1,6 +1,3 @@
1
- /**
2
- * AttachmentChip - File chip with icon, name, and size
3
- */
4
1
  import type { AttachmentData } from '../types.js';
5
2
  export interface Props {
6
3
  attachment: AttachmentData;
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentChip.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AttachmentChip.svelte.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;CAChD;AA+CD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"AttachmentChip.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AttachmentChip.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;CAChD;AAgDD,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();
@@ -59,11 +60,12 @@ export interface Props {
59
60
  <div class="attachment-item">
60
61
  <span class="filename">{attachment.filename}</span>
61
62
  <span class="size">{formatSize(attachment.size)}</span>
62
- <button
63
+ <Button
64
+ variant="ghost"
65
+ size="sm"
63
66
  class="remove"
64
67
  onclick={() => onremove?.(i)}
65
- type="button"
66
- >×</button>
68
+ >×</Button>
67
69
  </div>
68
70
  {/each}
69
71
  </div>
@@ -78,11 +80,12 @@ export interface Props {
78
80
  ondragleave={handleDragLeave}
79
81
  >
80
82
  <label class="upload-label">
83
+ <!-- raw-primitive-allow: native file input — the Input primitive binds value, which is invalid for type=file (throws InvalidStateError on the bind write-back) and renders a visible control; this hidden picker behind the drop zone stays native -->
81
84
  <input
82
85
  type="file"
83
86
  multiple
84
87
  class="file-input"
85
- onchange={(e) => handleFiles((e.target as HTMLInputElement).files)}
88
+ onchange={(e) => handleFiles((e.currentTarget as HTMLInputElement).files)}
86
89
  />
87
90
  <span class="upload-text">{t(M['messages.attachment_upload.drop_files'])}</span>
88
91
  </label>
@@ -122,10 +125,15 @@ export interface Props {
122
125
  font-size: var(--smrt-typography-label-small-size, 11px);
123
126
  }
124
127
 
125
- .remove {
128
+ /*
129
+ * The remove button now renders through smrt-ui's <Button variant="ghost">.
130
+ * The <button> lives inside the Button child, so `.attachment-item :global(.remove)`
131
+ * anchors on the real `.attachment-item` element and pierces the child scope to
132
+ * keep the compact error-colored icon styling (issue #1589).
133
+ */
134
+ .attachment-item :global(.remove) {
126
135
  background: none;
127
136
  border: none;
128
- cursor: pointer;
129
137
  padding: 0 var(--smrt-spacing-1, 4px);
130
138
  color: var(--smrt-color-error, #ba1a1a);
131
139
  font-size: var(--smrt-typography-label-large-size, 14px);
@@ -148,7 +156,11 @@ export interface Props {
148
156
  cursor: pointer;
149
157
  }
150
158
 
151
- .file-input {
159
+ /*
160
+ * The native file input stays visually hidden — the visible affordance is the
161
+ * `.upload-text` label inside the styled drop-zone (issue #1589).
162
+ */
163
+ .upload-label .file-input {
152
164
  display: none;
153
165
  }
154
166
 
@@ -1 +1 @@
1
- {"version":3,"file":"AttachmentUpload.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AttachmentUpload.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,KAAK;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA6ED,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"AttachmentUpload.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AttachmentUpload.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,KAAK;IACpB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgFD,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -18,6 +18,8 @@ export interface Props {
18
18
 
19
19
  <script lang="ts">
20
20
  import { useI18n } from '@happyvertical/smrt-ui/i18n';
21
+ import { Form, Input, Select, Textarea } from '@happyvertical/smrt-ui/forms';
22
+ import { Button } from '@happyvertical/smrt-ui/ui';
21
23
  import { M } from '../i18n.js';
22
24
  import RecipientInput from './RecipientInput.svelte';
23
25
  import AttachmentUpload from './AttachmentUpload.svelte';
@@ -137,11 +139,12 @@ export interface Props {
137
139
  }
138
140
  </script>
139
141
 
140
- <form class="compose-form" onsubmit={(e) => { e.preventDefault(); handleSend(); }}>
142
+ <div class="compose-form-shell">
143
+ <Form class="compose-form" onsubmit={handleSend}>
141
144
  {#if accounts.length > 1}
142
145
  <div class="field">
143
146
  <label class="field-label" for="compose-account">From</label>
144
- <select
147
+ <Select
145
148
  id="compose-account"
146
149
  class="select"
147
150
  bind:value={accountId}
@@ -152,7 +155,7 @@ export interface Props {
152
155
  {account.name}{account.email ? ` <${account.email}>` : ''}
153
156
  </option>
154
157
  {/each}
155
- </select>
158
+ </Select>
156
159
  </div>
157
160
  {/if}
158
161
 
@@ -182,17 +185,17 @@ export interface Props {
182
185
  {#if !showCc || !showBcc}
183
186
  <div class="cc-toggles">
184
187
  {#if !showCc}
185
- <button type="button" class="link-btn" onclick={() => showCc = true}>Cc</button>
188
+ <Button variant="ghost" size="sm" class="link-btn" onclick={() => showCc = true}>Cc</Button>
186
189
  {/if}
187
190
  {#if !showBcc}
188
- <button type="button" class="link-btn" onclick={() => showBcc = true}>Bcc</button>
191
+ <Button variant="ghost" size="sm" class="link-btn" onclick={() => showBcc = true}>Bcc</Button>
189
192
  {/if}
190
193
  </div>
191
194
  {/if}
192
195
 
193
196
  <div class="field">
194
197
  <label class="field-label" for="compose-subject">Subject</label>
195
- <input
198
+ <Input
196
199
  id="compose-subject"
197
200
  type="text"
198
201
  class="text-input"
@@ -204,7 +207,7 @@ export interface Props {
204
207
  {:else if type === 'slack'}
205
208
  <div class="field">
206
209
  <label class="field-label" for="compose-channel">Channel</label>
207
- <input
210
+ <Input
208
211
  id="compose-channel"
209
212
  type="text"
210
213
  class="text-input"
@@ -216,13 +219,12 @@ export interface Props {
216
219
  {/if}
217
220
 
218
221
  <div class="body-field">
219
- <textarea
220
- class="body-input"
222
+ <Textarea
221
223
  bind:value={body}
222
224
  oninput={markDirty}
223
225
  placeholder={type === 'tweet' ? "What's happening?" : 'Write your message...'}
224
226
  rows={type === 'tweet' ? 4 : 10}
225
- ></textarea>
227
+ />
226
228
  {#if type === 'tweet'}
227
229
  <div class="char-count" class:over-limit={isOverLimit}>
228
230
  {charCount}/280
@@ -259,24 +261,31 @@ export interface Props {
259
261
  {/if}
260
262
 
261
263
  <div class="actions">
262
- <button
264
+ <Button
263
265
  type="submit"
264
- class="btn-primary"
266
+ variant="primary"
265
267
  disabled={isSending || isOverLimit}
266
268
  >
267
269
  {isSending ? 'Sending...' : 'Send'}
268
- </button>
269
- <button type="button" class="btn-secondary" onclick={handleSaveDraft}>
270
+ </Button>
271
+ <Button variant="secondary" onclick={handleSaveDraft}>
270
272
  {t(M['messages.compose_form.save_draft'])}
271
- </button>
272
- <button type="button" class="btn-text" onclick={() => ondiscard?.()}>
273
+ </Button>
274
+ <Button variant="ghost" class="btn-text" onclick={() => ondiscard?.()}>
273
275
  Discard
274
- </button>
276
+ </Button>
275
277
  </div>
276
- </form>
278
+ </Form>
279
+ </div>
277
280
 
278
281
  <style>
279
- .compose-form {
282
+ /*
283
+ * The form now renders through smrt-ui's <Form> (Provider-free base `<form>`).
284
+ * `class="compose-form"` lands on the real `<form>` inside the Form child, so
285
+ * `.compose-form-shell :global(.compose-form)` anchors on the wrapper and
286
+ * pierces the child scope to keep the column layout / padding (issue #1589).
287
+ */
288
+ .compose-form-shell :global(.compose-form) {
280
289
  display: flex;
281
290
  flex-direction: column;
282
291
  gap: var(--smrt-spacing-2, 8px);
@@ -298,11 +307,22 @@ export interface Props {
298
307
  min-width: 56px;
299
308
  }
300
309
 
301
- .select,
302
- .text-input {
310
+ /*
311
+ * The From <Select> and Subject/Channel <Input>s now render through smrt-ui's
312
+ * form primitives. These are naked, borderless inline fields that sit on the
313
+ * `.field` row's bottom-border, so `.field :global(.select)` /
314
+ * `.field :global(.text-input)` pierce the child scopes to strip the
315
+ * primitives' border / background / focus box-shadow and restore the flush
316
+ * inline look. `appearance: auto` brings back the Select's native arrow (the
317
+ * primitive paints a chevron on its own background, which we've cleared) —
318
+ * issue #1589.
319
+ */
320
+ .field :global(.select),
321
+ .field :global(.text-input) {
303
322
  flex: 1;
304
323
  border: none;
305
324
  outline: none;
325
+ box-shadow: none;
306
326
  font-family: inherit;
307
327
  font-size: var(--smrt-typography-body-medium-size, 14px);
308
328
  padding: var(--smrt-spacing-2, 8px) 0;
@@ -310,16 +330,32 @@ export interface Props {
310
330
  color: var(--smrt-color-on-surface, #1c1b1f);
311
331
  }
312
332
 
333
+ .field :global(.select) {
334
+ appearance: auto;
335
+ cursor: pointer;
336
+ }
337
+
338
+ .field :global(.select):focus,
339
+ .field :global(.text-input):focus {
340
+ border: none;
341
+ box-shadow: none;
342
+ }
343
+
313
344
  .cc-toggles {
314
345
  display: flex;
315
346
  gap: var(--smrt-spacing-2, 8px);
316
347
  justify-content: flex-end;
317
348
  }
318
349
 
319
- .link-btn {
350
+ /*
351
+ * The Cc/Bcc toggles now render through smrt-ui's <Button variant="ghost">.
352
+ * `.cc-toggles :global(.link-btn)` anchors on the real `.cc-toggles` element
353
+ * and pierces the Button child scope to keep the underlined text-link look
354
+ * (issue #1589).
355
+ */
356
+ .cc-toggles :global(.link-btn) {
320
357
  background: none;
321
358
  border: none;
322
- cursor: pointer;
323
359
  color: var(--smrt-color-primary, #6750a4);
324
360
  font-size: var(--smrt-typography-label-large-size, 13px);
325
361
  text-decoration: underline;
@@ -329,24 +365,6 @@ export interface Props {
329
365
  position: relative;
330
366
  }
331
367
 
332
- .body-input {
333
- width: 100%;
334
- border: 1px solid var(--smrt-color-outline-variant, #cac4d0);
335
- border-radius: var(--smrt-radius-md, 12px);
336
- padding: var(--smrt-spacing-3, 12px);
337
- font-family: var(--smrt-font-family, system-ui);
338
- font-size: var(--smrt-typography-body-medium-size, 14px);
339
- resize: vertical;
340
- background: var(--smrt-color-surface, #fffbfe);
341
- color: var(--smrt-color-on-surface, #1c1b1f);
342
- box-sizing: border-box;
343
- }
344
-
345
- .body-input:focus {
346
- outline: 2px solid var(--smrt-color-primary, #6750a4);
347
- outline-offset: -1px;
348
- }
349
-
350
368
  .char-count {
351
369
  text-align: right;
352
370
  font-size: var(--smrt-typography-label-medium-size, 12px);
@@ -373,40 +391,13 @@ export interface Props {
373
391
  padding-top: var(--smrt-spacing-2, 8px);
374
392
  }
375
393
 
376
- .btn-primary {
377
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-6, 24px);
378
- border-radius: var(--smrt-radius-full, 20px);
379
- border: none;
380
- background: var(--smrt-color-primary, #6750a4);
381
- color: var(--smrt-color-on-primary, #fff);
382
- font-family: var(--smrt-font-family, system-ui);
383
- font-size: var(--smrt-typography-label-large-size, 14px);
384
- cursor: pointer;
385
- }
386
-
387
- .btn-primary:disabled {
388
- opacity: 0.6;
389
- cursor: not-allowed;
390
- }
391
-
392
- .btn-secondary {
393
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
394
- border-radius: var(--smrt-radius-full, 20px);
395
- border: 1px solid var(--smrt-color-outline, #79747e);
396
- background: transparent;
397
- color: var(--smrt-color-primary, #6750a4);
398
- font-family: var(--smrt-font-family, system-ui);
399
- font-size: var(--smrt-typography-label-large-size, 14px);
400
- cursor: pointer;
401
- }
402
-
403
- .btn-text {
404
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
405
- border: none;
406
- background: transparent;
394
+ /*
395
+ * Send/Save-draft now use Button's primary/secondary variants directly (dead
396
+ * .btn-primary/.btn-secondary CSS removed). The Discard button keeps its
397
+ * neutral on-surface-variant text via `.actions :global(.btn-text)` (Button's
398
+ * ghost uses the primary color) — issue #1589.
399
+ */
400
+ .actions :global(.btn-text) {
407
401
  color: var(--smrt-color-on-surface-variant, #49454f);
408
- font-family: var(--smrt-font-family, system-ui);
409
- font-size: var(--smrt-typography-label-large-size, 14px);
410
- cursor: pointer;
411
402
  }
412
403
  </style>
@@ -1 +1 @@
1
- {"version":3,"file":"ComposeForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ComposeForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EAEX,YAAY,EAEb,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAoOD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"ComposeForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ComposeForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EAEX,YAAY,EAEb,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACnC,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AA0OD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}