@soft-toast/vue 1.0.1 → 1.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.
@@ -28,7 +28,6 @@
28
28
  .soft-toast-container[data-position="bottom"] { bottom: 32px; left: 50%; transform: translateX(-50%); }
29
29
  .soft-toast-container[data-position="left"] { top: 50%; left: 32px; transform: translateY(-50%); }
30
30
  .soft-toast-container[data-position="right"] { top: 50%; right: 32px; transform: translateY(-50%); }
31
- .soft-toast-container[data-position="center"] { top: 50%; left: 50%; transform: translate(-50%, -50%); }
32
31
 
33
32
  /* ---- Toast Item ---- */
34
33
  .soft-toast-item {
@@ -45,8 +44,7 @@
45
44
  line-height: 1.45;
46
45
  cursor: default;
47
46
  user-select: none;
48
- will-change: transform, opacity;
49
- touch-action: pan-y; /* allow vertical scroll, intercept horizontal for swipe */
47
+ touch-action: pan-y;
50
48
 
51
49
  /* Clean modern white card */
52
50
  background: rgba(255, 255, 255, 0.98);
@@ -56,9 +54,20 @@
56
54
  inset 0 1px 0 rgba(255, 255, 255, 1);
57
55
  }
58
56
 
57
+ .soft-toast-item[data-interactive="false"] {
58
+ pointer-events: none;
59
+ touch-action: none;
60
+ }
61
+
62
+ .soft-toast-item[data-leaving="true"] {
63
+ pointer-events: none;
64
+ touch-action: none;
65
+ }
66
+
59
67
  /* Show grab cursor on swipeable toasts to hint at the gesture */
60
68
  .soft-toast-item--swipeable {
61
69
  cursor: grab;
70
+ touch-action: none;
62
71
  }
63
72
  .soft-toast-item--swipeable:active {
64
73
  cursor: grabbing;
@@ -101,6 +110,8 @@
101
110
 
102
111
  /* ---- Content layout ---- */
103
112
  .soft-toast-content {
113
+ position: relative;
114
+ z-index: 1;
104
115
  display: flex;
105
116
  align-items: flex-start;
106
117
  gap: 11px;
@@ -111,7 +122,7 @@
111
122
  flex-shrink: 0;
112
123
  width: 24px;
113
124
  height: 24px;
114
- margin-top: 1px;
125
+ margin-top: 0;
115
126
  display: flex;
116
127
  align-items: center;
117
128
  justify-content: center;
@@ -155,6 +166,7 @@
155
166
  display: flex;
156
167
  align-items: center;
157
168
  gap: 12px;
169
+ min-height: 24px;
158
170
  }
159
171
 
160
172
  .soft-toast-title {
@@ -162,8 +174,8 @@
162
174
  font-size: 14px;
163
175
  color: #111827;
164
176
  margin: 0;
165
- line-height: 1.4;
166
- letter-spacing: -0.01em;
177
+ line-height: 1.3;
178
+ letter-spacing: 0;
167
179
  /* Slight right padding by default so text doesn't bump against close button on hover */
168
180
  padding-right: 4px;
169
181
  }
@@ -182,17 +194,20 @@
182
194
  max-height: 120px;
183
195
  overflow-y: auto;
184
196
  padding-right: 4px;
197
+ scrollbar-width: none;
185
198
  }
186
199
 
187
- /* Custom Scrollbar for long descriptions */
188
- .soft-toast-description::-webkit-scrollbar { width: 4px; }
189
- .soft-toast-description::-webkit-scrollbar-track { background: transparent; }
190
- .soft-toast-description::-webkit-scrollbar-thumb {
191
- background: rgba(0, 0, 0, 0.1);
200
+ /* Custom Scrollbar for long descriptions — hidden by default, shown on hover */
201
+ .soft-toast-description::-webkit-scrollbar { width: 0; }
202
+ .soft-toast-item:hover .soft-toast-description { scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.15) transparent; }
203
+ .soft-toast-item:hover .soft-toast-description::-webkit-scrollbar { width: 4px; }
204
+ .soft-toast-item:hover .soft-toast-description::-webkit-scrollbar-track { background: transparent; }
205
+ .soft-toast-item:hover .soft-toast-description::-webkit-scrollbar-thumb {
206
+ background: rgba(0, 0, 0, 0.15);
192
207
  border-radius: 4px;
193
208
  }
194
- .soft-toast-description::-webkit-scrollbar-thumb:hover {
195
- background: rgba(0, 0, 0, 0.2);
209
+ .soft-toast-item:hover .soft-toast-description::-webkit-scrollbar-thumb:hover {
210
+ background: rgba(0, 0, 0, 0.25);
196
211
  }
197
212
 
198
213
  /* Timestamp — lives BELOW all content, never overlaps close button */
@@ -217,6 +232,7 @@
217
232
  width: 100%;
218
233
  padding: 8px 16px;
219
234
  border-radius: 12px;
235
+ background: rgba(100, 116, 139, 0.12); /* fallback for Safari < 16.2 */
220
236
  background: color-mix(in srgb, var(--st-accent) 15%, transparent);
221
237
  color: var(--st-icon-color);
222
238
  border: none;
@@ -229,6 +245,7 @@
229
245
  text-align: center;
230
246
  }
231
247
  .soft-toast-action-button:hover {
248
+ background: rgba(100, 116, 139, 0.22); /* fallback for Safari < 16.2 */
232
249
  background: color-mix(in srgb, var(--st-accent) 25%, transparent);
233
250
  transform: scale(1.02);
234
251
  }
@@ -247,6 +264,7 @@
247
264
  /* Close Button */
248
265
  .soft-toast-close {
249
266
  position: absolute;
267
+ z-index: 3;
250
268
  top: 10px;
251
269
  right: 10px;
252
270
  width: 22px;
@@ -269,6 +287,10 @@
269
287
  transform: scale(1.1);
270
288
  }
271
289
  .soft-toast-item:hover .soft-toast-close { opacity: 1; }
290
+ /* iOS/touch: no hover state — always show close button */
291
+ @media (hover: none) {
292
+ .soft-toast-close { opacity: 0.7; }
293
+ }
272
294
  .soft-toast-close[data-position="top-left"] { right: auto; left: 10px; }
273
295
 
274
296
  /* Morph X to Minus on Hover */
@@ -344,6 +366,23 @@
344
366
  .soft-toast-close { opacity: 1; }
345
367
  }
346
368
 
369
+ /* ---- Collapsed stack: only front toast is touchable on mobile ---- */
370
+ /* Prevents hidden stacked toasts from intercepting touch/scroll on the page */
371
+ @media (hover: none) {
372
+ .soft-toast-container:not([data-expanded="true"]) .soft-toast-item[data-interactive="false"] {
373
+ pointer-events: none;
374
+ touch-action: none;
375
+ }
376
+ /* Front toast in collapsed stack: no swipe gesture — tap to expand only */
377
+ .soft-toast-container:not([data-expanded="true"]) .soft-toast-item[data-st-index="0"] {
378
+ touch-action: manipulation;
379
+ }
380
+ /* Expanded: all toasts can swipe — JS handles both axes */
381
+ .soft-toast-container[data-expanded="true"] .soft-toast-item[data-interactive="true"] {
382
+ touch-action: none;
383
+ }
384
+ }
385
+
347
386
  /* ---- Reduced Motion ---- */
348
387
  @media (prefers-reduced-motion: reduce) {
349
388
  .soft-toast-item,
@@ -1,7 +1,7 @@
1
1
  import type { VNode, Component } from 'vue'
2
2
 
3
3
  export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info' | 'promise'
4
- export type ToastPosition = 'top' | 'bottom' | 'left' | 'right' | 'center' | 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
4
+ export type ToastPosition = 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
5
5
  export type AnimationPreset = 'smooth' | 'bouncy' | 'subtle' | 'snappy'
6
6
  export type QueueOverflow = 'drop-oldest' | 'drop-newest'
7
7
 
@@ -13,13 +13,13 @@ export interface ToastAction {
13
13
  class?: string
14
14
  }
15
15
 
16
- export interface ToastPromiseMessages {
16
+ export interface ToastPromiseMessages<T = unknown> {
17
17
  loading: string
18
- success: string
19
- error: string
18
+ success: string | ((data: T) => string)
19
+ error: string | ((err: unknown) => string)
20
20
  description?: {
21
- success?: string
22
- error?: string
21
+ success?: string | ((data: T) => string)
22
+ error?: string | ((err: unknown) => string)
23
23
  }
24
24
  action?: {
25
25
  error?: ToastAction
@@ -108,8 +108,10 @@ export interface ToastContainerProps {
108
108
  queueOverflow?: QueueOverflow
109
109
  dir?: 'ltr' | 'rtl'
110
110
  swipeToDismiss?: boolean
111
+ slotFilter?: (toast: Toast) => boolean
111
112
  }
112
113
 
113
114
  export interface ToastPluginOptions extends ToastContainerProps {
114
115
  teleportTarget?: string
116
+ autoMount?: boolean
115
117
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"useToast.d.ts","sourceRoot":"","sources":["../../src/composables/useToast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAMlE,eAAO,MAAM,QAAQ;qBACF,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAGtD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;mBAGxD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAGpD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;kBAGzD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAGnD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;cAG7D,CAAC,aACE,OAAO,CAAC,CAAC,CAAC,YACX,oBAAoB,YACpB,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAAC,KACnE,OAAO,CAAC,CAAC,CAAC;sBAEK,YAAY;iBAEjB,MAAM,WAAW,OAAO,CAAC,YAAY,CAAC;mBAEpC,MAAM;;gBAGT,MAAM;iBACL,MAAM;IAEnB;;;;;;;;;OASG;mBACY,MAAM,YAAW,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAGjE;;;OAGG;;IAGH,wEAAwE;;CAExE,CAAA;AAIF,eAAO,MAAM,KAAK;qBACC,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAEtD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;mBAExD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAEpD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;kBAEzD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;qBAEnD,MAAM,YAAY,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;cAE7D,CAAC,aACE,OAAO,CAAC,CAAC,CAAC,YACX,oBAAoB,YACpB,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAAC,KACnE,OAAO,CAAC,CAAC,CAAC;sBACK,YAAY;iBACjB,MAAM,WAAW,OAAO,CAAC,YAAY,CAAC;mBACpC,MAAM;;gBAET,MAAM;iBACL,MAAM;mBACJ,MAAM,YAAW,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;;;CAIlE,CAAA"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=useToast.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useToast.test.d.ts","sourceRoot":"","sources":["../../src/composables/useToast.test.ts"],"names":[],"mappings":""}