@revova/hydrogen 1.0.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 ADDED
@@ -0,0 +1,384 @@
1
+ # @revova/hydrogen
2
+
3
+ Official Revova review widgets for Shopify Hydrogen storefronts.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @revova/hydrogen
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ - React 18+
14
+ - Shopify Hydrogen storefront with the Revova app installed
15
+
16
+ ---
17
+
18
+ ## Quick Start
19
+
20
+ The `proxyUrl` is always `/apps/revova` — Shopify's App Proxy routes requests to your Revova backend automatically. No API keys needed in the storefront.
21
+
22
+ ---
23
+
24
+ ## Components
25
+
26
+ ### `<ReviewWidget>`
27
+
28
+ Full review list with pagination, sorting, and an inline submission form.
29
+
30
+ ```tsx
31
+ import { ReviewWidget } from '@revova/hydrogen';
32
+
33
+ export default function ProductPage() {
34
+ const { product } = useLoaderData<typeof loader>();
35
+
36
+ return (
37
+ <ReviewWidget
38
+ proxyUrl="/apps/revova"
39
+ productId={product.id}
40
+ />
41
+ );
42
+ }
43
+ ```
44
+
45
+ **Props**
46
+
47
+ | Prop | Type | Default | Description |
48
+ |---|---|---|---|
49
+ | `proxyUrl` | `string` | — | App proxy base URL (`/apps/revova`) |
50
+ | `productId` | `string` | — | Shopify product GID |
51
+ | `locale` | `string` | — | Locale code for translated reviews (e.g. `fr`) |
52
+ | `pageSize` | `number` | `10` | Reviews per page |
53
+ | `showForm` | `boolean` | `true` | Show the write-review button and form |
54
+ | `starColor` | `string` | `#f59e0b` | Star fill colour |
55
+ | `className` | `string` | — | CSS class on the wrapper |
56
+
57
+ ---
58
+
59
+ ### `<ReviewForm>`
60
+
61
+ Standalone submission form — use when you want the form separate from the list.
62
+
63
+ ```tsx
64
+ import { ReviewForm } from '@revova/hydrogen';
65
+
66
+ // `form` comes from the ReviewsResponse returned by useReviews
67
+ <ReviewForm
68
+ proxyUrl="/apps/revova"
69
+ productId={product.id}
70
+ form={data.form}
71
+ onSuccess={() => console.log('submitted')}
72
+ />
73
+ ```
74
+
75
+ **Props:** `proxyUrl`, `productId`, `form` (required — `ResolvedForm` from loader), `onSuccess?`, `className?`
76
+
77
+ ---
78
+
79
+ ### `<StarRating>`
80
+
81
+ Renders star icons for any numeric rating. Supports half-stars via linear gradient fill.
82
+
83
+ ```tsx
84
+ import { StarRating } from '@revova/hydrogen';
85
+
86
+ <StarRating rating={4.5} size={20} color="#f59e0b" />
87
+ ```
88
+
89
+ **Props:** `rating` (0–5), `max?` (default 5), `size?` (px, default 16), `color?`, `className?`
90
+
91
+ ---
92
+
93
+ ### `<ReviewCount>`
94
+
95
+ Aggregate rating + review count badge. Fetches from `widget-globals`.
96
+
97
+ ```tsx
98
+ import { ReviewCount } from '@revova/hydrogen';
99
+
100
+ // On a product card or PDP header
101
+ <ReviewCount proxyUrl="/apps/revova" starSize={14} />
102
+ ```
103
+
104
+ **Props:** `proxyUrl`, `starColor?`, `starSize?`, `className?`
105
+
106
+ ---
107
+
108
+ ### `<ReviewCarousel>`
109
+
110
+ Auto-advancing carousel of recent reviews. Includes previous/next arrows and dot indicators.
111
+
112
+ ```tsx
113
+ import { ReviewCarousel } from '@revova/hydrogen';
114
+
115
+ <ReviewCarousel
116
+ proxyUrl="/apps/revova"
117
+ limit={10}
118
+ autoPlay
119
+ intervalMs={4000}
120
+ />
121
+ ```
122
+
123
+ **Props:** `proxyUrl`, `limit?` (default 10), `autoPlay?` (default `true`), `intervalMs?` (default 4000), `starColor?`, `className?`
124
+
125
+ ---
126
+
127
+ ### `<ReviewGallery>`
128
+
129
+ Masonry photo grid of reviews that have images. Clicking any photo opens a lightbox with the full review.
130
+
131
+ ```tsx
132
+ import { ReviewGallery } from '@revova/hydrogen';
133
+
134
+ <ReviewGallery
135
+ proxyUrl="/apps/revova"
136
+ columns={3}
137
+ limit={20}
138
+ />
139
+ ```
140
+
141
+ **Props:** `proxyUrl`, `limit?` (default 20), `columns?` (default 3), `starColor?`, `className?`
142
+
143
+ ---
144
+
145
+ ### `<QnAWidget>`
146
+
147
+ Product Q&A — lists questions with answers and includes an ask-a-question form.
148
+
149
+ ```tsx
150
+ import { QnAWidget } from '@revova/hydrogen';
151
+
152
+ <QnAWidget
153
+ proxyUrl="/apps/revova"
154
+ productId={product.id}
155
+ />
156
+ ```
157
+
158
+ **Props:** `proxyUrl`, `productId`, `className?`
159
+
160
+ ---
161
+
162
+ ### `<TrustBadge>`
163
+
164
+ Aggregate rating badge in three styles: `pill` (default), `inline`, or `card`.
165
+
166
+ ```tsx
167
+ import { TrustBadge } from '@revova/hydrogen';
168
+
169
+ // Pill — great for footers, headers
170
+ <TrustBadge proxyUrl="/apps/revova" style="pill" />
171
+
172
+ // Card — great for landing pages
173
+ <TrustBadge proxyUrl="/apps/revova" style="card" />
174
+
175
+ // Inline — great inside sentences or product specs
176
+ <TrustBadge proxyUrl="/apps/revova" style="inline" />
177
+ ```
178
+
179
+ **Props:** `proxyUrl`, `style?` (`'pill' | 'inline' | 'card'`, default `'pill'`), `starColor?`, `className?`
180
+
181
+ ---
182
+
183
+ ### `<ReviewTicker>`
184
+
185
+ A continuously scrolling marquee of recent review snippets — ideal for homepages and hero sections.
186
+
187
+ ```tsx
188
+ import { ReviewTicker } from '@revova/hydrogen';
189
+
190
+ <ReviewTicker
191
+ proxyUrl="/apps/revova"
192
+ limit={20}
193
+ speedSeconds={30}
194
+ />
195
+ ```
196
+
197
+ **Props:** `proxyUrl`, `limit?` (default 20), `speedSeconds?` (default 30), `starColor?`, `className?`
198
+
199
+ ---
200
+
201
+ ### `<SocialProofPopup>`
202
+
203
+ A timed floating popup showing recent reviews one at a time. Appears after a short delay and cycles automatically.
204
+
205
+ ```tsx
206
+ import { SocialProofPopup } from '@revova/hydrogen';
207
+
208
+ // Add once to your root layout
209
+ <SocialProofPopup
210
+ proxyUrl="/apps/revova"
211
+ position="bottom-left"
212
+ intervalMs={8000}
213
+ displayMs={5000}
214
+ />
215
+ ```
216
+
217
+ **Props:** `proxyUrl`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-left'`), `intervalMs?` (default 8000), `displayMs?` (default 5000), `starColor?`, `className?`
218
+
219
+ ---
220
+
221
+ ### `<FloatingReviewsTab>`
222
+
223
+ A sticky tab fixed to the left or right edge of the viewport. Clicking it slides out a panel of recent reviews.
224
+
225
+ ```tsx
226
+ import { FloatingReviewsTab } from '@revova/hydrogen';
227
+
228
+ <FloatingReviewsTab
229
+ proxyUrl="/apps/revova"
230
+ label="Reviews"
231
+ position="right"
232
+ color="#111827"
233
+ />
234
+ ```
235
+
236
+ **Props:** `proxyUrl`, `label?` (default `'Reviews'`), `position?` (`'left' | 'right'`, default `'right'`), `color?`, `limit?` (default 5), `starColor?`, `className?`
237
+
238
+ ---
239
+
240
+ ### `<FloatingReviewButton>`
241
+
242
+ A fixed "Write a Review" button that opens a modal with the submission form.
243
+
244
+ ```tsx
245
+ import { FloatingReviewButton } from '@revova/hydrogen';
246
+
247
+ <FloatingReviewButton
248
+ proxyUrl="/apps/revova"
249
+ productId={product.id}
250
+ text="Write a Review"
251
+ position="bottom-right"
252
+ color="#111827"
253
+ />
254
+ ```
255
+
256
+ **Props:** `proxyUrl`, `productId`, `text?` (default `'Write a Review'`), `color?`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-right'`), `className?`
257
+
258
+ ---
259
+
260
+ ## Hooks
261
+
262
+ Use hooks to build fully custom UIs while Revova handles data fetching.
263
+
264
+ ### `useReviews(options)`
265
+
266
+ Paginated reviews for a product with sorting controls.
267
+
268
+ ```tsx
269
+ import { useReviews } from '@revova/hydrogen';
270
+
271
+ const { data, loading, error, setPage, setSort, currentPage, currentSort, refetch } = useReviews({
272
+ proxyUrl: '/apps/revova',
273
+ productId: product.id,
274
+ limit: 5,
275
+ sort: 'helpful', // 'recent' | 'helpful' | 'rating_high' | 'rating_low'
276
+ locale: 'fr', // optional — returns translated content
277
+ });
278
+ ```
279
+
280
+ ### `useWidgetGlobals(options)`
281
+
282
+ Shop-level stats and recent reviews. Used internally by `<ReviewCount>`, `<TrustBadge>`, `<ReviewCarousel>`, `<ReviewGallery>`, `<ReviewTicker>`, `<SocialProofPopup>`, and `<FloatingReviewsTab>`.
283
+
284
+ ```tsx
285
+ import { useWidgetGlobals } from '@revova/hydrogen';
286
+
287
+ const { data, loading, error } = useWidgetGlobals({
288
+ proxyUrl: '/apps/revova',
289
+ limit: 20,
290
+ });
291
+
292
+ // data.stats.averageRating — "4.8"
293
+ // data.stats.totalReviews — 142
294
+ // data.reviews — recent GlobalReview[]
295
+ // data.config — merchant widget settings
296
+ ```
297
+
298
+ ### `useSubmitReview(proxyUrl)`
299
+
300
+ Submit a new review programmatically.
301
+
302
+ ```tsx
303
+ import { useSubmitReview } from '@revova/hydrogen';
304
+
305
+ const { submit, submitting, success, error, result, reset } = useSubmitReview('/apps/revova');
306
+
307
+ await submit({
308
+ productId: 'gid://shopify/Product/123',
309
+ email: 'buyer@example.com',
310
+ formId: 'form-id-from-loader',
311
+ fieldAnswers: [
312
+ { fieldId: 'star-field-id', value: 5 },
313
+ { fieldId: 'title-field-id', value: 'Great product!' },
314
+ { fieldId: 'body-field-id', value: 'Really happy with this purchase.' },
315
+ ],
316
+ });
317
+ ```
318
+
319
+ ### `useQnA(options)`
320
+
321
+ Fetch and submit Q&A for a product.
322
+
323
+ ```tsx
324
+ import { useQnA } from '@revova/hydrogen';
325
+
326
+ const {
327
+ data,
328
+ loading,
329
+ setPage,
330
+ submitQuestion,
331
+ submitAnswer,
332
+ submitState,
333
+ resetSubmit,
334
+ } = useQnA({ proxyUrl: '/apps/revova', productId: product.id });
335
+
336
+ // Submit a question
337
+ await submitQuestion({
338
+ intent: 'question',
339
+ productId: product.id,
340
+ email: 'user@example.com',
341
+ body: 'Does this come in blue?',
342
+ });
343
+ ```
344
+
345
+ ### `useHelpfulVote(proxyUrl)`
346
+
347
+ Cast a helpful / not-helpful vote on a review.
348
+
349
+ ```tsx
350
+ import { useHelpfulVote } from '@revova/hydrogen';
351
+
352
+ const { vote, loading, voted } = useHelpfulVote('/apps/revova');
353
+
354
+ <button onClick={() => vote({ reviewId: review.id, vote: 'helpful' })} disabled={voted}>
355
+ Helpful ({review.helpfulCount})
356
+ </button>
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Styling
362
+
363
+ All components are **unstyled by default** — they render semantic HTML with inline structural styles only (layout, positioning). Pass a `className` prop and override with Tailwind, CSS Modules, or any CSS-in-JS solution.
364
+
365
+ The `starColor` prop is available on every component that displays stars and defaults to `#f59e0b` (amber).
366
+
367
+ ---
368
+
369
+ ## Placement Guide
370
+
371
+ | Widget | Where to use |
372
+ |---|---|
373
+ | `<ReviewWidget>` | Product detail page |
374
+ | `<ReviewForm>` | Custom PDP, post-purchase page |
375
+ | `<StarRating>` | Anywhere — product cards, PDPs, search results |
376
+ | `<ReviewCount>` | Product cards, PDP header |
377
+ | `<ReviewCarousel>` | Homepage, collection pages |
378
+ | `<ReviewGallery>` | Homepage, dedicated reviews page |
379
+ | `<QnAWidget>` | Product detail page (below reviews) |
380
+ | `<TrustBadge>` | Homepage hero, footer, landing pages |
381
+ | `<ReviewTicker>` | Homepage hero, announcement bar |
382
+ | `<SocialProofPopup>` | Root layout (renders once site-wide) |
383
+ | `<FloatingReviewsTab>` | Root layout (renders once site-wide) |
384
+ | `<FloatingReviewButton>` | Product detail page |