feedback-vos 1.0.35 → 1.0.37

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/README.md CHANGED
@@ -131,7 +131,7 @@ When feedback is submitted:
131
131
 
132
132
  ### Widget Not Visible
133
133
 
134
- If the widget is not showing up, check the following:
134
+ The widget uses inline styles to ensure it's always visible, even with CSS conflicts. If the widget is still not showing up, check the following:
135
135
 
136
136
  1. **Verify the client component wrapper is created correctly:**
137
137
  - Ensure `'use client'` directive is at the top of your `FeedbackWidget.tsx`
@@ -150,7 +150,16 @@ If the widget is not showing up, check the following:
150
150
  - The widget uses `z-50` for positioning - ensure no other styles override this
151
151
  - Verify Tailwind CSS is properly configured in your project
152
152
  - **CRITICAL:** The widget requires `brand` colors in your Tailwind config (see Requirements section below)
153
- - **Widget outside viewport:** If the widget appears outside the screen, check for parent containers with `transform`, `perspective`, `filter`, or `overflow: hidden` that can break `fixed` positioning. Ensure the widget is placed directly in `<body>` in your layout.
153
+ - **Widget outside viewport or not visible:** If the widget appears outside the screen or is not visible, add this CSS to your global stylesheet (e.g., `globals.css`):
154
+ ```css
155
+ [data-feedback-widget="true"] {
156
+ position: fixed !important;
157
+ bottom: 1rem !important;
158
+ right: 1rem !important;
159
+ z-index: 9999 !important;
160
+ }
161
+ ```
162
+ This ensures the widget is always visible regardless of CSS conflicts or parent container transforms.
154
163
 
155
164
  5. **Debug in browser console:**
156
165
  ```javascript
package/dist/index.js CHANGED
@@ -18,30 +18,30 @@ var thoughtImageUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzYiIGhlaWdodD0
18
18
  // src/lib/theme.ts
19
19
  function getThemeClasses(theme) {
20
20
  return {
21
- // Background colors - light mode is now softer (gray-50 instead of white)
22
- bgPrimary: theme === "dark" ? "bg-zinc-900" : "bg-gray-50",
23
- bgSecondary: theme === "dark" ? "bg-zinc-800" : "bg-gray-100",
24
- bgTertiary: theme === "dark" ? "bg-zinc-700" : "bg-gray-200",
25
- bgHover: theme === "dark" ? "hover:bg-zinc-600" : "hover:bg-gray-200",
26
- bgHoverSecondary: theme === "dark" ? "hover:bg-zinc-700" : "hover:bg-gray-200",
21
+ // Background colors - light mode uses white for better clarity
22
+ bgPrimary: theme === "dark" ? "bg-zinc-900" : "bg-white",
23
+ bgSecondary: theme === "dark" ? "bg-zinc-800" : "bg-gray-50",
24
+ bgTertiary: theme === "dark" ? "bg-zinc-700" : "bg-gray-100",
25
+ bgHover: theme === "dark" ? "hover:bg-zinc-600" : "hover:bg-gray-100",
26
+ bgHoverSecondary: theme === "dark" ? "hover:bg-zinc-700" : "hover:bg-gray-50",
27
27
  // Text colors
28
28
  textPrimary: theme === "dark" ? "text-zinc-100" : "text-gray-900",
29
29
  textSecondary: theme === "dark" ? "text-zinc-300" : "text-gray-700",
30
30
  textTertiary: theme === "dark" ? "text-zinc-400" : "text-gray-600",
31
31
  textMuted: theme === "dark" ? "text-neutral-400" : "text-gray-500",
32
- // Border colors
33
- borderPrimary: theme === "dark" ? "border-zinc-700" : "border-gray-300",
32
+ // Border colors - stronger borders in light mode for better definition
33
+ borderPrimary: theme === "dark" ? "border-zinc-700" : "border-gray-200",
34
34
  borderSecondary: theme === "dark" ? "border-zinc-600" : "border-gray-300",
35
35
  borderHover: theme === "dark" ? "hover:border-zinc-500" : "hover:border-gray-400",
36
36
  // Canvas/Editor background
37
- canvasBg: theme === "dark" ? "bg-zinc-900" : "bg-gray-200",
37
+ canvasBg: theme === "dark" ? "bg-zinc-900" : "bg-gray-100",
38
38
  // Overlay
39
39
  overlay: theme === "dark" ? "bg-black/80" : "bg-black/60",
40
40
  // Focus ring offset
41
- focusRingOffset: theme === "dark" ? "focus:ring-offset-zinc-900" : "focus:ring-offset-gray-50",
42
- // Button variants
43
- buttonSecondary: theme === "dark" ? "bg-zinc-800 hover:bg-zinc-700 text-zinc-100" : "bg-gray-200 hover:bg-gray-300 text-gray-900",
44
- buttonTertiary: theme === "dark" ? "bg-zinc-700 hover:bg-zinc-600 text-zinc-100" : "bg-gray-300 hover:bg-gray-400 text-gray-900",
41
+ focusRingOffset: theme === "dark" ? "focus:ring-offset-zinc-900" : "focus:ring-offset-white",
42
+ // Button variants - clearer distinction in light mode
43
+ buttonSecondary: theme === "dark" ? "bg-zinc-800 hover:bg-zinc-700 text-zinc-100" : "bg-white hover:bg-gray-50 text-gray-900 border border-gray-200",
44
+ buttonTertiary: theme === "dark" ? "bg-zinc-700 hover:bg-zinc-600 text-zinc-100" : "bg-gray-50 hover:bg-gray-100 text-gray-900 border border-gray-200",
45
45
  // Icon colors - make icons more visible (darker for better contrast)
46
46
  iconColor: theme === "dark" ? "text-zinc-100" : "text-gray-900"
47
47
  };
@@ -114,20 +114,20 @@ function FeedbackTypeStep({ onFeedbackTypeChanged, language, theme }) {
114
114
  const feedbackTypes = getFeedbackTypes(language);
115
115
  const themeClasses = getThemeClasses(theme);
116
116
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
117
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center justify-between w-full gap-2", children: [
118
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-lg md:text-xl leading-6 ${themeClasses.textPrimary}`, children: t.form.header }),
117
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: `flex items-center justify-between w-full gap-2 ${theme === "light" ? "pb-3 mb-2 border-b border-gray-200" : "pb-2"}`, children: [
118
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-lg md:text-xl leading-6 font-semibold ${themeClasses.textPrimary}`, children: t.form.header }),
119
119
  /* @__PURE__ */ jsxRuntime.jsx(CloseButton, { title: t.form.closeButton, theme })
120
120
  ] }),
121
121
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex py-6 md:py-8 gap-2 md:gap-2 w-full justify-center md:justify-start flex-wrap", children: Object.entries(feedbackTypes).map(([key, value]) => {
122
122
  return /* @__PURE__ */ jsxRuntime.jsxs(
123
123
  "button",
124
124
  {
125
- className: `${themeClasses.bgSecondary} rounded py-4 md:py-5 flex-1 min-w-[80px] md:w-24 flex flex-col items-center gap-2 border-2 border-transparent hover:border-brand-500 focus:border-brand-500 focus:outline-none transition-colors`,
125
+ className: `${themeClasses.bgSecondary} rounded-lg py-4 md:py-5 flex-1 min-w-[80px] md:w-24 flex flex-col items-center gap-2 border-2 ${theme === "light" ? "border-gray-200" : "border-transparent"} hover:border-brand-500 focus:border-brand-500 focus:outline-none transition-all shadow-sm hover:shadow-md ${theme === "light" ? "hover:bg-white" : ""}`,
126
126
  type: "button",
127
127
  onClick: () => onFeedbackTypeChanged(key),
128
128
  children: [
129
129
  /* @__PURE__ */ jsxRuntime.jsx("img", { src: value.image.source, alt: value.image.alt, className: "w-5 h-5 md:w-6 md:h-6" }),
130
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs md:text-sm text-center ${themeClasses.textPrimary}`, children: value.title })
130
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs md:text-sm text-center font-medium ${themeClasses.textPrimary}`, children: value.title })
131
131
  ]
132
132
  },
133
133
  key
@@ -387,7 +387,13 @@ function ScreenshotButton({
387
387
  const themeClasses = getThemeClasses(theme);
388
388
  async function handleTakeScreenshot() {
389
389
  setIsTakenScreenShot(true);
390
- const canvas = await html2canvas__default.default(document.querySelector("html"), {
390
+ const canvas = await html2canvas__default.default(document.body, {
391
+ width: window.innerWidth,
392
+ height: window.innerHeight,
393
+ scrollX: -window.scrollX,
394
+ scrollY: -window.scrollY,
395
+ windowWidth: window.innerWidth,
396
+ windowHeight: window.innerHeight,
391
397
  ignoreElements: (element) => {
392
398
  return element.hasAttribute("data-feedback-widget") || element.closest("[data-feedback-widget]") !== null;
393
399
  }
@@ -1250,7 +1256,7 @@ function FeedbackContentStep({
1250
1256
  }
1251
1257
  }
1252
1258
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1253
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "relative w-full", children: [
1259
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: `relative w-full ${theme === "light" ? "pb-3 mb-3 border-b border-gray-200" : "pb-2 mb-2"}`, children: [
1254
1260
  /* @__PURE__ */ jsxRuntime.jsx(
1255
1261
  "button",
1256
1262
  {
@@ -1260,7 +1266,7 @@ function FeedbackContentStep({
1260
1266
  children: /* @__PURE__ */ jsxRuntime.jsx(phosphorReact.ArrowLeft, { weight: "bold", className: "w-5 h-5 md:w-5 md:h-5" })
1261
1267
  }
1262
1268
  ),
1263
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `text-lg md:text-xl leading-6 flex items-center gap-2 pl-10 md:pl-12 pr-10 md:pr-12 ${themeClasses.textPrimary}`, children: [
1269
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `text-lg md:text-xl leading-6 flex items-center gap-2 pl-10 md:pl-12 pr-10 md:pr-12 font-semibold ${themeClasses.textPrimary}`, children: [
1264
1270
  /* @__PURE__ */ jsxRuntime.jsx(
1265
1271
  "img",
1266
1272
  {
@@ -1278,10 +1284,10 @@ function FeedbackContentStep({
1278
1284
  "textarea",
1279
1285
  {
1280
1286
  className: `w-full min-h-[100px] md:min-h-[112px] text-sm
1281
- ${themeClasses.textPrimary} border-2 border-brand-500 bg-transparent rounded-md p-2 md:p-3
1287
+ ${themeClasses.textPrimary} border-2 ${theme === "light" ? "border-gray-300" : "border-brand-500"} ${theme === "light" ? "bg-gray-50" : "bg-transparent"} rounded-md p-2 md:p-3
1282
1288
  ${theme === "dark" ? "placeholder:text-zinc-400" : "placeholder:text-gray-500"}
1283
1289
  focus:border-brand-500 focus:ring-brand-500 focus:ring-1 resize-none focus:outline-none
1284
- ${theme === "dark" ? "scrollbar-thumb-zinc-700" : "scrollbar-thumb-gray-400"} scrollbar-track-transparent scrollbar-thin`,
1290
+ ${theme === "dark" ? "scrollbar-thumb-zinc-700" : "scrollbar-thumb-gray-400"} scrollbar-track-transparent scrollbar-thin transition-colors`,
1285
1291
  placeholder: t.content.placeholder,
1286
1292
  onChange: (e) => setComment(e.target.value)
1287
1293
  }
@@ -1326,13 +1332,13 @@ function FeedbackSuccessStep({ onFeedbackRestartRequest, language, theme }) {
1326
1332
  const t = getTranslations(language);
1327
1333
  const themeClasses = getThemeClasses(theme);
1328
1334
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1329
- /* @__PURE__ */ jsxRuntime.jsx("header", { children: /* @__PURE__ */ jsxRuntime.jsx(CloseButton, { title: t.form.closeButton, theme }) }),
1335
+ /* @__PURE__ */ jsxRuntime.jsx("header", { className: `flex items-center justify-end w-full ${theme === "light" ? "pb-3 mb-2 border-b border-gray-200" : "pb-2"}`, children: /* @__PURE__ */ jsxRuntime.jsx(CloseButton, { title: t.form.closeButton, theme }) }),
1330
1336
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center py-8 md:py-10 w-full max-w-[304px] px-2", children: [
1331
1337
  /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "41", height: "40", viewBox: "0 0 41 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "w-10 h-10 md:w-[41px] md:h-[40px]", children: [
1332
1338
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M38.5 34C38.5 36.209 36.709 38 34.5 38H6.5C4.291 38 2.5 36.209 2.5 34V6C2.5 3.791 4.291 2 6.5 2H34.5C36.709 2 38.5 3.791 38.5 6V34Z", fill: "#77B255" }),
1333
1339
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M31.78 8.36202C30.624 7.61102 29.076 7.94002 28.322 9.09802L17.436 25.877L12.407 21.227C11.393 20.289 9.81103 20.352 8.87403 21.365C7.93703 22.379 7.99903 23.961 9.01303 24.898L16.222 31.564C16.702 32.009 17.312 32.229 17.918 32.229C18.591 32.229 19.452 31.947 20.017 31.09C20.349 30.584 32.517 11.82 32.517 11.82C33.268 10.661 32.938 9.11302 31.78 8.36202Z", fill: "white" })
1334
1340
  ] }),
1335
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-lg md:text-xl mt-2 text-center ${themeClasses.textPrimary}`, children: t.success.message }),
1341
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-lg md:text-xl mt-2 text-center font-medium ${themeClasses.textPrimary}`, children: t.success.message }),
1336
1342
  /* @__PURE__ */ jsxRuntime.jsx(
1337
1343
  "button",
1338
1344
  {
@@ -1379,7 +1385,7 @@ function WidgetForm({ integration, githubConfig, language, theme }) {
1379
1385
  setFeedbackSent(false);
1380
1386
  setFeedbackType(null);
1381
1387
  }
1382
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${themeClasses.bgPrimary} p-3 md:p-4 relative rounded-2xl mb-4 flex flex-col items-center shadow-lg w-[calc(100vw-2rem)] md:w-auto md:min-w-[384px] max-w-md`, children: [
1388
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${themeClasses.bgPrimary} p-3 md:p-4 relative rounded-2xl mb-4 flex flex-col items-center ${theme === "light" ? "shadow-xl border border-gray-200" : "shadow-lg"} w-[calc(100vw-2rem)] md:w-auto md:min-w-[384px] max-w-md`, children: [
1383
1389
  feedbackSent ? /* @__PURE__ */ jsxRuntime.jsx(FeedbackSuccessStep, { onFeedbackRestartRequest: handleRestartFeedback, language, theme }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: !feedbackType ? /* @__PURE__ */ jsxRuntime.jsx(FeedbackTypeStep, { onFeedbackTypeChanged: setFeedbackType, language, theme }) : /* @__PURE__ */ jsxRuntime.jsx(
1384
1390
  FeedbackContentStep,
1385
1391
  {
@@ -1440,15 +1446,32 @@ function Widget({
1440
1446
  const isLeft = position.includes("left");
1441
1447
  const panelPositionClass = isTop ? "absolute top-full mt-2" : "absolute bottom-full mb-2";
1442
1448
  const panelAlignmentClass = isLeft ? "left-0" : "right-0";
1449
+ const getPositionStyles = () => {
1450
+ const baseStyles = {
1451
+ position: "fixed",
1452
+ zIndex: 9999
1453
+ };
1454
+ if (position === "bottom-right") {
1455
+ baseStyles.bottom = "1rem";
1456
+ baseStyles.right = "1rem";
1457
+ } else if (position === "bottom-left") {
1458
+ baseStyles.bottom = "1rem";
1459
+ baseStyles.left = "1rem";
1460
+ } else if (position === "top-right") {
1461
+ baseStyles.top = "1rem";
1462
+ baseStyles.right = "1rem";
1463
+ } else if (position === "top-left") {
1464
+ baseStyles.top = "1rem";
1465
+ baseStyles.left = "1rem";
1466
+ }
1467
+ return baseStyles;
1468
+ };
1443
1469
  return /* @__PURE__ */ jsxRuntime.jsx(
1444
1470
  "div",
1445
1471
  {
1446
1472
  "data-feedback-widget": "true",
1447
1473
  className: `fixed ${positionClasses[position]} z-50`,
1448
- style: {
1449
- position: "fixed",
1450
- zIndex: 50
1451
- },
1474
+ style: getPositionStyles(),
1452
1475
  children: /* @__PURE__ */ jsxRuntime.jsxs(react.Popover, { className: "relative", children: [
1453
1476
  /* @__PURE__ */ jsxRuntime.jsx(react.Popover.Panel, { className: `${panelPositionClass} ${panelAlignmentClass}`, children: /* @__PURE__ */ jsxRuntime.jsx(
1454
1477
  WidgetForm,