@kelet-ai/feedback-ui 0.3.0 → 0.4.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 +36 -19
- package/dist/components/vote-feedback.d.ts +1 -1
- package/dist/feedback-ui.es.js +822 -798
- package/dist/feedback-ui.umd.js +16 -16
- package/dist/hooks/feedback-state/use-feedback-reducer.d.ts +4 -4
- package/dist/hooks/feedback-state/use-feedback-state.d.ts +5 -5
- package/dist/hooks/feedback-state/use-state-change-tracking.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/lib/otel-trace.d.ts +22 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +9 -2
- package/dist/lib/utils.d.ts +0 -2
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ import { ShadcnVoteFeedback } from '@/components/ui/vote-feedback';
|
|
|
28
28
|
function App() {
|
|
29
29
|
return (
|
|
30
30
|
<ShadcnVoteFeedback
|
|
31
|
-
|
|
31
|
+
tx_id="my-feature"
|
|
32
32
|
onFeedback={feedback => console.log(feedback)}
|
|
33
33
|
variant="outline"
|
|
34
34
|
/>
|
|
@@ -91,7 +91,7 @@ Users explicitly vote and provide comments:
|
|
|
91
91
|
```tsx
|
|
92
92
|
import { VoteFeedback } from '@kelet-ai/feedback-ui';
|
|
93
93
|
|
|
94
|
-
<VoteFeedback.Root onFeedback={handleFeedback}
|
|
94
|
+
<VoteFeedback.Root onFeedback={handleFeedback} tx_id="ai-response">
|
|
95
95
|
<VoteFeedback.UpvoteButton>👍 Helpful</VoteFeedback.UpvoteButton>
|
|
96
96
|
<VoteFeedback.DownvoteButton>👎 Not helpful</VoteFeedback.DownvoteButton>
|
|
97
97
|
<VoteFeedback.Popover>
|
|
@@ -158,14 +158,14 @@ Understanding these fundamental concepts will help you implement feedback collec
|
|
|
158
158
|
**Best Practice**: Use traceable IDs from your logging system (session ID, trace ID, request ID)
|
|
159
159
|
|
|
160
160
|
```tsx
|
|
161
|
-
// ✅ Good: Traceable
|
|
162
|
-
<VoteFeedback.Root
|
|
161
|
+
// ✅ Good: Traceable tx_id
|
|
162
|
+
<VoteFeedback.Root tx_id="session-abc123-ai-response-456"/>
|
|
163
163
|
|
|
164
|
-
// ✅ Good: Content-based
|
|
165
|
-
<VoteFeedback.Root
|
|
164
|
+
// ✅ Good: Content-based tx_id
|
|
165
|
+
<VoteFeedback.Root tx_id={`article-${articleId}-section-${sectionId}`}/>
|
|
166
166
|
|
|
167
|
-
// ❌ Poor: Generic
|
|
168
|
-
<VoteFeedback.Root
|
|
167
|
+
// ❌ Poor: Generic tx_id
|
|
168
|
+
<VoteFeedback.Root tx_id="feedback"/>
|
|
169
169
|
```
|
|
170
170
|
|
|
171
171
|
### **📊 Feedback Sources**
|
|
@@ -290,8 +290,8 @@ const [data, setData] = useFeedbackState(initial, 'tracker', {
|
|
|
290
290
|
#### **Identifiers**
|
|
291
291
|
|
|
292
292
|
✅ Use traceable session/request IDs
|
|
293
|
-
✅ Include context in
|
|
294
|
-
✅ Keep
|
|
293
|
+
✅ Include context in tx_id structure
|
|
294
|
+
✅ Keep tx_ids consistent across related actions
|
|
295
295
|
|
|
296
296
|
#### **Feedback Sources**
|
|
297
297
|
|
|
@@ -313,6 +313,23 @@ const [data, setData] = useFeedbackState(initial, 'tracker', {
|
|
|
313
313
|
|
|
314
314
|
---
|
|
315
315
|
|
|
316
|
+
## 🔗 OpenTelemetry Integration
|
|
317
|
+
|
|
318
|
+
Automatically extract trace IDs to correlate feedback with distributed traces:
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
import { VoteFeedback, getOtelTraceId } from '@kelet-ai/feedback-ui';
|
|
322
|
+
|
|
323
|
+
<VoteFeedback.Root tx_id={getOtelTraceId} onFeedback={handleFeedback}>
|
|
324
|
+
<VoteFeedback.UpvoteButton>👍</VoteFeedback.UpvoteButton>
|
|
325
|
+
<VoteFeedback.DownvoteButton>👎</VoteFeedback.DownvoteButton>
|
|
326
|
+
</VoteFeedback.Root>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Requires `@opentelemetry/api` and active Span to collect the trace_id from.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
316
333
|
## 🔧 Core Components
|
|
317
334
|
|
|
318
335
|
### **VoteFeedback.Root**
|
|
@@ -321,7 +338,7 @@ Main container component that manages feedback state.
|
|
|
321
338
|
|
|
322
339
|
```tsx
|
|
323
340
|
<VoteFeedback.Root
|
|
324
|
-
|
|
341
|
+
tx_id="unique-id" // Required: Unique tracking ID
|
|
325
342
|
onFeedback={handleFeedback} // Required: Callback function
|
|
326
343
|
trigger_name="user_feedback" // Optional: Categorization
|
|
327
344
|
extra_metadata={{ page: 'home' }} // Optional: Additional data
|
|
@@ -370,7 +387,7 @@ const [count, setCount] = useFeedbackState(0, 'counter-widget');
|
|
|
370
387
|
```tsx
|
|
371
388
|
const [profile, setProfile] = useFeedbackState(
|
|
372
389
|
{ name: '', email: '' },
|
|
373
|
-
state => `profile-${state.email}`, // Dynamic
|
|
390
|
+
state => `profile-${state.email}`, // Dynamic tx_id
|
|
374
391
|
{
|
|
375
392
|
debounceMs: 2000, // Wait time before sending feedback
|
|
376
393
|
diffType: 'object', // Format: 'git' | 'object' | 'json'
|
|
@@ -460,7 +477,7 @@ dispatch({ type: 'custom' }, 'override'); // Custom trigger name
|
|
|
460
477
|
|
|
461
478
|
```tsx
|
|
462
479
|
<VoteFeedback.Root
|
|
463
|
-
|
|
480
|
+
tx_id="ai-response-123"
|
|
464
481
|
onFeedback={handleFeedback}
|
|
465
482
|
trigger_name="ai_evaluation"
|
|
466
483
|
extra_metadata={{
|
|
@@ -486,7 +503,7 @@ dispatch({ type: 'custom' }, 'override'); // Custom trigger name
|
|
|
486
503
|
|
|
487
504
|
```typescript
|
|
488
505
|
interface FeedbackData {
|
|
489
|
-
|
|
506
|
+
tx_id: string; // Unique tracking ID
|
|
490
507
|
vote: 'upvote' | 'downvote'; // User's vote
|
|
491
508
|
explanation?: string; // Optional user comment
|
|
492
509
|
extra_metadata?: Record<string, any>; // Additional context data
|
|
@@ -501,7 +518,7 @@ interface FeedbackData {
|
|
|
501
518
|
|
|
502
519
|
| Prop | Type | Required | Description |
|
|
503
520
|
| ---------------- | ------------------------------ | -------- | ----------------------------------- |
|
|
504
|
-
| `
|
|
521
|
+
| `tx_id` | `string` | ✅ | Unique transaction ID for tracking |
|
|
505
522
|
| `onFeedback` | `(data: FeedbackData) => void` | ✅ | Callback when feedback is submitted |
|
|
506
523
|
| `trigger_name` | `string` | ❌ | Optional categorization tag |
|
|
507
524
|
| `extra_metadata` | `object` | ❌ | Additional context data |
|
|
@@ -586,9 +603,9 @@ bun run checks # Run all quality checks (lint, format, typecheck, tests)
|
|
|
586
603
|
<VoteFeedback.UpvoteButton>👍</VoteFeedback.UpvoteButton>
|
|
587
604
|
</VoteFeedback.Root>
|
|
588
605
|
|
|
589
|
-
// ✅ Include required
|
|
606
|
+
// ✅ Include required tx_id and onFeedback
|
|
590
607
|
<VoteFeedback.Root
|
|
591
|
-
|
|
608
|
+
tx_id="my-feature"
|
|
592
609
|
onFeedback={handleFeedback}
|
|
593
610
|
>
|
|
594
611
|
<VoteFeedback.UpvoteButton>👍</VoteFeedback.UpvoteButton>
|
|
@@ -624,14 +641,14 @@ const [value, setValue] = useFeedbackState('initial', 'test', {
|
|
|
624
641
|
|
|
625
642
|
### **Best Practices**
|
|
626
643
|
|
|
627
|
-
✅ **Use unique
|
|
644
|
+
✅ **Use unique tx_ids** for each feedback instance - the tx_id should be traceable back to the session's log
|
|
628
645
|
and allow us to understand the context of the feedback.
|
|
629
646
|
✅ **Handle feedback data asynchronously** in your callback
|
|
630
647
|
✅ **Test keyboard navigation** in your implementation
|
|
631
648
|
✅ **Provide meaningful trigger names** for categorization
|
|
632
649
|
✅ **Include relevant metadata** for context
|
|
633
650
|
|
|
634
|
-
❌ **Don't use the same
|
|
651
|
+
❌ **Don't use the same tx_id** for multiple components. A tx_id should be traced back to the session's log -
|
|
635
652
|
allows us to understand the context of the feedback.
|
|
636
653
|
|
|
637
654
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DownvoteButtonProps, PopoverProps, SubmitButtonProps, TextareaProps, UpvoteButtonProps, VoteFeedbackRootProps } from '../types';
|
|
2
2
|
export declare const VoteFeedback: {
|
|
3
|
-
Root: ({ children, onFeedback, defaultText,
|
|
3
|
+
Root: ({ children, onFeedback, defaultText, tx_id: txIdProp, extra_metadata, trigger_name, }: VoteFeedbackRootProps) => import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
UpvoteButton: ({ asChild, children, onClick, ...props }: UpvoteButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
DownvoteButton: ({ asChild, children, onClick, ...props }: DownvoteButtonProps) => string | number | bigint | true | Iterable<import('react').ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<import('react').ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
Popover: ({ asChild, children, ...props }: PopoverProps) => import("react/jsx-runtime").JSX.Element | null;
|