@cohiva/support-widget 1.1.0 → 1.1.2

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.
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ module.exports = __toCommonJS(index_exports);
39
39
 
40
40
  // src/components/SupportWidget.tsx
41
41
  var import_react2 = require("react");
42
+ var import_lucide_react = require("lucide-react");
42
43
 
43
44
  // src/adapters/centralApi.ts
44
45
  function createCentralFeedbackClient(options) {
@@ -724,7 +725,7 @@ function buildFeedbackDescription(formData, diagnostics) {
724
725
  }
725
726
 
726
727
  // src/components/SupportWidget.tsx
727
- var import_widget = require("./widget-TTYCIVNC.css");
728
+ var import_widget = require("./widget-IHSQAQI2.css");
728
729
 
729
730
  // src/utils/classNames.ts
730
731
  function classNames(...items) {
@@ -733,6 +734,12 @@ function classNames(...items) {
733
734
 
734
735
  // src/components/SupportWidget.tsx
735
736
  var import_jsx_runtime = require("react/jsx-runtime");
737
+ var typeIconMap = {
738
+ bug: { icon: import_lucide_react.Bug, color: "#ef4444" },
739
+ feature: { icon: import_lucide_react.Lightbulb, color: "#f59e0b" },
740
+ feedback: { icon: import_lucide_react.MessageCircle, color: "#3b82f6" },
741
+ improvement: { icon: import_lucide_react.Wrench, color: "#8b5cf6" }
742
+ };
736
743
  function labelForType(type) {
737
744
  return feedbackTypes.find((item) => item.value === type)?.label || type;
738
745
  }
@@ -881,7 +888,7 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
881
888
  ]
882
889
  }
883
890
  ),
884
- isOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-overlay", onClick: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-modal-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
891
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-overlay", onClick: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
885
892
  "div",
886
893
  {
887
894
  "aria-describedby": "support-widget-description",
@@ -892,7 +899,8 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
892
899
  children: [
893
900
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { "aria-label": "Close", className: "sw-close", onClick: handleClose, type: "button", children: "x" }),
894
901
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "sw-sr-only", id: "support-widget-description", children: "Support ticket dialog" }),
895
- isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sw-success", "data-testid": "feedback-success-screen", children: [
902
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-modal-body", children: isSubmitted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sw-success", "data-testid": "feedback-success-screen", children: [
903
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.CheckCircle, { "aria-hidden": "true", className: "sw-success-icon", color: "#0f766e", size: 48 }),
896
904
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: "Thank You!" }),
897
905
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Your feedback helps us improve the product." }),
898
906
  submitResult?.issue_number || submitResult?.issue_url ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { "data-testid": "feedback-success-issue-link", children: [
@@ -904,23 +912,31 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
904
912
  ] }) : null
905
913
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
906
914
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "sw-header", children: [
907
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: step === 1 ? "Send Feedback" : selectedTypeConfig?.label || "Support Ticket" }),
908
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: step === 1 ? "What kind of support ticket would you like to submit?" : selectedTypeConfig?.description })
915
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: step === 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
916
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.MessageSquarePlus, { "aria-hidden": "true", className: "sw-header-icon", size: 22 }),
917
+ " Send Feedback"
918
+ ] }) : selectedTypeConfig?.label || "Support Ticket" }),
919
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: step === 1 ? "Help us improve Cohiva by sharing your experience" : selectedTypeConfig?.description })
909
920
  ] }),
910
- step === 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-type-grid", children: feedbackTypes.map((typeConfig) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
911
- "button",
912
- {
913
- className: "sw-type-card",
914
- "data-testid": `feedback-type-${typeConfig.value}`,
915
- onClick: () => handleTypeSelect(typeConfig.value),
916
- type: "button",
917
- children: [
918
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: typeConfig.label }),
919
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: typeConfig.description })
920
- ]
921
- },
922
- typeConfig.value
923
- )) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "sw-form", onSubmit: handleSubmit, children: [
921
+ step === 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sw-type-grid", children: feedbackTypes.map((typeConfig) => {
922
+ const entry = typeIconMap[typeConfig.value];
923
+ const Icon = entry?.icon;
924
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
925
+ "button",
926
+ {
927
+ className: "sw-type-card",
928
+ "data-testid": `feedback-type-${typeConfig.value}`,
929
+ onClick: () => handleTypeSelect(typeConfig.value),
930
+ type: "button",
931
+ children: [
932
+ Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", className: "sw-type-card-icon", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { color: entry.color, size: 36, strokeWidth: 1.5 }) }) : null,
933
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: typeConfig.label }),
934
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: typeConfig.description })
935
+ ]
936
+ },
937
+ typeConfig.value
938
+ );
939
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: "sw-form", onSubmit: handleSubmit, children: [
924
940
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "support-title", children: "Title *" }),
925
941
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
926
942
  "input",
@@ -1020,13 +1036,16 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
1020
1036
  !validation.valid ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "sw-error", children: validation.description }) : null,
1021
1037
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sw-actions", children: [
1022
1038
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setStep(1), type: "button", children: "Back" }),
1023
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: isSubmitting || !validation.valid, type: "submit", children: isSubmitting ? "Submitting..." : "Submit" })
1039
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: isSubmitting || !validation.valid, type: "submit", children: isSubmitting ? "Submitting..." : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1040
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Send, { "aria-hidden": "true", size: 14, style: { marginRight: "0.35rem", verticalAlign: "middle" } }),
1041
+ "Submit"
1042
+ ] }) })
1024
1043
  ] })
1025
1044
  ] })
1026
- ] })
1045
+ ] }) })
1027
1046
  ]
1028
1047
  }
1029
- ) }) }) : null
1048
+ ) }) : null
1030
1049
  ] });
1031
1050
  }
1032
1051
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -196,4 +196,4 @@ interface GitHubIssueProxyClientOptions {
196
196
  }
197
197
  declare function createGitHubIssueProxyClient(options: GitHubIssueProxyClientOptions): (payload: SubmitFeedbackRequest) => Promise<SubmitResult>;
198
198
 
199
- export { type DiagnosticsConfig, type DiagnosticsSnapshot, type FeedbackFormData, type FeedbackType, type SubmissionConfig, type SubmissionMode, type SubmitFeedbackRequest, type SubmitResult, SupportWidget, type SupportWidgetConfig, type SupportWidgetProps, buildExperienceDetailsPayload, buildFeedbackDescription, clearFeedbackDiagnostics, createCentralFeedbackClient, createEmptyFeedbackForm, createGitHubIssueProxyClient, feedbackFieldLabels, feedbackTypes, getFeedbackDiagnosticsSnapshot, getRequiredFeedbackFields, installFeedbackDiagnostics, recordFeedbackRouteVisit, validateFeedbackForm };
199
+ export { type DiagnosticsConfig, type DiagnosticsEntry, type DiagnosticsSnapshot, type FeedbackFormData, type FeedbackType, type SubmissionConfig, type SubmissionMode, type SubmitFeedbackRequest, type SubmitResult, SupportWidget, type SupportWidgetConfig, type SupportWidgetProps, buildExperienceDetailsPayload, buildFeedbackDescription, clearFeedbackDiagnostics, createCentralFeedbackClient, createEmptyFeedbackForm, createGitHubIssueProxyClient, feedbackFieldLabels, feedbackTypes, getFeedbackDiagnosticsSnapshot, getRequiredFeedbackFields, installFeedbackDiagnostics, recordFeedbackRouteVisit, validateFeedbackForm };
package/dist/index.d.ts CHANGED
@@ -196,4 +196,4 @@ interface GitHubIssueProxyClientOptions {
196
196
  }
197
197
  declare function createGitHubIssueProxyClient(options: GitHubIssueProxyClientOptions): (payload: SubmitFeedbackRequest) => Promise<SubmitResult>;
198
198
 
199
- export { type DiagnosticsConfig, type DiagnosticsSnapshot, type FeedbackFormData, type FeedbackType, type SubmissionConfig, type SubmissionMode, type SubmitFeedbackRequest, type SubmitResult, SupportWidget, type SupportWidgetConfig, type SupportWidgetProps, buildExperienceDetailsPayload, buildFeedbackDescription, clearFeedbackDiagnostics, createCentralFeedbackClient, createEmptyFeedbackForm, createGitHubIssueProxyClient, feedbackFieldLabels, feedbackTypes, getFeedbackDiagnosticsSnapshot, getRequiredFeedbackFields, installFeedbackDiagnostics, recordFeedbackRouteVisit, validateFeedbackForm };
199
+ export { type DiagnosticsConfig, type DiagnosticsEntry, type DiagnosticsSnapshot, type FeedbackFormData, type FeedbackType, type SubmissionConfig, type SubmissionMode, type SubmitFeedbackRequest, type SubmitResult, SupportWidget, type SupportWidgetConfig, type SupportWidgetProps, buildExperienceDetailsPayload, buildFeedbackDescription, clearFeedbackDiagnostics, createCentralFeedbackClient, createEmptyFeedbackForm, createGitHubIssueProxyClient, feedbackFieldLabels, feedbackTypes, getFeedbackDiagnosticsSnapshot, getRequiredFeedbackFields, installFeedbackDiagnostics, recordFeedbackRouteVisit, validateFeedbackForm };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // src/components/SupportWidget.tsx
2
2
  import { useCallback, useEffect as useEffect2, useMemo, useState } from "react";
3
+ import { Bug, CheckCircle, Lightbulb, MessageCircle, MessageSquarePlus, Send, Wrench } from "lucide-react";
3
4
 
4
5
  // src/adapters/centralApi.ts
5
6
  function createCentralFeedbackClient(options) {
@@ -685,7 +686,7 @@ function buildFeedbackDescription(formData, diagnostics) {
685
686
  }
686
687
 
687
688
  // src/components/SupportWidget.tsx
688
- import "./widget-TTYCIVNC.css";
689
+ import "./widget-IHSQAQI2.css";
689
690
 
690
691
  // src/utils/classNames.ts
691
692
  function classNames(...items) {
@@ -694,6 +695,12 @@ function classNames(...items) {
694
695
 
695
696
  // src/components/SupportWidget.tsx
696
697
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
698
+ var typeIconMap = {
699
+ bug: { icon: Bug, color: "#ef4444" },
700
+ feature: { icon: Lightbulb, color: "#f59e0b" },
701
+ feedback: { icon: MessageCircle, color: "#3b82f6" },
702
+ improvement: { icon: Wrench, color: "#8b5cf6" }
703
+ };
697
704
  function labelForType(type) {
698
705
  return feedbackTypes.find((item) => item.value === type)?.label || type;
699
706
  }
@@ -842,7 +849,7 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
842
849
  ]
843
850
  }
844
851
  ),
845
- isOpen ? /* @__PURE__ */ jsx("div", { className: "sw-overlay", onClick: handleClose, children: /* @__PURE__ */ jsx("div", { className: "sw-modal-wrapper", children: /* @__PURE__ */ jsxs(
852
+ isOpen ? /* @__PURE__ */ jsx("div", { className: "sw-overlay", onClick: handleClose, children: /* @__PURE__ */ jsxs(
846
853
  "div",
847
854
  {
848
855
  "aria-describedby": "support-widget-description",
@@ -853,7 +860,8 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
853
860
  children: [
854
861
  /* @__PURE__ */ jsx("button", { "aria-label": "Close", className: "sw-close", onClick: handleClose, type: "button", children: "x" }),
855
862
  /* @__PURE__ */ jsx("p", { className: "sw-sr-only", id: "support-widget-description", children: "Support ticket dialog" }),
856
- isSubmitted ? /* @__PURE__ */ jsxs("div", { className: "sw-success", "data-testid": "feedback-success-screen", children: [
863
+ /* @__PURE__ */ jsx("div", { className: "sw-modal-body", children: isSubmitted ? /* @__PURE__ */ jsxs("div", { className: "sw-success", "data-testid": "feedback-success-screen", children: [
864
+ /* @__PURE__ */ jsx(CheckCircle, { "aria-hidden": "true", className: "sw-success-icon", color: "#0f766e", size: 48 }),
857
865
  /* @__PURE__ */ jsx("h2", { children: "Thank You!" }),
858
866
  /* @__PURE__ */ jsx("p", { children: "Your feedback helps us improve the product." }),
859
867
  submitResult?.issue_number || submitResult?.issue_url ? /* @__PURE__ */ jsxs("p", { "data-testid": "feedback-success-issue-link", children: [
@@ -865,23 +873,31 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
865
873
  ] }) : null
866
874
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
867
875
  /* @__PURE__ */ jsxs("header", { className: "sw-header", children: [
868
- /* @__PURE__ */ jsx("h2", { children: step === 1 ? "Send Feedback" : selectedTypeConfig?.label || "Support Ticket" }),
869
- /* @__PURE__ */ jsx("p", { children: step === 1 ? "What kind of support ticket would you like to submit?" : selectedTypeConfig?.description })
876
+ /* @__PURE__ */ jsx("h2", { children: step === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
877
+ /* @__PURE__ */ jsx(MessageSquarePlus, { "aria-hidden": "true", className: "sw-header-icon", size: 22 }),
878
+ " Send Feedback"
879
+ ] }) : selectedTypeConfig?.label || "Support Ticket" }),
880
+ /* @__PURE__ */ jsx("p", { children: step === 1 ? "Help us improve Cohiva by sharing your experience" : selectedTypeConfig?.description })
870
881
  ] }),
871
- step === 1 ? /* @__PURE__ */ jsx("div", { className: "sw-type-grid", children: feedbackTypes.map((typeConfig) => /* @__PURE__ */ jsxs(
872
- "button",
873
- {
874
- className: "sw-type-card",
875
- "data-testid": `feedback-type-${typeConfig.value}`,
876
- onClick: () => handleTypeSelect(typeConfig.value),
877
- type: "button",
878
- children: [
879
- /* @__PURE__ */ jsx("strong", { children: typeConfig.label }),
880
- /* @__PURE__ */ jsx("span", { children: typeConfig.description })
881
- ]
882
- },
883
- typeConfig.value
884
- )) }) : /* @__PURE__ */ jsxs("form", { className: "sw-form", onSubmit: handleSubmit, children: [
882
+ step === 1 ? /* @__PURE__ */ jsx("div", { className: "sw-type-grid", children: feedbackTypes.map((typeConfig) => {
883
+ const entry = typeIconMap[typeConfig.value];
884
+ const Icon = entry?.icon;
885
+ return /* @__PURE__ */ jsxs(
886
+ "button",
887
+ {
888
+ className: "sw-type-card",
889
+ "data-testid": `feedback-type-${typeConfig.value}`,
890
+ onClick: () => handleTypeSelect(typeConfig.value),
891
+ type: "button",
892
+ children: [
893
+ Icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "sw-type-card-icon", children: /* @__PURE__ */ jsx(Icon, { color: entry.color, size: 36, strokeWidth: 1.5 }) }) : null,
894
+ /* @__PURE__ */ jsx("strong", { children: typeConfig.label }),
895
+ /* @__PURE__ */ jsx("span", { children: typeConfig.description })
896
+ ]
897
+ },
898
+ typeConfig.value
899
+ );
900
+ }) }) : /* @__PURE__ */ jsxs("form", { className: "sw-form", onSubmit: handleSubmit, children: [
885
901
  /* @__PURE__ */ jsx("label", { htmlFor: "support-title", children: "Title *" }),
886
902
  /* @__PURE__ */ jsx(
887
903
  "input",
@@ -981,13 +997,16 @@ function SupportWidget({ config, isVisible = true, onSuccess, onError, onSubmit
981
997
  !validation.valid ? /* @__PURE__ */ jsx("p", { className: "sw-error", children: validation.description }) : null,
982
998
  /* @__PURE__ */ jsxs("div", { className: "sw-actions", children: [
983
999
  /* @__PURE__ */ jsx("button", { onClick: () => setStep(1), type: "button", children: "Back" }),
984
- /* @__PURE__ */ jsx("button", { disabled: isSubmitting || !validation.valid, type: "submit", children: isSubmitting ? "Submitting..." : "Submit" })
1000
+ /* @__PURE__ */ jsx("button", { disabled: isSubmitting || !validation.valid, type: "submit", children: isSubmitting ? "Submitting..." : /* @__PURE__ */ jsxs(Fragment, { children: [
1001
+ /* @__PURE__ */ jsx(Send, { "aria-hidden": "true", size: 14, style: { marginRight: "0.35rem", verticalAlign: "middle" } }),
1002
+ "Submit"
1003
+ ] }) })
985
1004
  ] })
986
1005
  ] })
987
- ] })
1006
+ ] }) })
988
1007
  ]
989
1008
  }
990
- ) }) }) : null
1009
+ ) }) : null
991
1010
  ] });
992
1011
  }
993
1012
  export {
package/dist/styles.css CHANGED
@@ -7,8 +7,8 @@
7
7
  --sw-color-text: #0f172a;
8
8
  --sw-color-text-muted: #475569;
9
9
  --sw-color-border: #cbd5e1;
10
- --sw-color-primary: #0f766e;
11
- --sw-color-primary-hover: #115e59;
10
+ --sw-color-primary: #8b5cf6;
11
+ --sw-color-primary-hover: #7c3aed;
12
12
  --sw-color-danger: #b91c1c;
13
13
  --sw-shadow-elevated: 0 20px 35px rgba(15, 23, 42, 0.25);
14
14
  }
@@ -61,12 +61,7 @@
61
61
  inset: 0;
62
62
  z-index: 1100;
63
63
  background: rgba(2, 6, 23, 0.7);
64
- overflow-y: auto;
65
- }
66
-
67
- .sw-modal-wrapper {
68
64
  display: flex;
69
- min-height: 100%;
70
65
  align-items: center;
71
66
  justify-content: center;
72
67
  padding: 1rem;
@@ -74,15 +69,25 @@
74
69
 
75
70
  .sw-modal {
76
71
  width: min(100%, 56rem);
72
+ max-height: calc(100dvh - 2rem);
73
+ display: flex;
74
+ flex-direction: column;
75
+ overflow: hidden;
77
76
  position: relative;
78
77
  border-radius: 1rem;
79
78
  border: 1px solid var(--sw-color-border);
80
79
  background: var(--sw-color-surface);
81
80
  color: var(--sw-color-text);
82
- padding: 1.25rem;
83
81
  box-shadow: var(--sw-shadow-elevated);
84
82
  }
85
83
 
84
+ .sw-modal-body {
85
+ flex: 1;
86
+ overflow-y: auto;
87
+ overscroll-behavior: contain;
88
+ padding: 1.25rem;
89
+ }
90
+
86
91
  .sw-close {
87
92
  position: absolute;
88
93
  right: 0.75rem;
@@ -97,6 +102,13 @@
97
102
  .sw-header h2 {
98
103
  margin: 0;
99
104
  font-size: 1.25rem;
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 0.4rem;
108
+ }
109
+
110
+ .sw-header-icon {
111
+ flex-shrink: 0;
100
112
  }
101
113
 
102
114
  .sw-header p {
@@ -115,12 +127,22 @@
115
127
  border: 2px solid var(--sw-color-border);
116
128
  border-radius: 0.75rem;
117
129
  background: #ffffff;
118
- padding: 0.85rem;
119
- display: grid;
120
- gap: 0.4rem;
130
+ padding: 1.25rem 1rem;
131
+ display: flex;
132
+ flex-direction: column;
133
+ align-items: center;
134
+ text-align: center;
135
+ gap: 0.5rem;
121
136
  transition: border-color 150ms ease, background 150ms ease;
122
137
  }
123
138
 
139
+ .sw-type-card-icon {
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ margin-bottom: 0.25rem;
144
+ }
145
+
124
146
  .sw-type-card:hover {
125
147
  border-color: var(--sw-color-primary);
126
148
  background: var(--sw-color-surface-muted);
@@ -218,10 +240,19 @@
218
240
  color: #ffffff;
219
241
  background: var(--sw-color-primary);
220
242
  border-color: var(--sw-color-primary);
243
+ border-radius: 999px;
244
+ font-weight: 600;
245
+ font-size: 1rem;
246
+ padding: 0.75rem;
247
+ display: inline-flex;
248
+ align-items: center;
249
+ justify-content: center;
250
+ gap: 0.4rem;
221
251
  }
222
252
 
223
- .sw-actions button[type='submit']:hover {
253
+ .sw-actions button[type='submit']:hover:not(:disabled) {
224
254
  background: var(--sw-color-primary-hover);
255
+ border-color: var(--sw-color-primary-hover);
225
256
  }
226
257
 
227
258
  .sw-actions button:disabled {
@@ -232,6 +263,14 @@
232
263
  .sw-success {
233
264
  text-align: center;
234
265
  padding: 3rem 1rem;
266
+ display: flex;
267
+ flex-direction: column;
268
+ align-items: center;
269
+ gap: 0.5rem;
270
+ }
271
+
272
+ .sw-success-icon {
273
+ margin-bottom: 0.5rem;
235
274
  }
236
275
 
237
276
  @media (max-width: 640px) {
@@ -7,8 +7,8 @@
7
7
  --sw-color-text: #0f172a;
8
8
  --sw-color-text-muted: #475569;
9
9
  --sw-color-border: #cbd5e1;
10
- --sw-color-primary: #0f766e;
11
- --sw-color-primary-hover: #115e59;
10
+ --sw-color-primary: #8b5cf6;
11
+ --sw-color-primary-hover: #7c3aed;
12
12
  --sw-color-danger: #b91c1c;
13
13
  --sw-shadow-elevated: 0 20px 35px rgba(15, 23, 42, 0.25);
14
14
  }
@@ -61,12 +61,7 @@
61
61
  inset: 0;
62
62
  z-index: 1100;
63
63
  background: rgba(2, 6, 23, 0.7);
64
- overflow-y: auto;
65
- }
66
-
67
- .sw-modal-wrapper {
68
64
  display: flex;
69
- min-height: 100%;
70
65
  align-items: center;
71
66
  justify-content: center;
72
67
  padding: 1rem;
@@ -74,15 +69,25 @@
74
69
 
75
70
  .sw-modal {
76
71
  width: min(100%, 56rem);
72
+ max-height: calc(100dvh - 2rem);
73
+ display: flex;
74
+ flex-direction: column;
75
+ overflow: hidden;
77
76
  position: relative;
78
77
  border-radius: 1rem;
79
78
  border: 1px solid var(--sw-color-border);
80
79
  background: var(--sw-color-surface);
81
80
  color: var(--sw-color-text);
82
- padding: 1.25rem;
83
81
  box-shadow: var(--sw-shadow-elevated);
84
82
  }
85
83
 
84
+ .sw-modal-body {
85
+ flex: 1;
86
+ overflow-y: auto;
87
+ overscroll-behavior: contain;
88
+ padding: 1.25rem;
89
+ }
90
+
86
91
  .sw-close {
87
92
  position: absolute;
88
93
  right: 0.75rem;
@@ -97,6 +102,13 @@
97
102
  .sw-header h2 {
98
103
  margin: 0;
99
104
  font-size: 1.25rem;
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 0.4rem;
108
+ }
109
+
110
+ .sw-header-icon {
111
+ flex-shrink: 0;
100
112
  }
101
113
 
102
114
  .sw-header p {
@@ -115,12 +127,22 @@
115
127
  border: 2px solid var(--sw-color-border);
116
128
  border-radius: 0.75rem;
117
129
  background: #ffffff;
118
- padding: 0.85rem;
119
- display: grid;
120
- gap: 0.4rem;
130
+ padding: 1.25rem 1rem;
131
+ display: flex;
132
+ flex-direction: column;
133
+ align-items: center;
134
+ text-align: center;
135
+ gap: 0.5rem;
121
136
  transition: border-color 150ms ease, background 150ms ease;
122
137
  }
123
138
 
139
+ .sw-type-card-icon {
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ margin-bottom: 0.25rem;
144
+ }
145
+
124
146
  .sw-type-card:hover {
125
147
  border-color: var(--sw-color-primary);
126
148
  background: var(--sw-color-surface-muted);
@@ -218,10 +240,19 @@
218
240
  color: #ffffff;
219
241
  background: var(--sw-color-primary);
220
242
  border-color: var(--sw-color-primary);
243
+ border-radius: 999px;
244
+ font-weight: 600;
245
+ font-size: 1rem;
246
+ padding: 0.75rem;
247
+ display: inline-flex;
248
+ align-items: center;
249
+ justify-content: center;
250
+ gap: 0.4rem;
221
251
  }
222
252
 
223
- .sw-actions button[type='submit']:hover {
253
+ .sw-actions button[type='submit']:hover:not(:disabled) {
224
254
  background: var(--sw-color-primary-hover);
255
+ border-color: var(--sw-color-primary-hover);
225
256
  }
226
257
 
227
258
  .sw-actions button:disabled {
@@ -232,6 +263,14 @@
232
263
  .sw-success {
233
264
  text-align: center;
234
265
  padding: 3rem 1rem;
266
+ display: flex;
267
+ flex-direction: column;
268
+ align-items: center;
269
+ gap: 0.5rem;
270
+ }
271
+
272
+ .sw-success-icon {
273
+ margin-bottom: 0.5rem;
235
274
  }
236
275
 
237
276
  @media (max-width: 640px) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cohiva/support-widget",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Reusable Support Ticket widget with diagnostics capture and typed payload generation",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -63,6 +63,7 @@
63
63
  "react-dom": ">=18"
64
64
  },
65
65
  "dependencies": {
66
+ "lucide-react": "^1.7.0",
66
67
  "zod": "^3.24.1"
67
68
  },
68
69
  "devDependencies": {
@@ -1,243 +0,0 @@
1
- :root {
2
- --sw-color-launcher-bg: #6d28d9;
3
- --sw-color-launcher-bg-hover: #5b21b6;
4
- --sw-color-launcher-border: #8b5cf6;
5
- --sw-color-surface: #ffffff;
6
- --sw-color-surface-muted: #f8fafc;
7
- --sw-color-text: #0f172a;
8
- --sw-color-text-muted: #475569;
9
- --sw-color-border: #cbd5e1;
10
- --sw-color-primary: #0f766e;
11
- --sw-color-primary-hover: #115e59;
12
- --sw-color-danger: #b91c1c;
13
- --sw-shadow-elevated: 0 20px 35px rgba(15, 23, 42, 0.25);
14
- }
15
-
16
- .sw-sr-only {
17
- border: 0;
18
- clip: rect(0, 0, 0, 0);
19
- height: 1px;
20
- margin: -1px;
21
- overflow: hidden;
22
- padding: 0;
23
- position: absolute;
24
- width: 1px;
25
- }
26
-
27
- .sw-launcher {
28
- position: fixed;
29
- right: 1.5rem;
30
- bottom: 1.5rem;
31
- z-index: 1000;
32
- display: inline-flex;
33
- align-items: center;
34
- gap: 0.5rem;
35
- border-radius: 999px;
36
- border: 2px solid var(--sw-color-launcher-border);
37
- background: var(--sw-color-launcher-bg);
38
- color: #ffffff;
39
- font-size: 0.875rem;
40
- font-weight: 700;
41
- padding: 0.625rem 1rem;
42
- box-shadow: 0 10px 24px rgba(76, 29, 149, 0.38);
43
- transition: transform 150ms ease, background 150ms ease;
44
- }
45
-
46
- .sw-launcher:hover {
47
- transform: scale(1.05);
48
- background: var(--sw-color-launcher-bg-hover);
49
- }
50
-
51
- .sw-launcher-icon {
52
- width: 1.25rem;
53
- height: 1.25rem;
54
- display: inline-flex;
55
- align-items: center;
56
- justify-content: center;
57
- }
58
-
59
- .sw-overlay {
60
- position: fixed;
61
- inset: 0;
62
- z-index: 1100;
63
- background: rgba(2, 6, 23, 0.7);
64
- display: grid;
65
- place-items: center;
66
- padding: 1rem;
67
- }
68
-
69
- .sw-modal {
70
- width: min(100%, 56rem);
71
- max-height: 92vh;
72
- overflow: auto;
73
- position: relative;
74
- border-radius: 1rem;
75
- border: 1px solid var(--sw-color-border);
76
- background: var(--sw-color-surface);
77
- color: var(--sw-color-text);
78
- padding: 1.25rem;
79
- box-shadow: var(--sw-shadow-elevated);
80
- }
81
-
82
- .sw-close {
83
- position: absolute;
84
- right: 0.75rem;
85
- top: 0.75rem;
86
- width: 2rem;
87
- height: 2rem;
88
- border-radius: 0.5rem;
89
- border: 1px solid var(--sw-color-border);
90
- background: transparent;
91
- }
92
-
93
- .sw-header h2 {
94
- margin: 0;
95
- font-size: 1.25rem;
96
- }
97
-
98
- .sw-header p {
99
- margin: 0.3rem 0 1rem;
100
- color: var(--sw-color-text-muted);
101
- }
102
-
103
- .sw-type-grid {
104
- display: grid;
105
- grid-template-columns: repeat(2, minmax(0, 1fr));
106
- gap: 0.75rem;
107
- }
108
-
109
- .sw-type-card {
110
- text-align: left;
111
- border: 2px solid var(--sw-color-border);
112
- border-radius: 0.75rem;
113
- background: #ffffff;
114
- padding: 0.85rem;
115
- display: grid;
116
- gap: 0.4rem;
117
- transition: border-color 150ms ease, background 150ms ease;
118
- }
119
-
120
- .sw-type-card:hover {
121
- border-color: var(--sw-color-primary);
122
- background: var(--sw-color-surface-muted);
123
- }
124
-
125
- .sw-type-card span {
126
- color: var(--sw-color-text-muted);
127
- font-size: 0.85rem;
128
- }
129
-
130
- .sw-form {
131
- display: grid;
132
- gap: 0.8rem;
133
- }
134
-
135
- .sw-field {
136
- display: grid;
137
- gap: 0.35rem;
138
- }
139
-
140
- .sw-field textarea,
141
- .sw-form input,
142
- .sw-form select {
143
- border: 1px solid var(--sw-color-border);
144
- border-radius: 0.5rem;
145
- padding: 0.6rem;
146
- font: inherit;
147
- }
148
-
149
- .sw-row {
150
- display: grid;
151
- grid-template-columns: repeat(2, minmax(0, 1fr));
152
- gap: 0.75rem;
153
- }
154
-
155
- .sw-section {
156
- border: 1px solid var(--sw-color-border);
157
- border-radius: 0.75rem;
158
- background: var(--sw-color-surface-muted);
159
- padding: 0.8rem;
160
- }
161
-
162
- .sw-section h3 {
163
- margin-top: 0;
164
- margin-bottom: 0.6rem;
165
- font-size: 1rem;
166
- }
167
-
168
- .sw-rating {
169
- display: grid;
170
- gap: 0.45rem;
171
- }
172
-
173
- .sw-rating-button {
174
- border: 1px solid var(--sw-color-border);
175
- border-radius: 0.3rem;
176
- background: transparent;
177
- color: #94a3b8;
178
- margin-right: 0.35rem;
179
- }
180
-
181
- .sw-rating-button.is-active {
182
- color: #f59e0b;
183
- border-color: #f59e0b;
184
- }
185
-
186
- .sw-diagnostics-note {
187
- border: 1px dashed var(--sw-color-border);
188
- border-radius: 0.55rem;
189
- font-size: 0.8rem;
190
- color: var(--sw-color-text-muted);
191
- padding: 0.65rem;
192
- }
193
-
194
- .sw-error {
195
- color: var(--sw-color-danger);
196
- margin: 0;
197
- }
198
-
199
- .sw-actions {
200
- display: flex;
201
- gap: 0.75rem;
202
- }
203
-
204
- .sw-actions button {
205
- flex: 1;
206
- border: 1px solid var(--sw-color-border);
207
- border-radius: 0.5rem;
208
- padding: 0.6rem;
209
- font: inherit;
210
- background: #ffffff;
211
- }
212
-
213
- .sw-actions button[type='submit'] {
214
- color: #ffffff;
215
- background: var(--sw-color-primary);
216
- border-color: var(--sw-color-primary);
217
- }
218
-
219
- .sw-actions button[type='submit']:hover {
220
- background: var(--sw-color-primary-hover);
221
- }
222
-
223
- .sw-actions button:disabled {
224
- opacity: 0.5;
225
- cursor: not-allowed;
226
- }
227
-
228
- .sw-success {
229
- text-align: center;
230
- padding: 3rem 1rem;
231
- }
232
-
233
- @media (max-width: 640px) {
234
- .sw-type-grid,
235
- .sw-row {
236
- grid-template-columns: 1fr;
237
- }
238
-
239
- .sw-launcher {
240
- right: 1rem;
241
- bottom: 1rem;
242
- }
243
- }