react-feedback-surveys 1.7.0 → 1.9.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/README.md +223 -91
- package/dist/index.css +1 -1
- package/dist/index.d.ts +98 -11
- package/dist/index.js +2891 -2734
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -9,28 +9,36 @@
|
|
|
9
9
|
|
|
10
10
|
> Lightweight, customizable survey widgets to collect user feedback in React apps.
|
|
11
11
|
|
|
12
|
+
## Introduction
|
|
13
|
+
|
|
14
|
+
react-feedback-surveys is a standalone, open-source (MIT) UI library — no backend, no hosting, no
|
|
15
|
+
account required. Render the components, wire `onScoreSubmit`/`onFeedbackSubmit` to your own backend
|
|
16
|
+
(or nowhere at all).
|
|
17
|
+
|
|
18
|
+
Want AI-generated insights, a hosted dashboard, and response storage without building your own backend?
|
|
19
|
+
Check out [feedback.tools](https://feedback.tools) — built by the same team.
|
|
20
|
+
|
|
12
21
|
## Table of Contents
|
|
13
22
|
|
|
23
|
+
- [Introduction](#introduction)
|
|
14
24
|
- [Features](#features)
|
|
15
25
|
- [Survey Types](#survey-types)
|
|
16
26
|
- [Installation](#installation)
|
|
17
27
|
* [1. Install](#1-install)
|
|
18
28
|
* [2. Styles](#2-styles)
|
|
19
|
-
- [Survey
|
|
20
|
-
* [
|
|
21
|
-
* [
|
|
22
|
-
* [
|
|
23
|
-
* [CES7 (Customer Effort Score, 7-Point Scale)](#ces7-customer-effort-score-7-point-scale)
|
|
29
|
+
- [Survey Component](#survey-component)
|
|
30
|
+
* [CSAT (Customer Satisfaction Score)](#csat-customer-satisfaction-score)
|
|
31
|
+
* [NPS (Net Promoter Score)](#nps-net-promoter-score)
|
|
32
|
+
* [CES (Customer Effort Score)](#ces-customer-effort-score)
|
|
24
33
|
- [Layout Components](#layout-components)
|
|
25
34
|
* [Popup](#popup)
|
|
26
35
|
* [Surface](#surface)
|
|
27
36
|
- [Props](#props)
|
|
28
37
|
* [Shared Props](#shared-props)
|
|
38
|
+
* [Accessibility Labels](#accessibility-labels)
|
|
39
|
+
* [Attachments](#attachments)
|
|
40
|
+
* [Format Props](#format-props)
|
|
29
41
|
* [Scale Style Options](#scale-style-options)
|
|
30
|
-
+ [CSAT2Survey](#csat2survey)
|
|
31
|
-
+ [CSAT5Survey](#csat5survey)
|
|
32
|
-
+ [CES7Survey](#ces7survey)
|
|
33
|
-
+ [NPS10Survey](#nps10survey)
|
|
34
42
|
- [Styling](#styling)
|
|
35
43
|
* [CSS Variables](#css-variables)
|
|
36
44
|
* [Custom Classes](#custom-classes)
|
|
@@ -47,20 +55,25 @@
|
|
|
47
55
|
|
|
48
56
|
## Features
|
|
49
57
|
|
|
50
|
-
- **
|
|
58
|
+
- **A single `Survey` component** – the format (methodology, scale length, visual style) is configuration, not a different import
|
|
59
|
+
- **Ready-to-use survey formats** – CSAT (2 or 5 points), CES (7 points), NPS (0–10)
|
|
51
60
|
- **Multiple scale styles** – emoji, stars, numbers, thumbs
|
|
52
61
|
- **Flexible placement** – embed inline or display as popup overlay
|
|
53
62
|
- **Follow-up feedback** – optional text input or multiple choice responses
|
|
54
63
|
- **Optional email collection** – close the loop by capturing a respondent's email when no user identity is known
|
|
64
|
+
- **Optional screenshot attachments** – let respondents attach a screenshot, captured by a function you provide
|
|
55
65
|
- **Fully customizable** – CSS variables and custom class names
|
|
56
66
|
- **Zero dependencies**
|
|
57
67
|
- **TypeScript support**
|
|
58
68
|
|
|
59
69
|
## Survey Types
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- **
|
|
71
|
+
`Survey` covers four feedback methodologies, selected with the `type` prop. `CSAT` is the only one with a variable scale length, set via `points`:
|
|
72
|
+
|
|
73
|
+
- **CSAT (Customer Satisfaction Score):** `type="csat"`, 2-point or 5-point scale (`points={2}` or `points={5}`)
|
|
74
|
+
- **NPS (Net Promoter Score):** `type="nps"`, fixed 0–10 scale
|
|
75
|
+
- **CES (Customer Effort Score):** `type="ces"`, fixed 7-point scale
|
|
76
|
+
- **General (text feedback only):** `type="general"`, no rating scale — see [General](#general-text-feedback-only)
|
|
64
77
|
|
|
65
78
|
## Installation
|
|
66
79
|
|
|
@@ -78,24 +91,28 @@ yarn add react-feedback-surveys
|
|
|
78
91
|
import 'react-feedback-surveys/index.css';
|
|
79
92
|
```
|
|
80
93
|
|
|
81
|
-
## Survey
|
|
94
|
+
## Survey Component
|
|
95
|
+
|
|
96
|
+
Every format is reached through the same `Survey` import — `type` and `points` pick the methodology and scale length, `scaleStyle` picks the visual style. See [Format Props](#format-props) for the full matrix of valid `type`/`points`/`scaleStyle` combinations.
|
|
82
97
|
|
|
83
|
-
###
|
|
98
|
+
### CSAT (Customer Satisfaction Score)
|
|
84
99
|
|
|
85
|
-
Surveys to ask users about their overall satisfaction.
|
|
100
|
+
Surveys to ask users about their overall satisfaction, or about a specific feature or flow.
|
|
86
101
|
|
|
87
102
|
**Example questions:**
|
|
88
103
|
- "How satisfied are you with our product?"
|
|
89
|
-
- "
|
|
90
|
-
- "
|
|
104
|
+
- "Was this search helpful?"
|
|
105
|
+
- "Are you satisfied with the checkout process?"
|
|
91
106
|
|
|
92
|
-
<img alt="
|
|
107
|
+
<img alt="CSAT, 5-point scale" src="docs/assets/csat5.png" width="416" />
|
|
93
108
|
|
|
94
109
|
```tsx
|
|
95
|
-
import {
|
|
110
|
+
import { Survey } from 'react-feedback-surveys';
|
|
96
111
|
import 'react-feedback-surveys/index.css';
|
|
97
112
|
|
|
98
|
-
<
|
|
113
|
+
<Survey
|
|
114
|
+
type="csat"
|
|
115
|
+
points={5}
|
|
99
116
|
scaleStyle="emoji"
|
|
100
117
|
question="How would you rate your satisfaction with our product?"
|
|
101
118
|
minLabel="Very unsatisfied"
|
|
@@ -110,24 +127,12 @@ import 'react-feedback-surveys/index.css';
|
|
|
110
127
|
/>
|
|
111
128
|
```
|
|
112
129
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
### CSAT2 (Customer Satisfaction Score, 2-Point Scale)
|
|
116
|
-
|
|
117
|
-
Surveys to ask users about specific features or flows.
|
|
118
|
-
|
|
119
|
-
**Example questions:**
|
|
120
|
-
- "Was this search helpful?"
|
|
121
|
-
- "Did you find what you were looking for?"
|
|
122
|
-
- "Are you satisfied with the checkout process?"
|
|
123
|
-
|
|
124
|
-
<img alt="CSAT2" src="docs/assets/csat2.png" width="386" />
|
|
130
|
+
<img alt="CSAT, 2-point scale" src="docs/assets/csat2.png" width="386" />
|
|
125
131
|
|
|
126
132
|
```tsx
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<CSAT2Survey
|
|
133
|
+
<Survey
|
|
134
|
+
type="csat"
|
|
135
|
+
points={2}
|
|
131
136
|
scaleStyle="thumbs"
|
|
132
137
|
question="Are you satisfied with the result?"
|
|
133
138
|
responseType="text"
|
|
@@ -140,26 +145,27 @@ import 'react-feedback-surveys/index.css';
|
|
|
140
145
|
/>
|
|
141
146
|
```
|
|
142
147
|
|
|
143
|
-
`scaleStyle`: `emoji` | `thumbs`.
|
|
148
|
+
`points={5}` → `scaleStyle`: `emoji` | `numbers` | `stars`. `points={2}` → `scaleStyle`: `emoji` | `thumbs`.
|
|
144
149
|
|
|
145
|
-
###
|
|
150
|
+
### NPS (Net Promoter Score)
|
|
146
151
|
|
|
147
|
-
Surveys to ask users if they'd recommend your product.
|
|
152
|
+
Surveys to ask users if they'd recommend your product. Fixed 0–10 scale — no `points` prop needed.
|
|
148
153
|
|
|
149
154
|
**Example questions:**
|
|
150
155
|
- "How likely are you to recommend us to a friend or colleague?"
|
|
151
156
|
- "On a scale of 0-10, would you recommend our service?"
|
|
152
157
|
- "How likely are you to recommend this product to others?"
|
|
153
158
|
|
|
154
|
-
<img alt="
|
|
159
|
+
<img alt="NPS" src="docs/assets/nps10.png" width="616" />
|
|
155
160
|
|
|
156
|
-
<img alt="
|
|
161
|
+
<img alt="NPS mobile" src="docs/assets/nps10-mobile.png" width="340" />
|
|
157
162
|
|
|
158
163
|
```tsx
|
|
159
|
-
import {
|
|
164
|
+
import { Survey } from 'react-feedback-surveys';
|
|
160
165
|
import 'react-feedback-surveys/index.css';
|
|
161
166
|
|
|
162
|
-
<
|
|
167
|
+
<Survey
|
|
168
|
+
type="nps"
|
|
163
169
|
scaleStyle="numbers"
|
|
164
170
|
question="How likely are you to recommend our product/service to a friend or colleague?"
|
|
165
171
|
minLabel="Very unlikely"
|
|
@@ -176,22 +182,23 @@ import 'react-feedback-surveys/index.css';
|
|
|
176
182
|
|
|
177
183
|
`scaleStyle`: `numbers`.
|
|
178
184
|
|
|
179
|
-
###
|
|
185
|
+
### CES (Customer Effort Score)
|
|
180
186
|
|
|
181
|
-
Surveys to ask users how easy it is to use your product.
|
|
187
|
+
Surveys to ask users how easy it is to use your product. Fixed 7-point scale — no `points` prop needed.
|
|
182
188
|
|
|
183
189
|
**Example questions:**
|
|
184
190
|
- "How easy was it to complete your task?"
|
|
185
191
|
- "How much effort did it take to resolve your issue?"
|
|
186
192
|
- "How easy was it to sign up for an account?"
|
|
187
193
|
|
|
188
|
-
<img alt="
|
|
194
|
+
<img alt="CES" src="docs/assets/ces7.png" width="436" />
|
|
189
195
|
|
|
190
196
|
```tsx
|
|
191
|
-
import {
|
|
197
|
+
import { Survey } from 'react-feedback-surveys';
|
|
192
198
|
import 'react-feedback-surveys/index.css';
|
|
193
199
|
|
|
194
|
-
<
|
|
200
|
+
<Survey
|
|
201
|
+
type="ces"
|
|
195
202
|
scaleStyle="numbers"
|
|
196
203
|
question="How easy was it to complete your task?"
|
|
197
204
|
minLabel="Very difficult"
|
|
@@ -208,6 +215,31 @@ import 'react-feedback-surveys/index.css';
|
|
|
208
215
|
|
|
209
216
|
`scaleStyle`: `numbers`.
|
|
210
217
|
|
|
218
|
+
### General (text feedback only)
|
|
219
|
+
|
|
220
|
+
No rating scale — just text feedback and an optional screenshot. The text feedback step is shown immediately and is the whole survey; there's no `points`/`scaleStyle`/`minLabel`/`maxLabel`/`question` to set.
|
|
221
|
+
|
|
222
|
+
**Example use cases:**
|
|
223
|
+
- A general "Send feedback" or "Report a problem" trigger with no methodology attached.
|
|
224
|
+
- Contexts where a numeric rating doesn't make sense.
|
|
225
|
+
|
|
226
|
+
<img alt="General" src="docs/assets/general.png" width="368" />
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
import { Survey } from 'react-feedback-surveys';
|
|
230
|
+
import 'react-feedback-surveys/index.css';
|
|
231
|
+
|
|
232
|
+
<Survey
|
|
233
|
+
type="general"
|
|
234
|
+
textQuestion="Got feedback? We'd love to hear it"
|
|
235
|
+
textButtonSendLabel="Send"
|
|
236
|
+
thankYouMessage="Thank you for your feedback!"
|
|
237
|
+
onFeedbackSubmit={({ text }) => {/* ... */}}
|
|
238
|
+
/>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`responseType` defaults to `'text'` (also accepts `'choices'`) — it can't be unset, since the text feedback step is the only content the survey has. The step is mandatory: there's no Skip button (`textButtonSkipLabel` is ignored for `type="general"`), and Submit stays disabled until there's something to send.
|
|
242
|
+
|
|
211
243
|
## Layout Components
|
|
212
244
|
|
|
213
245
|
### Popup
|
|
@@ -219,7 +251,7 @@ The `<Popup>` component wraps survey widgets in a fixed overlay that slides in f
|
|
|
219
251
|
#### Usage
|
|
220
252
|
|
|
221
253
|
```tsx
|
|
222
|
-
import { Popup,
|
|
254
|
+
import { Popup, Survey } from 'react-feedback-surveys';
|
|
223
255
|
import 'react-feedback-surveys/index.css';
|
|
224
256
|
|
|
225
257
|
<Popup
|
|
@@ -232,7 +264,9 @@ import 'react-feedback-surveys/index.css';
|
|
|
232
264
|
placement="bottomRight"
|
|
233
265
|
onClose={() => console.log('Closed')}
|
|
234
266
|
>
|
|
235
|
-
<
|
|
267
|
+
<Survey
|
|
268
|
+
type="csat"
|
|
269
|
+
points={5}
|
|
236
270
|
scaleStyle="stars"
|
|
237
271
|
question="How would you rate your satisfaction?"
|
|
238
272
|
onScoreSubmit={({ value }) => {/* ... */}}
|
|
@@ -249,9 +283,13 @@ import 'react-feedback-surveys/index.css';
|
|
|
249
283
|
| `className` | `string` | - | - | Additional CSS class name for the popup container. |
|
|
250
284
|
| `classNames` | `{ base?: string; content?: string; close?: string }` | - | - | Optional class names for internal popup elements. |
|
|
251
285
|
| `children` | `React.ReactNode` | - | - | Content to render inside the popup (typically a survey component). |
|
|
286
|
+
| `closeLabel` | `string` | - | `'Close survey'` | Close button label, used for both its `aria-label` and `title`. |
|
|
252
287
|
| `onClose` | `() => void` | - | - | Callback fired when the close button is clicked. |
|
|
253
288
|
|
|
254
|
-
For more examples, check out the Storybook stories
|
|
289
|
+
For more examples, check out the Storybook stories under `widgets/Survey` (grouped by CSAT/NPS/CES in the sidebar).
|
|
290
|
+
|
|
291
|
+
> **Note**
|
|
292
|
+
> If the survey inside uses `dir="rtl"` on a page that's otherwise LTR (or vice versa), pass the same `dir` to `Popup` too — the close button's position resolves against the document direction, while the survey head's reserved offset resolves against the survey's own `dir`. Passing both keeps them aligned.
|
|
255
293
|
|
|
256
294
|
### Surface
|
|
257
295
|
|
|
@@ -265,11 +303,13 @@ The Surface component provides:
|
|
|
265
303
|
#### Usage
|
|
266
304
|
|
|
267
305
|
```tsx
|
|
268
|
-
import { Surface,
|
|
306
|
+
import { Surface, Survey } from 'react-feedback-surveys';
|
|
269
307
|
import 'react-feedback-surveys/index.css';
|
|
270
308
|
|
|
271
309
|
<Surface className="custom-surface">
|
|
272
|
-
<
|
|
310
|
+
<Survey
|
|
311
|
+
type="csat"
|
|
312
|
+
points={5}
|
|
273
313
|
scaleStyle="stars"
|
|
274
314
|
question="How would you rate your satisfaction?"
|
|
275
315
|
onScoreSubmit={({ value }) => {/* ... */}}
|
|
@@ -288,7 +328,7 @@ The Surface component uses the `--ft-surface-padding`, `--ft-surface-padding-mob
|
|
|
288
328
|
|
|
289
329
|
## Props
|
|
290
330
|
|
|
291
|
-
Most props are shared across
|
|
331
|
+
Most props are shared across every survey format. `type` (and `points`, for CSAT) select the format; `scaleStyle` picks its visual style — see [Format Props](#format-props).
|
|
292
332
|
|
|
293
333
|
### Shared Props
|
|
294
334
|
|
|
@@ -296,14 +336,17 @@ Most props are shared across all survey widgets. Each widget differs only in its
|
|
|
296
336
|
|--------------------|-------------------------------|----------|------------------------------------------------------------------------------|
|
|
297
337
|
| `classNames` | `ClassNamesConfig` (see below)| - | Optional class names to target internal parts. |
|
|
298
338
|
| `dir` | `'ltr' \| 'rtl' \| 'auto'` | - | Text direction for RTL/LTR language support. |
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
339
|
+
| `strings` | `SurveyStrings` (see below) | - | Overrides for the library's own aria-labels and other screen-reader-only text. See [Accessibility Labels](#accessibility-labels). |
|
|
340
|
+
| `question` | `string` | required (not used for `type="general"`) | Main survey question displayed on the first screen. |
|
|
341
|
+
| `minLabel` | `string` | - | Left label for the scale. Not used for `type="general"`. |
|
|
342
|
+
| `maxLabel` | `string` | - | Right label for the scale. Not used for `type="general"`. |
|
|
343
|
+
| `getScoreLabelSuffix` | `(label: string) => string` | - | Builds the visible text appended after the first/last numbered scale button when it carries `minLabel`/`maxLabel`. Default `` (label) => ` - ${label}` ``. Applies to the `numbers` scale style (CSAT5, CES, NPS). |
|
|
344
|
+
| `responseType` | `null \| 'text' \| 'choices'` (`'text' \| 'choices'` for `type="general"`, defaults to `'text'`) | - | Enables optional follow-up feedback. |
|
|
303
345
|
| `textQuestion` | `string` | - | Follow-up question displayed when `responseType` is defined. |
|
|
304
346
|
| `textButtonSendLabel` | `string` | - | Submit label for the feedback screen. |
|
|
305
347
|
| `textButtonSkipLabel` | `string` | - | Skip label for the feedback screen. |
|
|
306
348
|
| `choiceOptions` | `string[] \| null` | - | Predefined choices (when `responseType === 'choices'`). |
|
|
349
|
+
| `otherPlaceholder` | `string` | - | Placeholder for the free-text input next to choice checkboxes. Default `'Other'`. |
|
|
307
350
|
| `thankYouMessage` | `string` | required | Message shown after submission. |
|
|
308
351
|
| `collectContact` | `boolean` | - | Enables an optional email collection step before the success screen. |
|
|
309
352
|
| `userId` | `string` | - | Existing user identity. When provided, the email collection step is skipped. |
|
|
@@ -311,6 +354,43 @@ Most props are shared across all survey widgets. Each widget differs only in its
|
|
|
311
354
|
| `contactSubtext` | `string` | - | Descriptive text shown above the email input. |
|
|
312
355
|
| `contactButtonSendLabel` | `string` | - | Submit label for the email collection screen. |
|
|
313
356
|
| `contactButtonSkipLabel` | `string` | - | Skip label for the email collection screen. |
|
|
357
|
+
| `onCaptureScreenshot` | `() => string \| Blob \| Promise<string \| Blob>` | - | Enables an optional screenshot-attachment control on the feedback step. Hidden unless provided — see [Attachments](#attachments). |
|
|
358
|
+
| `screenshotButtonLabel` | `string` | - | Label for the screenshot-attachment control. |
|
|
359
|
+
| `screenshotErrorMessage` | `string` | - | Shown to the respondent when `onCaptureScreenshot` fails. Default `'Failed to capture screenshot'`. |
|
|
360
|
+
| `maxAttachments` | `number` | - | Maximum number of attachments a respondent may confirm. Default `1`. See [Attachments](#attachments). |
|
|
361
|
+
| `attachmentCaption` | `string` | - | Visible caption under an attachment thumbnail, also used as its image alt text. Default `'Screenshot'`. |
|
|
362
|
+
|
|
363
|
+
### Accessibility Labels
|
|
364
|
+
|
|
365
|
+
A handful of internal aria-labels ship with an English default. These are never visible UI copy (that's `question`, `thankYouMessage`, `otherPlaceholder`, `attachmentCaption`, etc., always authored by you, listed alongside the rest of the shared props above) — every key in `strings` is announced to assistive tech only, useful to override if you're localizing a survey for a non-English audience.
|
|
366
|
+
|
|
367
|
+
Pass a `strings` object with only the keys you want to change — each one merges over its own English default, so there's no need to repeat the rest:
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
<Survey
|
|
371
|
+
/* ... */
|
|
372
|
+
strings={{
|
|
373
|
+
emailLabel: 'Adresse e-mail',
|
|
374
|
+
getScoreLabel: (score) => `Score ${score}`
|
|
375
|
+
}}
|
|
376
|
+
/>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### SurveyStrings Type
|
|
380
|
+
|
|
381
|
+
| Key | Type | Default |
|
|
382
|
+
|-----|------|---------|
|
|
383
|
+
| `feedbackFormLabel` | `string` | `'Feedback form'` |
|
|
384
|
+
| `additionalFeedbackLabel` | `string` | `'Additional feedback'` |
|
|
385
|
+
| `yourFeedbackLabel` | `string` | `'Your feedback'` |
|
|
386
|
+
| `contactFormLabel` | `string` | `'Contact form'` |
|
|
387
|
+
| `emailLabel` | `string` | `'Email address'` |
|
|
388
|
+
| `attachmentOpenLabel` | `string` | `'Open screenshot in a new tab'` |
|
|
389
|
+
| `attachmentRemoveLabel` | `string` | `'Remove screenshot'` |
|
|
390
|
+
| `getScoreLabel` | `(score: number) => string` | `(score) => \`Score ${score}\`` |
|
|
391
|
+
| `getStarsLabel` | `(score: number) => string` | `(score) => \`${score} ${score > 1 ? 'stars' : 'star'}\`` |
|
|
392
|
+
|
|
393
|
+
`getScoreLabel` applies to the `numbers` scale style (CSAT5, CES, NPS); `getStarsLabel` applies to CSAT5's `stars` style. Both are callbacks rather than templates so you can apply correct pluralization for your target language. `Popup`'s close button label lives on `Popup` itself, not in `strings` — see its own `closeLabel` prop in [Popup Props](#props).
|
|
314
394
|
|
|
315
395
|
#### ClassNamesConfig Type
|
|
316
396
|
|
|
@@ -350,10 +430,13 @@ interface ClassNamesConfig {
|
|
|
350
430
|
|
|
351
431
|
```typescript
|
|
352
432
|
type ScorePayload = { value: number };
|
|
353
|
-
type FeedbackPayload = { value
|
|
433
|
+
type FeedbackPayload = { value?: number; text?: string | string[]; attachments?: Attachment[] };
|
|
354
434
|
type ContactPayload = { value?: number; text?: string | string[]; email: string };
|
|
435
|
+
type Attachment = { kind: 'screenshot'; data: string | Blob; name?: string; mimeType?: string; size?: number };
|
|
355
436
|
```
|
|
356
437
|
|
|
438
|
+
> See [Attachments](#attachments).
|
|
439
|
+
|
|
357
440
|
> **Event behavior**
|
|
358
441
|
|
|
359
442
|
#### `onScoreSubmit`
|
|
@@ -372,13 +455,14 @@ The actual `value` returned depends on the survey type:
|
|
|
372
455
|
Invoked when the user completes the follow-up step and submits their feedback (only applies when `responseType` is `text` or `choices`).
|
|
373
456
|
This callback provides both the original score and the user's input.
|
|
374
457
|
|
|
375
|
-
|
|
458
|
+
For surveys with a rating step, the feedback step is optional: respondents can submit feedback or skip it via the `textButtonSkipLabel` button (or by submitting with empty input), and either action advances to the next screen. For `type="general"`, the feedback step **is** the survey, so there's no Skip button — Submit stays disabled until there's something to send. `onFeedbackSubmit` only fires when feedback text or choices are actually submitted; it is **not** called when a rating-survey's step is skipped.
|
|
376
459
|
|
|
377
460
|
**Arguments:**
|
|
378
|
-
- `value
|
|
461
|
+
- `value?: number` — the same score previously passed to `onScoreSubmit`; `undefined` for `type="general"`, which has no rating step
|
|
379
462
|
- `text: string | string[]` — depends on `responseType`:
|
|
380
|
-
- `text`: a single text
|
|
381
|
-
- `choices`: an array of selected options (may include
|
|
463
|
+
- `text`: a single text feedback string
|
|
464
|
+
- `choices`: an array of selected options (may include free-text feedback if enabled)
|
|
465
|
+
- `attachments?: Attachment[]` — present when the respondent confirmed a screenshot; see [Attachments](#attachments)
|
|
382
466
|
|
|
383
467
|
> **Important**
|
|
384
468
|
You should listen to **both** `onScoreSubmit` and `onFeedbackSubmit`.
|
|
@@ -399,7 +483,9 @@ When `collectContact` is `true` and no `userId` is provided, an optional email c
|
|
|
399
483
|
- `email: string` — the email address entered by the respondent.
|
|
400
484
|
|
|
401
485
|
```tsx
|
|
402
|
-
<
|
|
486
|
+
<Survey
|
|
487
|
+
type="csat"
|
|
488
|
+
points={5}
|
|
403
489
|
scaleStyle="numbers"
|
|
404
490
|
question="How would you rate your satisfaction with our product?"
|
|
405
491
|
responseType="text"
|
|
@@ -416,35 +502,73 @@ When `collectContact` is `true` and no `userId` is provided, an optional email c
|
|
|
416
502
|
/>
|
|
417
503
|
```
|
|
418
504
|
|
|
419
|
-
###
|
|
505
|
+
### Attachments
|
|
420
506
|
|
|
421
|
-
Each
|
|
507
|
+
Respondents can attach a screenshot to their feedback, surfaced on submit as `attachments?: Attachment[]` (see the event payload types above). Each attachment renders as a thumbnail in the feedback step, with a caption and size underneath, click to open it in a new tab, click the "x" to remove it. Submit is disabled for the brief moment a capture is still in flight, so it can't be confirmed before the attachment actually lands in the list.
|
|
422
508
|
|
|
423
|
-
|
|
509
|
+
Once an attachment is confirmed, the Skip button is disabled — an attached screenshot is never silently discarded. Remove the attachment to re-enable Skip, or fill in feedback and submit to keep it. An attachment on its own is never sufficient to submit, either: for `responseType="text"`, submitting with an attachment but no text flags the textarea instead of sending; for `responseType="choices"`, Submit stays disabled until a choice is picked or text is entered.
|
|
424
510
|
|
|
425
|
-
|
|
426
|
-
|--------------------------|-------------------------|----------|-----------------------------------------------------------------------------------|
|
|
427
|
-
| `scaleStyle` | `'emoji'` \| `'thumbs'` | required | Emoji mood scale style (happy/sad faces) or thumbs up/down emoji scale style. |
|
|
511
|
+
By default a respondent can confirm a single attachment: once one is attached, the add control hides. Pass `maxAttachments` to raise (or lower) that cap. The add control stays visible (below the existing thumbnails) until the cap is reached:
|
|
428
512
|
|
|
429
|
-
|
|
513
|
+
```tsx
|
|
514
|
+
<Survey
|
|
515
|
+
/* ... */
|
|
516
|
+
onCaptureScreenshot={() => domToDataUrl(document.body)}
|
|
517
|
+
maxAttachments={3}
|
|
518
|
+
/>
|
|
519
|
+
```
|
|
430
520
|
|
|
431
|
-
|
|
432
|
-
|--------------------------|---------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------|
|
|
433
|
-
| `scaleStyle` | `'emoji'` \| `'numbers'` \| `'stars'` | required | Emoji scale style (5 emotion levels), numeric scale style (1–5), or star rating scale style (1–5 stars). |
|
|
521
|
+
Pass `onCaptureScreenshot` to add an "Capture screenshot" control to the feedback step. Clicking it calls your function and attaches the result immediately. The control is off by default: it doesn't render at all unless `onCaptureScreenshot` is provided.
|
|
434
522
|
|
|
435
|
-
|
|
523
|
+
Capturing a screenshot needs an actual DOM-to-image library (or a native bridge in a hybrid app) — real, non-trivial code that most consumers of this package won't want to pay for in bundle size if they don't use the feature. So react-feedback-surveys deliberately doesn't ship a capture implementation itself: bring your own function that returns the captured image (as a data URL string, a `Blob`, or a `Promise` of either). A drop-in recipe using [modern-screenshot](https://github.com/qq15725/modern-screenshot):
|
|
436
524
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
525
|
+
```shell
|
|
526
|
+
npm i modern-screenshot
|
|
527
|
+
```
|
|
440
528
|
|
|
441
|
-
|
|
529
|
+
```tsx
|
|
530
|
+
import { Survey } from 'react-feedback-surveys';
|
|
531
|
+
import { domToDataUrl } from 'modern-screenshot';
|
|
532
|
+
import 'react-feedback-surveys/index.css';
|
|
442
533
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
534
|
+
<Survey
|
|
535
|
+
type="csat"
|
|
536
|
+
points={5}
|
|
537
|
+
scaleStyle="numbers"
|
|
538
|
+
question="How would you rate your satisfaction with our product?"
|
|
539
|
+
responseType="text"
|
|
540
|
+
textQuestion="We'd love to hear your thoughts — what can we improve?"
|
|
541
|
+
thankYouMessage="Thanks for your feedback!"
|
|
542
|
+
onCaptureScreenshot={() => domToDataUrl(document.body)}
|
|
543
|
+
onScoreSubmit={({ value }) => {/* ... */}}
|
|
544
|
+
onFeedbackSubmit={({ value, text, attachments }) => {/* attachments?.[0]?.data holds the attached screenshot */}}
|
|
545
|
+
/>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
In a hybrid app, `onCaptureScreenshot` can just as well call into a native bridge (e.g. `WKWebView.takeSnapshot` on iOS) instead of a DOM-to-image library.
|
|
446
549
|
|
|
447
|
-
Note
|
|
550
|
+
> **Note**
|
|
551
|
+
> DOM-to-image capture is best-effort — fonts, cross-origin images, and some CSS effects may not render identically on every browser (particularly Safari/iOS). The respondent can open the attached thumbnail in a new tab to check it, and remove it with one click if the capture came out wrong.
|
|
552
|
+
|
|
553
|
+
### Format Props
|
|
554
|
+
|
|
555
|
+
| Prop | Type | Required | Description |
|
|
556
|
+
|------|------|----------|--------------|
|
|
557
|
+
| `type` | `'csat'` \| `'nps'` \| `'ces'` \| `'general'` | required | Survey methodology. Determines the scale range and which `scaleStyle`/`points` combinations are valid. `'general'` has no scale at all — see [General](#general-text-feedback-only). |
|
|
558
|
+
| `points` | `2` \| `5` | required for `type="csat"`; not used otherwise | Number of points on the scale. `nps` is a fixed 0–10 scale and `ces` a fixed 1–7 scale, so neither takes `points`. |
|
|
559
|
+
|
|
560
|
+
### Scale Style Options
|
|
561
|
+
|
|
562
|
+
Valid `scaleStyle` values depend on `type` (and `points`, for CSAT):
|
|
563
|
+
|
|
564
|
+
| `type` | `points` | Scale range | Valid `scaleStyle` |
|
|
565
|
+
|--------|----------|-------------|---------------------|
|
|
566
|
+
| `csat` | `5` | 1–5 | `'emoji'` (5 emotion levels) \| `'numbers'` \| `'stars'` (1–5 stars) |
|
|
567
|
+
| `csat` | `2` | 0–1 | `'emoji'` (happy/sad faces) \| `'thumbs'` (thumbs up/down) |
|
|
568
|
+
| `ces` | — | 1–7 | `'numbers'` |
|
|
569
|
+
| `nps` | — | 0–10 | `'numbers'` |
|
|
570
|
+
|
|
571
|
+
Invalid combinations (e.g. `type="ces"` with `scaleStyle="stars"`) are rejected at the type level.
|
|
448
572
|
|
|
449
573
|
## Styling
|
|
450
574
|
|
|
@@ -472,6 +596,9 @@ You can override colors and fonts via CSS variables:
|
|
|
472
596
|
/* Error color for validation messages */
|
|
473
597
|
--ft-color-error: 32 95% 44%;
|
|
474
598
|
|
|
599
|
+
/* Error text color (attachment capture errors) — darker than --ft-color-error, tuned for text contrast rather than borders/outlines */
|
|
600
|
+
--ft-color-error-text: 32 95% 32%;
|
|
601
|
+
|
|
475
602
|
/* Border color for inputs and containers */
|
|
476
603
|
--ft-color-border: 214 14% 83%;
|
|
477
604
|
|
|
@@ -493,7 +620,7 @@ You can override colors and fonts via CSS variables:
|
|
|
493
620
|
--ft-popup-head-offset: 0;
|
|
494
621
|
|
|
495
622
|
/* Padding for Surface component container (desktop) */
|
|
496
|
-
--ft-surface-padding:
|
|
623
|
+
--ft-surface-padding: 20px;
|
|
497
624
|
|
|
498
625
|
/* Padding for Surface component container on mobile devices (max-width: 400px) */
|
|
499
626
|
--ft-surface-padding-mobile: 20px;
|
|
@@ -523,6 +650,7 @@ Here's an example of dark theme colors that work well with the survey components
|
|
|
523
650
|
--ft-color-bg: 220 13% 13%;
|
|
524
651
|
--ft-color-muted: 214 10% 60%;
|
|
525
652
|
--ft-color-error: 14 90% 62%;
|
|
653
|
+
--ft-color-error-text: 14 85% 72%;
|
|
526
654
|
--ft-color-border: 217 10% 28%;
|
|
527
655
|
--ft-color-outline: 216 12% 45%;
|
|
528
656
|
--ft-color-shadow: 0 0% 0%;
|
|
@@ -549,7 +677,7 @@ Here's an example of dark theme colors that work well with the survey components
|
|
|
549
677
|
**Implementation example with React:**
|
|
550
678
|
|
|
551
679
|
```tsx
|
|
552
|
-
import {
|
|
680
|
+
import { Survey } from 'react-feedback-surveys';
|
|
553
681
|
import 'react-feedback-surveys/index.css';
|
|
554
682
|
import { useEffect } from 'react';
|
|
555
683
|
|
|
@@ -573,7 +701,9 @@ function App() {
|
|
|
573
701
|
}, []);
|
|
574
702
|
|
|
575
703
|
return (
|
|
576
|
-
<
|
|
704
|
+
<Survey
|
|
705
|
+
type="csat"
|
|
706
|
+
points={5}
|
|
577
707
|
scaleStyle="emoji"
|
|
578
708
|
question="How satisfied are you with our product?"
|
|
579
709
|
onScoreSubmit={({ value }) => console.log('Score:', value)}
|
|
@@ -608,7 +738,7 @@ For deeper customization strategies, see the section below.
|
|
|
608
738
|
|
|
609
739
|
### Custom Classes
|
|
610
740
|
|
|
611
|
-
|
|
741
|
+
`Survey` accepts a `classNames` prop with two optional groups: `base` (outer shell) and `scale` (the interactive
|
|
612
742
|
rating UI). Pass your own class names to override styles without relying on internal selectors.
|
|
613
743
|
|
|
614
744
|
When is this useful?
|
|
@@ -637,13 +767,13 @@ Reference: available keys
|
|
|
637
767
|
| `scale.score` | Number inside a scale button (for numeric variants) |
|
|
638
768
|
| `scale.labels` | Left/Right labels displayed under the scale |
|
|
639
769
|
|
|
640
|
-
Example: customizing a
|
|
770
|
+
Example: customizing a `Survey` widget
|
|
641
771
|
|
|
642
772
|
```tsx
|
|
643
|
-
import {
|
|
773
|
+
import { Survey } from 'react-feedback-surveys';
|
|
644
774
|
import 'react-feedback-surveys/index.css';
|
|
645
775
|
|
|
646
|
-
<
|
|
776
|
+
<Survey
|
|
647
777
|
classNames={{
|
|
648
778
|
base: {
|
|
649
779
|
base: 'my-survey-base',
|
|
@@ -659,6 +789,8 @@ import 'react-feedback-surveys/index.css';
|
|
|
659
789
|
labels: 'my-scale-labels',
|
|
660
790
|
}
|
|
661
791
|
}}
|
|
792
|
+
type="csat"
|
|
793
|
+
points={5}
|
|
662
794
|
scaleStyle="numbers"
|
|
663
795
|
question="How would you rate your satisfaction with our product?"
|
|
664
796
|
minLabel="Very unsatisfied"
|