@product7/feedback-sdk 1.1.7 → 1.1.9

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.
@@ -1,6 +1,6 @@
1
1
  export const CSS_STYLES = `
2
2
  .feedback-widget {
3
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', Oxygen, Ubuntu, Cantarell, sans-serif;
4
4
  font-size: 14px;
5
5
  line-height: 1.4;
6
6
  z-index: 999999;
@@ -38,146 +38,105 @@ export const CSS_STYLES = `
38
38
  left: 20px;
39
39
  }
40
40
 
41
- .feedback-widget-button.position-bottom-center {
42
- bottom: 20px;
43
- left: 50%;
44
- transform: translateX(-50%);
45
- }
46
-
47
- .feedback-widget-button.position-top-center {
48
- top: 20px;
49
- left: 50%;
50
- transform: translateX(-50%);
51
- }
52
-
53
- .feedback-widget-button.position-center {
54
- top: 50%;
55
- left: 50%;
56
- transform: translate(-50%, -50%);
57
- }
58
-
59
- /* New button design - white with elevation */
60
41
  .feedback-trigger-btn {
61
- width: 52px;
62
- height: 52px;
63
- border-radius: 50%;
64
- border: none;
65
- background: #ffffff;
66
- cursor: pointer;
42
+ position: relative;
67
43
  display: flex;
68
44
  align-items: center;
69
45
  justify-content: center;
70
- box-shadow:
71
- 0 2px 4px rgba(0, 0, 0, 0.1),
72
- 0 8px 16px rgba(0, 0, 0, 0.15),
73
- 0 0 1px rgba(0, 0, 0, 0.1);
74
- transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
75
- padding: 0;
76
- }
77
-
78
- .feedback-trigger-btn:hover {
79
- box-shadow:
80
- 0 4px 8px rgba(0, 0, 0, 0.12),
81
- 0 12px 24px rgba(0, 0, 0, 0.2),
82
- 0 0 1px rgba(0, 0, 0, 0.1);
83
- transform: translateY(-2px);
46
+ gap: 12px;
47
+ height: 44px;
48
+ overflow: hidden;
49
+ border-radius: 0.5rem;
50
+ border: none;
51
+ padding: 10px 16px;
52
+ font-size: 14px;
53
+ font-weight: 500;
54
+ font-family: inherit;
55
+ cursor: pointer;
56
+ transition: all 0.3s ease;
57
+ color: white;
58
+ background: #155EEF;
59
+ box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.05);
84
60
  }
85
61
 
86
- .feedback-trigger-btn:active {
87
- transform: translateY(0px);
88
- box-shadow:
89
- 0 1px 3px rgba(0, 0, 0, 0.1),
90
- 0 4px 12px rgba(0, 0, 0, 0.12),
91
- 0 0 1px rgba(0, 0, 0, 0.1);
62
+ .feedback-trigger-btn:hover:not(:disabled) {
63
+ background: #004EEB;
64
+ box-shadow: 0 1px 2px 0 rgba(16, 24, 40, 0.1);
92
65
  }
93
66
 
94
- .feedback-trigger-btn svg {
95
- flex-shrink: 0;
96
- width: 22px;
97
- height: 25px;
67
+ .feedback-trigger-btn:disabled {
68
+ opacity: 0.7;
69
+ cursor: not-allowed;
98
70
  }
99
71
 
100
- .feedback-trigger-btn svg path {
101
- fill: #21244A;
72
+ .feedback-trigger-btn:focus-visible {
73
+ outline: 2px solid #155EEF;
74
+ outline-offset: 2px;
102
75
  }
103
76
 
104
- /* Loading Modal */
105
- .feedback-loading-modal {
106
- position: fixed;
107
- top: 50%;
108
- left: 50%;
109
- transform: translate(-50%, -50%) scale(0.9);
110
- z-index: 1000001;
77
+ .feedback-close-btn {
78
+ position: absolute;
79
+ top: -8px;
80
+ right: -8px;
81
+ width: 24px;
82
+ height: 24px;
83
+ border-radius: 50%;
84
+ background: #EF4444;
85
+ border: 2px solid white;
86
+ color: white;
87
+ cursor: pointer;
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
111
91
  opacity: 0;
112
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
92
+ transition: all 0.2s ease;
93
+ z-index: 10;
94
+ padding: 0;
113
95
  }
114
96
 
115
- .feedback-loading-modal.show {
97
+ .feedback-widget-button:hover .feedback-close-btn {
116
98
  opacity: 1;
117
- transform: translate(-50%, -50%) scale(1);
118
- }
119
-
120
- .feedback-loading-spinner {
121
- width: 48px;
122
- height: 48px;
123
- border: 4px solid rgba(0, 0, 0, 0.1);
124
- border-top-color: #21244A;
125
- border-radius: 50%;
126
- animation: spin 0.8s linear infinite;
127
99
  }
128
100
 
129
- @keyframes spin {
130
- to { transform: rotate(360deg); }
101
+ .feedback-close-btn:hover {
102
+ background: #DC2626;
103
+ transform: scale(1.1);
131
104
  }
132
105
 
133
- /* Modal Styles (centered) */
134
- .feedback-modal {
135
- position: fixed;
136
- top: 50%;
137
- left: 50%;
138
- transform: translate(-50%, -50%) scale(0.9);
139
- width: 480px;
140
- max-width: 90vw;
141
- max-height: 85vh;
142
- z-index: 1000000;
143
- opacity: 0;
144
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
145
- font-family: inherit;
146
- }
147
-
148
- .feedback-modal.open {
149
- opacity: 1;
150
- transform: translate(-50%, -50%) scale(1);
151
- }
152
-
153
- .feedback-modal .feedback-panel-content {
154
- max-height: 85vh;
155
- overflow-y: auto;
106
+ .feedback-close-btn:focus-visible {
107
+ outline: 2px solid #155EEF;
108
+ outline-offset: 2px;
156
109
  }
157
110
 
158
- /* Size variants */
159
- .feedback-modal.size-small {
160
- width: 360px;
111
+ .feedback-close-btn svg {
112
+ width: 10px;
113
+ height: 10px;
161
114
  }
162
115
 
163
- .feedback-modal.size-medium {
164
- width: 480px;
116
+ /* Minimized state */
117
+ .feedback-widget-button.minimized {
118
+ transform: scale(0.4);
119
+ opacity: 0.3;
120
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
165
121
  }
166
122
 
167
- .feedback-modal.size-large {
168
- width: 600px;
123
+ .feedback-widget-button.minimized:hover {
124
+ opacity: 0.6;
125
+ transform: scale(0.5);
169
126
  }
170
127
 
171
- .feedback-panel.size-small {
172
- width: 320px;
128
+ .feedback-widget-button.minimized .feedback-trigger-btn {
129
+ pointer-events: none;
173
130
  }
174
131
 
175
- .feedback-panel.size-medium {
176
- width: 420px;
132
+ .feedback-widget-button.minimized .feedback-close-btn {
133
+ opacity: 1;
134
+ background: #10B981;
135
+ pointer-events: auto;
177
136
  }
178
137
 
179
- .feedback-panel.size-large {
180
- width: 520px;
138
+ .feedback-widget-button.minimized .feedback-close-btn:hover {
139
+ background: #059669;
181
140
  }
182
141
 
183
142
  /* Side Panel Styles */
@@ -203,8 +162,7 @@ export const CSS_STYLES = `
203
162
  left: 0;
204
163
  right: 0;
205
164
  bottom: 0;
206
- background: rgba(0, 0, 0, 0.4);
207
- backdrop-filter: blur(4px);
165
+ background: rgba(0, 0, 0, 0.1);
208
166
  opacity: 0;
209
167
  transition: opacity 0.3s ease;
210
168
  pointer-events: none;
@@ -217,60 +175,84 @@ export const CSS_STYLES = `
217
175
  }
218
176
 
219
177
  .feedback-panel-content {
220
- background: var(--bg-color, #ffffff);
221
- color: var(--text-color, #171717);
178
+ background: white;
222
179
  height: 100%;
223
180
  display: flex;
224
181
  flex-direction: column;
225
- border-radius: 12px;
226
- border: 1px solid #e5e5e5;
182
+ border-radius: 16px;
183
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
184
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04),
185
+ 0 0 0 1px rgba(0, 0, 0, 0.05);
186
+ }
187
+
188
+ .feedback-panel.theme-dark .feedback-panel-content {
189
+ background: #1F2937;
190
+ color: white;
227
191
  }
228
192
 
229
193
  .feedback-panel-header {
230
194
  display: flex;
231
195
  align-items: center;
232
196
  justify-content: space-between;
233
- padding: 24px 24px 20px 24px;
197
+ padding: 24px;
198
+ border-bottom: 1px solid #E5E7EB;
234
199
  flex-shrink: 0;
235
200
  }
236
201
 
202
+ .feedback-panel.theme-dark .feedback-panel-header {
203
+ border-bottom-color: #374151;
204
+ }
205
+
237
206
  .feedback-panel-header h3 {
238
207
  margin: 0;
239
208
  font-size: 18px;
240
209
  font-weight: 600;
241
- color: var(--text-color, #171717);
210
+ color: #111827;
211
+ }
212
+
213
+ .feedback-panel.theme-dark .feedback-panel-header h3 {
214
+ color: white;
242
215
  }
243
216
 
244
217
  .feedback-panel-close {
245
218
  background: none;
246
219
  border: none;
247
- font-size: 20px;
220
+ font-size: 24px;
248
221
  cursor: pointer;
249
- color: #737373;
250
- padding: 0;
222
+ color: #6B7280;
223
+ padding: 4px;
251
224
  width: 32px;
252
225
  height: 32px;
253
226
  display: flex;
254
227
  align-items: center;
255
228
  justify-content: center;
256
- border-radius: 8px;
257
- transition: all 0.15s ease;
229
+ border-radius: 6px;
230
+ transition: all 0.2s ease;
258
231
  }
259
232
 
260
233
  .feedback-panel-close:hover {
261
- background: #f5f5f5;
262
- color: #171717;
234
+ background: #F3F4F6;
235
+ color: #111827;
263
236
  }
264
237
 
265
238
  .feedback-panel-close:focus-visible {
266
- outline: 2px solid var(--primary-color, #21244A);
239
+ outline: 2px solid #155EEF;
267
240
  outline-offset: 2px;
268
241
  }
269
242
 
243
+ .feedback-panel.theme-dark .feedback-panel-close {
244
+ color: #9CA3AF;
245
+ }
246
+
247
+ .feedback-panel.theme-dark .feedback-panel-close:hover {
248
+ background: #374151;
249
+ color: white;
250
+ }
251
+
270
252
  .feedback-panel-body {
271
253
  flex: 1;
272
254
  overflow-y: auto;
273
- padding: 0 24px 24px 24px;
255
+ padding: 24px;
274
256
  }
275
257
 
276
258
  .feedback-form {
@@ -280,59 +262,96 @@ export const CSS_STYLES = `
280
262
  }
281
263
 
282
264
  .feedback-form-group {
283
- margin-bottom: 16px;
265
+ display: flex;
266
+ flex-direction: column;
267
+ gap: 8px;
268
+ margin-bottom: 20px;
284
269
  }
285
270
 
286
271
  .feedback-form-group:last-child {
287
272
  margin-bottom: 0;
288
273
  }
289
274
 
290
- /* Unified input container */
291
- .feedback-input-container {
292
- border: 1px solid #e5e5e5;
293
- border-radius: 8px;
294
- padding: 16px;
295
- background: #ffffff;
296
- transition: all 0.15s ease;
275
+ .feedback-form-group label {
276
+ font-size: 14px;
277
+ font-weight: 500;
278
+ line-height: 1.25;
279
+ color: #374151;
297
280
  }
298
281
 
299
- .feedback-input-container:focus-within {
300
- border-color: var(--primary-color, #21244A);
301
- box-shadow: 0 0 0 3px rgba(33, 36, 74, 0.08);
282
+ .feedback-panel.theme-dark .feedback-form-group label {
283
+ color: #D1D5DB;
302
284
  }
303
285
 
304
- .feedback-form-group input,
305
- .feedback-form-group textarea {
286
+ .feedback-form-group input {
287
+ height: 44px;
306
288
  width: 100%;
307
- border: none;
308
- padding: 0;
309
- font-size: 14px;
289
+ border-radius: 8px;
290
+ border: 1px solid #D1D5DB;
291
+ padding: 10px 14px;
292
+ font-size: 15px;
293
+ font-weight: 400;
294
+ line-height: 1.5;
295
+ color: #1F2937;
310
296
  font-family: inherit;
311
- color: var(--text-color, #171717);
312
- background: transparent;
313
297
  outline: none;
314
- resize: none;
298
+ transition: all 0.2s ease;
315
299
  }
316
300
 
317
- .feedback-form-group input {
318
- font-weight: 600;
301
+ .feedback-form-group input::placeholder {
319
302
  font-size: 15px;
320
- margin-bottom: 12px;
303
+ color: #9CA3AF;
321
304
  }
322
305
 
323
- .feedback-form-group input::placeholder {
324
- color: #737373;
325
- font-weight: 600;
306
+ .feedback-form-group input:focus {
307
+ border-color: #155EEF;
308
+ box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
309
+ }
310
+
311
+ .feedback-form-group input:focus-visible {
312
+ outline: none;
326
313
  }
327
314
 
328
315
  .feedback-form-group textarea {
329
- min-height: 120px;
316
+ min-height: 200px;
317
+ width: 100%;
318
+ resize: vertical;
319
+ border-radius: 8px;
320
+ border: 1px solid #D1D5DB;
321
+ padding: 10px 14px;
322
+ font-size: 15px;
330
323
  font-weight: 400;
324
+ line-height: 1.5;
325
+ color: #1F2937;
326
+ font-family: inherit;
327
+ outline: none;
328
+ transition: all 0.2s ease;
331
329
  }
332
330
 
333
331
  .feedback-form-group textarea::placeholder {
334
- color: #a3a3a3;
335
- font-weight: 400;
332
+ font-size: 15px;
333
+ color: #9CA3AF;
334
+ }
335
+
336
+ .feedback-form-group textarea:focus {
337
+ border-color: #155EEF;
338
+ box-shadow: 0 0 0 3px rgba(21, 94, 239, 0.1);
339
+ }
340
+
341
+ .feedback-form-group textarea:focus-visible {
342
+ outline: none;
343
+ }
344
+
345
+ .feedback-panel.theme-dark .feedback-form-group input,
346
+ .feedback-panel.theme-dark .feedback-form-group textarea {
347
+ background: #374151;
348
+ border-color: #4B5563;
349
+ color: white;
350
+ }
351
+
352
+ .feedback-panel.theme-dark .feedback-form-group input::placeholder,
353
+ .feedback-panel.theme-dark .feedback-form-group textarea::placeholder {
354
+ color: #6B7280;
336
355
  }
337
356
 
338
357
  .feedback-btn {
@@ -349,7 +368,7 @@ export const CSS_STYLES = `
349
368
  font-weight: 500;
350
369
  font-family: inherit;
351
370
  cursor: pointer;
352
- transition: all 0.15s ease;
371
+ transition: all 0.2s ease;
353
372
  }
354
373
 
355
374
  .feedback-btn:disabled {
@@ -358,32 +377,62 @@ export const CSS_STYLES = `
358
377
  }
359
378
 
360
379
  .feedback-btn:focus-visible {
361
- outline: 2px solid #21244A;
380
+ outline: 2px solid #155EEF;
362
381
  outline-offset: 2px;
363
382
  }
364
383
 
365
384
  .feedback-btn-submit {
366
- background: var(--primary-color, #21244A);
385
+ background: #155EEF;
367
386
  color: white;
368
387
  width: 100%;
369
388
  }
370
389
 
371
390
  .feedback-btn-submit:hover:not(:disabled) {
372
- background: #2d3159;
391
+ background: #1A56DB;
373
392
  }
374
393
 
375
394
  .feedback-btn-submit:active:not(:disabled) {
376
- transform: scale(0.98);
395
+ background: #1E429F;
396
+ }
397
+
398
+ .feedback-btn-cancel {
399
+ background: transparent;
400
+ color: #6B7280;
401
+ border: 1px solid #D1D5DB;
402
+ }
403
+
404
+ .feedback-btn-cancel:hover:not(:disabled) {
405
+ background: #F9FAFB;
406
+ border-color: #9CA3AF;
407
+ color: #374151;
408
+ }
409
+
410
+ .feedback-panel.theme-dark .feedback-btn-cancel {
411
+ color: #D1D5DB;
412
+ border-color: #4B5563;
413
+ }
414
+
415
+ .feedback-panel.theme-dark .feedback-btn-cancel:hover:not(:disabled) {
416
+ background: #374151;
417
+ }
418
+
419
+ .feedback-form-actions {
420
+ display: flex;
421
+ flex-direction: column;
422
+ gap: 12px;
423
+ margin-top: auto;
424
+ padding-top: 24px;
377
425
  }
378
426
 
379
427
  .feedback-error {
380
- background: #FEF2F2;
381
- border: 1px solid #FEE2E2;
382
428
  color: #DC2626;
383
- padding: 12px 14px;
429
+ font-size: 14px;
430
+ font-weight: 400;
431
+ margin-top: 8px;
432
+ padding: 12px;
433
+ background: #FEE2E2;
434
+ border: 1px solid #FECACA;
384
435
  border-radius: 8px;
385
- font-size: 13px;
386
- margin-top: 12px;
387
436
  display: none;
388
437
  }
389
438
 
@@ -391,6 +440,12 @@ export const CSS_STYLES = `
391
440
  display: block;
392
441
  }
393
442
 
443
+ .feedback-panel.theme-dark .feedback-error {
444
+ background: #7F1D1D;
445
+ border-color: #991B1B;
446
+ color: #FCA5A5;
447
+ }
448
+
394
449
  .feedback-success-notification {
395
450
  position: fixed;
396
451
  top: 24px;
@@ -455,7 +510,7 @@ export const CSS_STYLES = `
455
510
  }
456
511
 
457
512
  .feedback-success-close:focus-visible {
458
- outline: 2px solid #21244A;
513
+ outline: 2px solid #155EEF;
459
514
  outline-offset: 2px;
460
515
  }
461
516
 
@@ -517,10 +572,18 @@ export const CSS_STYLES = `
517
572
  border-radius: 2px;
518
573
  }
519
574
 
575
+ .feedback-panel.theme-dark .feedback-panel-header::before {
576
+ background: #4B5563;
577
+ }
578
+
520
579
  .feedback-panel-body {
521
580
  padding: 20px;
522
581
  }
523
582
 
583
+ .feedback-form-group textarea {
584
+ min-height: 150px;
585
+ }
586
+
524
587
  .feedback-widget-button {
525
588
  bottom: 16px;
526
589
  right: 16px;
@@ -556,5 +619,35 @@ export const CSS_STYLES = `
556
619
  .feedback-success-notification {
557
620
  display: none !important;
558
621
  }
622
+
623
+ @media (max-width: 768px) {
624
+ .feedback-close-btn {
625
+ top: -6px;
626
+ right: -6px;
627
+ width: 20px;
628
+ height: 20px;
629
+ }
630
+
631
+ .feedback-close-btn svg {
632
+ width: 8px;
633
+ height: 8px;
634
+ }
635
+
636
+ .feedback-widget-button.minimized {
637
+ transform: scale(0.5);
638
+ }
639
+
640
+ .feedback-widget-button.minimized:hover {
641
+ transform: scale(0.6);
642
+ }
643
+ }
644
+
645
+ /* Reduced motion support */
646
+ @media (prefers-reduced-motion: reduce) {
647
+ .feedback-close-btn,
648
+ .feedback-widget-button.minimized {
649
+ transition: none;
650
+ }
651
+ }
559
652
  }
560
653
  `;
@@ -283,41 +283,44 @@ export class BaseWidget {
283
283
 
284
284
  _getPanelHTML() {
285
285
  return `
286
- <div class="feedback-panel-content">
287
- <div class="feedback-panel-header">
288
- <h3>Share Your Thoughts</h3>
289
- <button class="feedback-panel-close" type="button" aria-label="Close">&times;</button>
290
- </div>
291
- <div class="feedback-panel-body">
292
- <form class="feedback-form">
293
- <div class="feedback-form-group">
294
- <div class="feedback-input-container">
286
+ <div class="feedback-panel-content">
287
+ <div class="feedback-panel-header">
288
+ <h3>Send Feedback</h3>
289
+ <button class="feedback-panel-close" type="button" aria-label="Close">&times;</button>
290
+ </div>
291
+ <div class="feedback-panel-body">
292
+ <form class="feedback-form">
293
+ <div class="feedback-form-group">
294
+ <label for="feedback-title-${this.id}">Title (optional)</label>
295
295
  <input
296
296
  type="text"
297
297
  id="feedback-title-${this.id}"
298
298
  name="title"
299
- placeholder="Title"
299
+ placeholder="Brief description of your feedback"
300
300
  value="${this.state.title}"
301
301
  />
302
+ </div>
303
+ <div class="feedback-form-group">
304
+ <label for="feedback-content-${this.id}">Message *</label>
302
305
  <textarea
303
306
  id="feedback-content-${this.id}"
304
307
  name="content"
305
- placeholder="Tell us what's on your mind..."
308
+ placeholder="Tell us what you think..."
306
309
  required
307
310
  >${this.state.content}</textarea>
308
311
  </div>
309
- </div>
310
- <div class="feedback-error" role="alert"></div>
311
- <div class="feedback-form-group">
312
- <button type="submit" class="feedback-btn feedback-btn-submit">
313
- ${this.state.isSubmitting ? 'Sending...' : 'Submit Feedback'}
314
- </button>
315
- </div>
316
- </form>
312
+ <div class="feedback-error" role="alert"></div>
313
+ <div class="feedback-form-actions">
314
+ <button type="submit" class="feedback-btn feedback-btn-submit">
315
+ ${this.state.isSubmitting ? 'Sending...' : 'Send Feedback'}
316
+ </button>
317
+ </div>
318
+ </form>
319
+ </div>
317
320
  </div>
318
- </div>
319
- `;
321
+ `;
320
322
  }
323
+
321
324
  _attachPanelEvents() {
322
325
  const panel = this.panelElement;
323
326