react-visual-feedback 1.1.0 → 1.2.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.
- package/LICENSE +2 -2
- package/README.md +313 -171
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Murali
|
|
3
|
+
Copyright (c) 2025 Murali Vvrsn Gurajapu
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,36 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# React Visual Feedback
|
|
2
2
|
|
|
3
|
-
A powerful, visual feedback collection tool for React applications. Users can select any element on your page, and the widget automatically captures a screenshot and context information.
|
|
3
|
+
A powerful, visual feedback collection tool for React applications with an integrated dashboard for managing user feedback. Users can select any element on your page, and the widget automatically captures a screenshot and context information.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
+
### Feedback Collection
|
|
7
8
|
- 🎯 Visual element selection with hover highlighting
|
|
8
|
-
- 📸 Automatic screenshot capture of selected elements
|
|
9
|
+
- 📸 Automatic screenshot capture of selected elements with perfect CSS rendering
|
|
9
10
|
- 📝 Feedback form with rich context
|
|
10
11
|
- ⚡ Lightweight and performant
|
|
11
|
-
- 🎨
|
|
12
|
-
- ⌨️ Keyboard shortcuts (Ctrl+Q to activate, Esc to cancel)
|
|
12
|
+
- 🎨 Works with any CSS framework (Tailwind, Bootstrap, Material-UI, etc.)
|
|
13
|
+
- ⌨️ Keyboard shortcuts (Ctrl+Q to activate, Esc to cancel, Ctrl+Enter to submit)
|
|
14
|
+
- 🌓 Dark mode support
|
|
15
|
+
|
|
16
|
+
### Feedback Dashboard (New!)
|
|
17
|
+
- 📊 **Professional dashboard** with localStorage or custom data source
|
|
18
|
+
- 👨💻 **Developer mode** with full technical details
|
|
19
|
+
- 👤 **User mode** for simplified feedback view
|
|
20
|
+
- 🏷️ **Status management** with 7 professional status options
|
|
21
|
+
- ✅ **Custom dropdown** with smooth animations
|
|
22
|
+
- 🔒 **Permission system** - Users can only view, developers can manage
|
|
23
|
+
- 🔄 **Status change callbacks** for database synchronization
|
|
24
|
+
- ⌨️ Dashboard keyboard shortcut (Ctrl+Shift+Q)
|
|
13
25
|
|
|
14
26
|
## Installation
|
|
15
27
|
|
|
16
28
|
```bash
|
|
17
|
-
npm install
|
|
29
|
+
npm install react-visual-feedback
|
|
18
30
|
```
|
|
19
31
|
|
|
20
32
|
**Important:** Import the CSS file in your application:
|
|
21
33
|
|
|
22
34
|
```jsx
|
|
23
|
-
import '
|
|
35
|
+
import 'react-visual-feedback/dist/index.css';
|
|
24
36
|
```
|
|
25
37
|
|
|
26
38
|
## Quick Start
|
|
27
39
|
|
|
28
|
-
###
|
|
40
|
+
### Basic Usage (Feedback Only)
|
|
29
41
|
|
|
30
42
|
```jsx
|
|
31
43
|
import React from 'react';
|
|
32
|
-
import { FeedbackProvider } from '
|
|
33
|
-
import '
|
|
44
|
+
import { FeedbackProvider } from 'react-visual-feedback';
|
|
45
|
+
import 'react-visual-feedback/dist/index.css';
|
|
34
46
|
|
|
35
47
|
function App() {
|
|
36
48
|
const handleFeedbackSubmit = async (feedbackData) => {
|
|
@@ -53,269 +65,399 @@ function App() {
|
|
|
53
65
|
export default App;
|
|
54
66
|
```
|
|
55
67
|
|
|
56
|
-
###
|
|
68
|
+
### With Dashboard (Full Feature Set)
|
|
57
69
|
|
|
58
70
|
```jsx
|
|
59
|
-
import
|
|
71
|
+
import React from 'react';
|
|
72
|
+
import { FeedbackProvider, useFeedback } from 'react-visual-feedback';
|
|
73
|
+
import 'react-visual-feedback/dist/index.css';
|
|
60
74
|
|
|
61
|
-
function
|
|
62
|
-
const { setIsActive } = useFeedback();
|
|
75
|
+
function FeedbackButtons() {
|
|
76
|
+
const { isActive, setIsActive, setIsDashboardOpen } = useFeedback();
|
|
63
77
|
|
|
64
78
|
return (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
<div style={{ position: 'fixed', bottom: 20, right: 20, display: 'flex', gap: 10 }}>
|
|
80
|
+
<button onClick={() => setIsDashboardOpen(true)}>
|
|
81
|
+
📊 Dashboard
|
|
82
|
+
</button>
|
|
83
|
+
<button onClick={() => setIsActive(!isActive)}>
|
|
84
|
+
{isActive ? '✕ Cancel' : '💬 Report Issue'}
|
|
85
|
+
</button>
|
|
86
|
+
</div>
|
|
68
87
|
);
|
|
69
88
|
}
|
|
70
|
-
```
|
|
71
89
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
import { useFeedback } from 'murali-feedback-widget-react';
|
|
90
|
+
function App() {
|
|
91
|
+
const handleFeedbackSubmit = async (feedbackData) => {
|
|
92
|
+
console.log('Feedback received:', feedbackData);
|
|
93
|
+
await fetch('/api/feedback', {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: { 'Content-Type': 'application/json' },
|
|
96
|
+
body: JSON.stringify(feedbackData)
|
|
97
|
+
});
|
|
98
|
+
};
|
|
82
99
|
|
|
83
|
-
|
|
84
|
-
|
|
100
|
+
const handleStatusChange = async ({ id, status }) => {
|
|
101
|
+
console.log('Status changed:', { id, status });
|
|
102
|
+
// Update your database
|
|
103
|
+
await fetch(`/api/feedback/${id}/status`, {
|
|
104
|
+
method: 'PATCH',
|
|
105
|
+
headers: { 'Content-Type': 'application/json' },
|
|
106
|
+
body: JSON.stringify({ status })
|
|
107
|
+
});
|
|
108
|
+
};
|
|
85
109
|
|
|
86
110
|
return (
|
|
87
|
-
<
|
|
88
|
-
{
|
|
89
|
-
|
|
111
|
+
<FeedbackProvider
|
|
112
|
+
onSubmit={handleFeedbackSubmit}
|
|
113
|
+
onStatusChange={handleStatusChange}
|
|
114
|
+
dashboard={true}
|
|
115
|
+
isDeveloper={true} // Set to false for user mode
|
|
116
|
+
userName="John Doe"
|
|
117
|
+
userEmail="john@example.com"
|
|
118
|
+
>
|
|
119
|
+
<YourApp />
|
|
120
|
+
<FeedbackButtons />
|
|
121
|
+
</FeedbackProvider>
|
|
90
122
|
);
|
|
91
123
|
}
|
|
124
|
+
|
|
125
|
+
export default App;
|
|
92
126
|
```
|
|
93
127
|
|
|
94
|
-
|
|
95
|
-
You can control the widget's active state from the parent component:
|
|
128
|
+
## Dashboard Features
|
|
96
129
|
|
|
97
|
-
|
|
98
|
-
import React, { useState } from 'react';
|
|
99
|
-
import { FeedbackProvider } from 'murali-feedback-widget-react';
|
|
130
|
+
### Status Options
|
|
100
131
|
|
|
101
|
-
|
|
102
|
-
const [isFeedbackActive, setIsFeedbackActive] = useState(false);
|
|
132
|
+
The dashboard includes 7 professional status options:
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
134
|
+
| Status | Color | Description |
|
|
135
|
+
|--------|-------|-------------|
|
|
136
|
+
| **Reported** 🔴 | Red | Initial feedback submission |
|
|
137
|
+
| **Opened** 🟠 | Amber | Acknowledged and under review |
|
|
138
|
+
| **Doing it** 🔵 | Blue | Actively being worked on |
|
|
139
|
+
| **Resolved** 🟢 | Green | Fixed and ready |
|
|
140
|
+
| **Released** 🟣 | Purple | Deployed to production |
|
|
141
|
+
| **Blocked** 🔴 | Red | Waiting on dependencies |
|
|
142
|
+
| **Won't do** ⚪ | Gray | Not planned for implementation |
|
|
108
143
|
|
|
109
|
-
|
|
110
|
-
<div>
|
|
111
|
-
<button onClick={() => setIsFeedbackActive(!isFeedbackActive)}>
|
|
112
|
-
{isFeedbackActive ? 'Cancel' : 'Report Bug'}
|
|
113
|
-
</button>
|
|
144
|
+
### Developer vs User Mode
|
|
114
145
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
#### Developer Mode (`isDeveloper={true}`)
|
|
147
|
+
- ✅ View all technical details (element info, CSS, viewport, user agent)
|
|
148
|
+
- ✅ Change feedback status
|
|
149
|
+
- ✅ Delete feedback items
|
|
150
|
+
- ✅ Full control over feedback management
|
|
151
|
+
|
|
152
|
+
#### User Mode (`isDeveloper={false}`)
|
|
153
|
+
- ✅ View feedback submissions
|
|
154
|
+
- ✅ See current status (read-only)
|
|
155
|
+
- ❌ Cannot change status
|
|
156
|
+
- ❌ Cannot delete items
|
|
157
|
+
- Perfect for product managers and stakeholders
|
|
158
|
+
|
|
159
|
+
### Data Persistence
|
|
160
|
+
|
|
161
|
+
The dashboard supports two modes:
|
|
162
|
+
|
|
163
|
+
1. **localStorage** (default) - Automatic persistence in browser
|
|
164
|
+
2. **Custom data source** - Pass your own data via `dashboardData` prop
|
|
165
|
+
|
|
166
|
+
```jsx
|
|
167
|
+
// Using localStorage (automatic)
|
|
168
|
+
<FeedbackProvider dashboard={true}>
|
|
169
|
+
|
|
170
|
+
// Using custom data source
|
|
171
|
+
<FeedbackProvider
|
|
172
|
+
dashboard={true}
|
|
173
|
+
dashboardData={yourFeedbackArray}
|
|
174
|
+
>
|
|
125
175
|
```
|
|
126
176
|
|
|
127
177
|
## API Reference
|
|
128
178
|
|
|
129
|
-
### FeedbackProvider
|
|
179
|
+
### FeedbackProvider Props
|
|
180
|
+
|
|
181
|
+
| Prop | Type | Required | Default | Description |
|
|
182
|
+
|------|------|----------|---------|-------------|
|
|
183
|
+
| `onSubmit` | `(feedbackData) => Promise<void>` | Yes | - | Callback when feedback is submitted |
|
|
184
|
+
| `onStatusChange` | `({ id, status }) => void` | No | - | Callback when status changes |
|
|
185
|
+
| `children` | `ReactNode` | Yes | - | Your app components |
|
|
186
|
+
| `dashboard` | `boolean` | No | `false` | Enable dashboard feature |
|
|
187
|
+
| `dashboardData` | `Array` | No | `undefined` | Custom feedback data (uses localStorage if undefined) |
|
|
188
|
+
| `isDeveloper` | `boolean` | No | `false` | Enable developer mode with full permissions |
|
|
189
|
+
| `isUser` | `boolean` | No | `true` | Enable user mode (read-only) |
|
|
190
|
+
| `userName` | `string` | No | `'Anonymous'` | User name for feedback submissions |
|
|
191
|
+
| `userEmail` | `string` | No | `null` | User email for feedback submissions |
|
|
192
|
+
| `isActive` | `boolean` | No | `undefined` | Control widget active state (controlled mode) |
|
|
193
|
+
| `onActiveChange` | `(active: boolean) => void` | No | - | Callback when active state changes |
|
|
130
194
|
|
|
131
|
-
|
|
195
|
+
### useFeedback Hook
|
|
196
|
+
|
|
197
|
+
```jsx
|
|
198
|
+
const { isActive, setIsActive, setIsDashboardOpen } = useFeedback();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Returns:**
|
|
202
|
+
- `isActive`: `boolean` - Whether feedback mode is active
|
|
203
|
+
- `setIsActive`: `(active: boolean) => void` - Activate/deactivate feedback mode
|
|
204
|
+
- `setIsDashboardOpen`: `(open: boolean) => void` - Open/close dashboard
|
|
132
205
|
|
|
133
|
-
|
|
134
|
-
- `onSubmit` (required): `(feedbackData) => Promise<void>` - Callback function when feedback is submitted
|
|
135
|
-
- `children`: React nodes
|
|
136
|
-
- `isActive` (optional): `boolean` - Control the widget active state from parent (controlled mode)
|
|
137
|
-
- `onActiveChange` (optional): `(active: boolean) => void` - Callback when active state changes (used with controlled mode)
|
|
206
|
+
### Feedback Data Structure
|
|
138
207
|
|
|
139
|
-
|
|
140
|
-
```javascript
|
|
208
|
+
```typescript
|
|
141
209
|
{
|
|
142
|
-
|
|
210
|
+
id: string,
|
|
211
|
+
feedback: string,
|
|
212
|
+
userName: string,
|
|
213
|
+
userEmail: string | null,
|
|
214
|
+
status: 'reported' | 'opened' | 'doingIt' | 'resolved' | 'released' | 'blocked' | 'wontDo',
|
|
215
|
+
timestamp: string, // ISO 8601 format
|
|
216
|
+
url: string,
|
|
143
217
|
elementInfo: {
|
|
144
|
-
tagName:
|
|
145
|
-
id:
|
|
146
|
-
className:
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
218
|
+
tagName: string,
|
|
219
|
+
id: string,
|
|
220
|
+
className: string,
|
|
221
|
+
selector: string,
|
|
222
|
+
text: string,
|
|
223
|
+
position: {
|
|
224
|
+
x: number,
|
|
225
|
+
y: number,
|
|
226
|
+
width: number,
|
|
227
|
+
height: number
|
|
228
|
+
},
|
|
229
|
+
styles: {
|
|
230
|
+
backgroundColor: string,
|
|
231
|
+
color: string,
|
|
232
|
+
fontSize: string,
|
|
233
|
+
fontFamily: string
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
screenshot: string, // Base64 encoded PNG
|
|
237
|
+
viewport: {
|
|
238
|
+
width: number,
|
|
239
|
+
height: number
|
|
150
240
|
},
|
|
151
|
-
|
|
152
|
-
url: "https://yourapp.com/current-page",
|
|
153
|
-
userAgent: "Mozilla/5.0...",
|
|
154
|
-
timestamp: "2025-10-22T10:30:00.000Z"
|
|
241
|
+
userAgent: string
|
|
155
242
|
}
|
|
156
243
|
```
|
|
157
244
|
|
|
158
|
-
|
|
245
|
+
## Keyboard Shortcuts
|
|
159
246
|
|
|
160
|
-
|
|
247
|
+
| Shortcut | Action |
|
|
248
|
+
|----------|--------|
|
|
249
|
+
| `Ctrl+Q` | Activate feedback mode |
|
|
250
|
+
| `Ctrl+Shift+Q` | Open dashboard (when dashboard is enabled) |
|
|
251
|
+
| `Esc` | Cancel/close feedback mode or dashboard |
|
|
252
|
+
| `Ctrl+Enter` | Submit feedback (when form is open) |
|
|
161
253
|
|
|
162
|
-
|
|
163
|
-
- `isActive`: boolean - Whether the widget is currently active
|
|
164
|
-
- `setIsActive`: (active: boolean) => void - Function to activate/deactivate the widget
|
|
254
|
+
## Usage Examples
|
|
165
255
|
|
|
166
|
-
|
|
256
|
+
### Example 1: Basic Feedback Collection
|
|
167
257
|
|
|
168
|
-
|
|
258
|
+
```jsx
|
|
259
|
+
import { FeedbackProvider, useFeedback } from 'react-visual-feedback';
|
|
260
|
+
import 'react-visual-feedback/dist/index.css';
|
|
169
261
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
262
|
+
function FeedbackButton() {
|
|
263
|
+
const { setIsActive } = useFeedback();
|
|
264
|
+
return <button onClick={() => setIsActive(true)}>Report Issue</button>;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function App() {
|
|
268
|
+
return (
|
|
269
|
+
<FeedbackProvider onSubmit={async (data) => {
|
|
270
|
+
await fetch('/api/feedback', {
|
|
271
|
+
method: 'POST',
|
|
272
|
+
body: JSON.stringify(data)
|
|
273
|
+
});
|
|
274
|
+
}}>
|
|
275
|
+
<YourApp />
|
|
276
|
+
<FeedbackButton />
|
|
277
|
+
</FeedbackProvider>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
176
280
|
```
|
|
177
281
|
|
|
178
|
-
|
|
282
|
+
### Example 2: Full Dashboard with Status Management
|
|
179
283
|
|
|
180
284
|
```jsx
|
|
181
|
-
|
|
182
|
-
|
|
285
|
+
function App() {
|
|
286
|
+
const [isDeveloper, setIsDeveloper] = useState(true);
|
|
183
287
|
|
|
184
|
-
|
|
185
|
-
|
|
288
|
+
const handleStatusChange = async ({ id, status }) => {
|
|
289
|
+
// Update database
|
|
290
|
+
await fetch(`/api/feedback/${id}`, {
|
|
291
|
+
method: 'PATCH',
|
|
292
|
+
body: JSON.stringify({ status })
|
|
293
|
+
});
|
|
294
|
+
};
|
|
186
295
|
|
|
187
296
|
return (
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
background: '#007bff',
|
|
196
|
-
color: 'white',
|
|
197
|
-
border: 'none',
|
|
198
|
-
borderRadius: '5px',
|
|
199
|
-
cursor: 'pointer'
|
|
200
|
-
}}
|
|
297
|
+
<FeedbackProvider
|
|
298
|
+
dashboard={true}
|
|
299
|
+
isDeveloper={isDeveloper}
|
|
300
|
+
onSubmit={handleFeedbackSubmit}
|
|
301
|
+
onStatusChange={handleStatusChange}
|
|
302
|
+
userName="Jane Smith"
|
|
303
|
+
userEmail="jane@company.com"
|
|
201
304
|
>
|
|
202
|
-
|
|
203
|
-
</
|
|
305
|
+
<YourApp />
|
|
306
|
+
</FeedbackProvider>
|
|
204
307
|
);
|
|
205
308
|
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Example 3: Custom Data Source
|
|
206
312
|
|
|
313
|
+
```jsx
|
|
207
314
|
function App() {
|
|
208
|
-
const
|
|
209
|
-
try {
|
|
210
|
-
const response = await fetch('https://your-api.com/feedback', {
|
|
211
|
-
method: 'POST',
|
|
212
|
-
headers: { 'Content-Type': 'application/json' },
|
|
213
|
-
body: JSON.stringify(feedbackData)
|
|
214
|
-
});
|
|
315
|
+
const [feedbackData, setFeedbackData] = useState([]);
|
|
215
316
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
};
|
|
317
|
+
useEffect(() => {
|
|
318
|
+
// Load feedback from your API
|
|
319
|
+
fetch('/api/feedback')
|
|
320
|
+
.then(res => res.json())
|
|
321
|
+
.then(setFeedbackData);
|
|
322
|
+
}, []);
|
|
224
323
|
|
|
225
324
|
return (
|
|
226
|
-
<FeedbackProvider
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
325
|
+
<FeedbackProvider
|
|
326
|
+
dashboard={true}
|
|
327
|
+
dashboardData={feedbackData}
|
|
328
|
+
isDeveloper={true}
|
|
329
|
+
onStatusChange={async ({ id, status }) => {
|
|
330
|
+
// Update API
|
|
331
|
+
await fetch(`/api/feedback/${id}`, {
|
|
332
|
+
method: 'PATCH',
|
|
333
|
+
body: JSON.stringify({ status })
|
|
334
|
+
});
|
|
335
|
+
// Reload data
|
|
336
|
+
const updated = await fetch('/api/feedback').then(r => r.json());
|
|
337
|
+
setFeedbackData(updated);
|
|
338
|
+
}}
|
|
339
|
+
>
|
|
340
|
+
<YourApp />
|
|
232
341
|
</FeedbackProvider>
|
|
233
342
|
);
|
|
234
343
|
}
|
|
344
|
+
```
|
|
235
345
|
|
|
236
|
-
|
|
346
|
+
## Styling
|
|
347
|
+
|
|
348
|
+
The widget comes with default styles, but you can customize them:
|
|
349
|
+
|
|
350
|
+
```css
|
|
351
|
+
/* Feedback Collection */
|
|
352
|
+
.feedback-overlay { /* Background overlay */ }
|
|
353
|
+
.feedback-highlight { /* Element highlight */ }
|
|
354
|
+
.feedback-tooltip { /* Element info tooltip */ }
|
|
355
|
+
.feedback-modal { /* Feedback form modal */ }
|
|
356
|
+
.feedback-backdrop { /* Modal backdrop */ }
|
|
357
|
+
|
|
358
|
+
/* Dashboard */
|
|
359
|
+
.feedback-dashboard { /* Dashboard container */ }
|
|
360
|
+
.feedback-dashboard-backdrop { /* Dashboard backdrop */ }
|
|
237
361
|
```
|
|
238
362
|
|
|
239
363
|
## How It Works
|
|
240
364
|
|
|
365
|
+
### Feedback Collection Flow
|
|
366
|
+
|
|
241
367
|
1. User activates the widget (Ctrl+Q or button click)
|
|
242
368
|
2. User hovers over elements to see them highlighted
|
|
243
369
|
3. User clicks on the problematic element
|
|
244
|
-
4. Widget captures a screenshot
|
|
245
|
-
5. Feedback form appears with
|
|
246
|
-
6. User enters
|
|
247
|
-
7. Your `onSubmit` handler receives all
|
|
370
|
+
4. Widget captures a pixel-perfect screenshot
|
|
371
|
+
5. Feedback form appears with context pre-filled
|
|
372
|
+
6. User enters feedback and submits
|
|
373
|
+
7. Your `onSubmit` handler receives all data
|
|
374
|
+
|
|
375
|
+
### Dashboard Flow
|
|
376
|
+
|
|
377
|
+
1. User opens dashboard (Ctrl+Shift+Q or programmatically)
|
|
378
|
+
2. Dashboard displays all feedback submissions
|
|
379
|
+
3. Developer can change status via dropdown
|
|
380
|
+
4. Status change triggers `onStatusChange` callback
|
|
381
|
+
5. Your backend updates the database
|
|
382
|
+
6. Dashboard reflects the new status
|
|
248
383
|
|
|
249
384
|
## Browser Support
|
|
250
385
|
|
|
251
|
-
- Chrome/Edge
|
|
252
|
-
- Firefox
|
|
253
|
-
- Safari
|
|
254
|
-
- Opera
|
|
386
|
+
- ✅ Chrome/Edge
|
|
387
|
+
- ✅ Firefox
|
|
388
|
+
- ✅ Safari
|
|
389
|
+
- ✅ Opera
|
|
390
|
+
|
|
391
|
+
## Screenshot Capture
|
|
255
392
|
|
|
256
|
-
|
|
393
|
+
Uses `html-to-image` with `html2canvas` fallback for:
|
|
394
|
+
- ✅ Perfect CSS rendering
|
|
395
|
+
- ✅ Tailwind, Bootstrap, Material-UI support
|
|
396
|
+
- ✅ Gradients, shadows, modern CSS
|
|
397
|
+
- ✅ High-resolution (2x pixel ratio)
|
|
257
398
|
|
|
258
399
|
## Dependencies
|
|
259
400
|
|
|
260
401
|
- React ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
261
402
|
- react-dom ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
403
|
+
- html-to-image ^1.11.13
|
|
262
404
|
- html2canvas ^1.4.1
|
|
263
405
|
- lucide-react ^0.263.1
|
|
264
406
|
|
|
265
|
-
## Local Development
|
|
266
|
-
|
|
267
|
-
Want to test the widget locally? We've included a complete example app!
|
|
268
|
-
|
|
269
|
-
### Quick Start
|
|
407
|
+
## Local Development
|
|
270
408
|
|
|
271
409
|
```bash
|
|
272
|
-
#
|
|
410
|
+
# Clone repository
|
|
273
411
|
git clone https://github.com/Murali1889/react-feedback-widget.git
|
|
274
412
|
cd react-feedback-widget
|
|
275
413
|
|
|
276
|
-
#
|
|
414
|
+
# Install dependencies
|
|
277
415
|
npm install
|
|
278
416
|
|
|
279
|
-
#
|
|
417
|
+
# Build the widget
|
|
280
418
|
npm run build
|
|
281
419
|
|
|
282
|
-
#
|
|
420
|
+
# Run example app
|
|
283
421
|
cd example
|
|
284
422
|
npm install
|
|
285
423
|
npm run dev
|
|
286
424
|
```
|
|
287
425
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
### What's Included
|
|
426
|
+
Visit `http://localhost:8080` to see the demo!
|
|
291
427
|
|
|
292
|
-
|
|
293
|
-
- ✅ Both controlled and uncontrolled mode examples
|
|
294
|
-
- ✅ Interactive test elements (buttons, forms, images)
|
|
295
|
-
- ✅ Console logging to see feedback data
|
|
296
|
-
- ✅ Hot reload for fast development
|
|
428
|
+
## What's New in v1.2.0
|
|
297
429
|
|
|
298
|
-
###
|
|
430
|
+
### Dashboard Feature
|
|
431
|
+
- 📊 Complete feedback management dashboard
|
|
432
|
+
- 👨💻 Developer/User mode with permission system
|
|
433
|
+
- 🏷️ 7 professional status options with custom dropdown
|
|
434
|
+
- 🔄 Status change callbacks for database sync
|
|
435
|
+
- 💾 localStorage or custom data source support
|
|
436
|
+
- 📅 Improved timestamp formatting (e.g., "21 Oct 2025 at 9:35 PM")
|
|
299
437
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
438
|
+
### UI Improvements
|
|
439
|
+
- ✨ Smooth animations for status dropdown
|
|
440
|
+
- 🎨 Professional minimal design
|
|
441
|
+
- 🔒 Read-only status for users
|
|
442
|
+
- 🗑️ Conditional delete permissions
|
|
305
443
|
|
|
306
444
|
## License
|
|
307
445
|
|
|
308
|
-
MIT © Murali
|
|
446
|
+
MIT © 2025 Murali Vvrsn Gurajapu
|
|
309
447
|
|
|
310
448
|
## Contributing
|
|
311
449
|
|
|
312
|
-
Contributions
|
|
450
|
+
Contributions welcome! Please submit a Pull Request.
|
|
313
451
|
|
|
314
452
|
## Issues
|
|
315
453
|
|
|
316
|
-
|
|
317
|
-
https://github.com/Murali1889/react-feedback-widget/issues
|
|
454
|
+
Report issues at: https://github.com/Murali1889/react-feedback-widget/issues
|
|
318
455
|
|
|
319
456
|
## Author
|
|
320
457
|
|
|
321
|
-
Murali
|
|
458
|
+
**Murali**
|
|
459
|
+
Email: murali.g@hyperverge.co
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
Made with ❤️ for better user feedback collection
|