@handled-ai/design-system 0.18.2 → 0.18.4
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/dist/components/feedback-primitives.d.ts +21 -1
- package/dist/components/feedback-primitives.js +167 -16
- package/dist/components/feedback-primitives.js.map +1 -1
- package/dist/components/signal-priority-popover.js +12 -151
- package/dist/components/signal-priority-popover.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/__tests__/wit-636-feedback-states.test.tsx +2 -2
- package/src/components/feedback-primitives.tsx +200 -15
- package/src/components/signal-priority-popover.tsx +7 -158
- package/src/index.ts +2 -2
|
@@ -17,13 +17,9 @@ import {
|
|
|
17
17
|
ChevronDown,
|
|
18
18
|
ChevronUp,
|
|
19
19
|
Info,
|
|
20
|
-
ThumbsUp,
|
|
21
|
-
ThumbsDown,
|
|
22
|
-
Check,
|
|
23
|
-
Pencil,
|
|
24
20
|
} from "lucide-react"
|
|
25
21
|
import { cn } from "../lib/utils"
|
|
26
|
-
import { FeedbackFooter } from "./feedback-primitives"
|
|
22
|
+
import { FeedbackFooter, InlineFeedbackControl } from "./feedback-primitives"
|
|
27
23
|
import type { FeedbackChipTree, FeedbackSubmitData, PersistedFeedbackData } from "./feedback-primitives"
|
|
28
24
|
import type { SignalScoreUrgencyLabel } from "../prototype/prototype-config"
|
|
29
25
|
import { getSignalScoreUrgencyLabel, scoreRangeForUrgency, SIGNAL_TONE_CLASSES } from "./score-why-chips"
|
|
@@ -179,50 +175,6 @@ function PriorityFactorRow({ factor, initialFeedback, onFactorFeedback }: Priori
|
|
|
179
175
|
? "Lowers"
|
|
180
176
|
: "Neutral"
|
|
181
177
|
|
|
182
|
-
const [thumbState, setThumbState] = React.useState<"up" | "down" | null>(
|
|
183
|
-
initialFeedback?.type ?? null,
|
|
184
|
-
)
|
|
185
|
-
const [showInput, setShowInput] = React.useState(false)
|
|
186
|
-
const [detailText, setDetailText] = React.useState(initialFeedback?.detail ?? "")
|
|
187
|
-
const [saved, setSaved] = React.useState(!!initialFeedback)
|
|
188
|
-
const [savedDetail, setSavedDetail] = React.useState(initialFeedback?.detail ?? "")
|
|
189
|
-
const ownershipLabel = initialFeedback?.ownershipLabel ?? "Your feedback"
|
|
190
|
-
|
|
191
|
-
// Sync with initialFeedback prop changes
|
|
192
|
-
React.useEffect(() => {
|
|
193
|
-
if (initialFeedback) {
|
|
194
|
-
setThumbState(initialFeedback.type)
|
|
195
|
-
setSaved(true)
|
|
196
|
-
setSavedDetail(initialFeedback.detail)
|
|
197
|
-
}
|
|
198
|
-
}, [initialFeedback])
|
|
199
|
-
|
|
200
|
-
const handleThumbClick = React.useCallback(
|
|
201
|
-
(type: "up" | "down") => {
|
|
202
|
-
if (thumbState === type) {
|
|
203
|
-
// Toggle off
|
|
204
|
-
setThumbState(null)
|
|
205
|
-
setShowInput(false)
|
|
206
|
-
setSaved(false)
|
|
207
|
-
onFactorFeedback?.(factor.key, null)
|
|
208
|
-
} else {
|
|
209
|
-
setThumbState(type)
|
|
210
|
-
setShowInput(true)
|
|
211
|
-
setSaved(false)
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
[thumbState, factor.key, onFactorFeedback],
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
const handleSubmitDetail = React.useCallback(() => {
|
|
218
|
-
if (!thumbState) return
|
|
219
|
-
const text = detailText.trim()
|
|
220
|
-
onFactorFeedback?.(factor.key, thumbState, text)
|
|
221
|
-
setSaved(true)
|
|
222
|
-
setSavedDetail(text)
|
|
223
|
-
setShowInput(false)
|
|
224
|
-
}, [thumbState, detailText, factor.key, onFactorFeedback])
|
|
225
|
-
|
|
226
178
|
return (
|
|
227
179
|
<div
|
|
228
180
|
className="grid grid-cols-[20px_1fr_auto] gap-x-3 gap-y-1 px-4 py-3"
|
|
@@ -290,115 +242,12 @@ function PriorityFactorRow({ factor, initialFeedback, onFactorFeedback }: Priori
|
|
|
290
242
|
<>
|
|
291
243
|
<div />
|
|
292
244
|
<div className="col-span-2 mt-1">
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
setShowInput(true)
|
|
300
|
-
setSaved(false)
|
|
301
|
-
}}
|
|
302
|
-
className="group flex items-center gap-1.5 text-[11px] text-muted-foreground hover:text-foreground transition-colors"
|
|
303
|
-
data-testid={`factor-feedback-persisted-${factor.key}`}
|
|
304
|
-
>
|
|
305
|
-
<span className="font-medium">{ownershipLabel}:</span>
|
|
306
|
-
{thumbState === "up" ? (
|
|
307
|
-
<ThumbsUp className="h-[10px] w-[10px]" />
|
|
308
|
-
) : (
|
|
309
|
-
<ThumbsDown className="h-[10px] w-[10px]" />
|
|
310
|
-
)}
|
|
311
|
-
{savedDetail && (
|
|
312
|
-
<span className="max-w-[180px] truncate text-muted-foreground/70">
|
|
313
|
-
{savedDetail}
|
|
314
|
-
</span>
|
|
315
|
-
)}
|
|
316
|
-
<Pencil className="h-[9px] w-[9px] opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
317
|
-
</button>
|
|
318
|
-
) : (
|
|
319
|
-
<div className="flex items-center gap-1.5">
|
|
320
|
-
{/* Inline thumb buttons */}
|
|
321
|
-
<button
|
|
322
|
-
type="button"
|
|
323
|
-
onClick={() => handleThumbClick("up")}
|
|
324
|
-
className={cn(
|
|
325
|
-
"p-1 rounded transition-colors",
|
|
326
|
-
thumbState === "up"
|
|
327
|
-
? "text-foreground bg-muted"
|
|
328
|
-
: "text-muted-foreground/40 hover:text-foreground hover:bg-muted/50",
|
|
329
|
-
)}
|
|
330
|
-
title="This factor is accurate"
|
|
331
|
-
data-testid={`factor-thumb-up-${factor.key}`}
|
|
332
|
-
>
|
|
333
|
-
<ThumbsUp className="h-[10px] w-[10px]" />
|
|
334
|
-
</button>
|
|
335
|
-
<button
|
|
336
|
-
type="button"
|
|
337
|
-
onClick={() => handleThumbClick("down")}
|
|
338
|
-
className={cn(
|
|
339
|
-
"p-1 rounded transition-colors",
|
|
340
|
-
thumbState === "down"
|
|
341
|
-
? "text-red-600 bg-red-50"
|
|
342
|
-
: "text-muted-foreground/40 hover:text-red-600 hover:bg-red-50/50",
|
|
343
|
-
)}
|
|
344
|
-
title="Report issue with this factor"
|
|
345
|
-
data-testid={`factor-thumb-down-${factor.key}`}
|
|
346
|
-
>
|
|
347
|
-
<ThumbsDown className="h-[10px] w-[10px]" />
|
|
348
|
-
</button>
|
|
349
|
-
|
|
350
|
-
{/* Transient "Saved" pill */}
|
|
351
|
-
{saved && (
|
|
352
|
-
<span
|
|
353
|
-
className="inline-flex items-center gap-1 text-[11px] font-medium text-emerald-600"
|
|
354
|
-
role="status"
|
|
355
|
-
data-testid={`factor-saved-${factor.key}`}
|
|
356
|
-
>
|
|
357
|
-
<Check className="h-[10px] w-[10px]" />
|
|
358
|
-
Saved
|
|
359
|
-
</span>
|
|
360
|
-
)}
|
|
361
|
-
</div>
|
|
362
|
-
)}
|
|
363
|
-
|
|
364
|
-
{/* Inline detail input */}
|
|
365
|
-
{showInput && thumbState && (
|
|
366
|
-
<div className="mt-1.5">
|
|
367
|
-
<input
|
|
368
|
-
type="text"
|
|
369
|
-
value={detailText}
|
|
370
|
-
onChange={(e) => setDetailText(e.target.value)}
|
|
371
|
-
onKeyDown={(e) => {
|
|
372
|
-
if (e.key === "Enter") handleSubmitDetail()
|
|
373
|
-
if (e.key === "Escape") setShowInput(false)
|
|
374
|
-
}}
|
|
375
|
-
placeholder={
|
|
376
|
-
thumbState === "up"
|
|
377
|
-
? "What\u2019s accurate? (optional)"
|
|
378
|
-
: "What\u2019s wrong? (optional)"
|
|
379
|
-
}
|
|
380
|
-
className="w-full h-6 rounded border border-border bg-background px-2 text-[11px] text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:ring-1 focus:ring-ring"
|
|
381
|
-
data-testid={`factor-detail-input-${factor.key}`}
|
|
382
|
-
/>
|
|
383
|
-
<div className="mt-1 flex items-center gap-1.5">
|
|
384
|
-
<button
|
|
385
|
-
type="button"
|
|
386
|
-
onClick={handleSubmitDetail}
|
|
387
|
-
className="bg-foreground text-background rounded px-2 py-0.5 text-[10px] font-semibold"
|
|
388
|
-
data-testid={`factor-submit-${factor.key}`}
|
|
389
|
-
>
|
|
390
|
-
Submit
|
|
391
|
-
</button>
|
|
392
|
-
<button
|
|
393
|
-
type="button"
|
|
394
|
-
onClick={() => setShowInput(false)}
|
|
395
|
-
className="border border-border rounded px-2 py-0.5 text-[10px] font-medium"
|
|
396
|
-
>
|
|
397
|
-
Cancel
|
|
398
|
-
</button>
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
)}
|
|
245
|
+
<InlineFeedbackControl
|
|
246
|
+
feedbackKey={factor.key}
|
|
247
|
+
initialFeedback={initialFeedback}
|
|
248
|
+
onFeedback={onFactorFeedback}
|
|
249
|
+
testIdPrefix="factor"
|
|
250
|
+
/>
|
|
402
251
|
</div>
|
|
403
252
|
</>
|
|
404
253
|
)}
|
package/src/index.ts
CHANGED
|
@@ -37,8 +37,8 @@ export * from "./components/dialog"
|
|
|
37
37
|
export * from "./components/dropdown-menu"
|
|
38
38
|
export * from "./components/empty-state"
|
|
39
39
|
export * from "./components/entity-panel"
|
|
40
|
-
export { FeedbackFooter, FeedbackChipGroup, FeedbackInput, FeedbackActions } from "./components/feedback-primitives"
|
|
41
|
-
export type { FeedbackFooterProps, FeedbackChipTree, FeedbackChipGroupProps, FeedbackInputProps, FeedbackActionsProps, FeedbackSubmitData, PersistedFeedbackData } from "./components/feedback-primitives"
|
|
40
|
+
export { FeedbackFooter, FeedbackChipGroup, FeedbackInput, FeedbackActions, InlineFeedbackControl } from "./components/feedback-primitives"
|
|
41
|
+
export type { FeedbackFooterProps, FeedbackChipTree, FeedbackChipGroupProps, FeedbackInputProps, FeedbackActionsProps, FeedbackSubmitData, PersistedFeedbackData, InlineFeedbackControlProps } from "./components/feedback-primitives"
|
|
42
42
|
export { SignalPriorityPopover } from "./components/signal-priority-popover"
|
|
43
43
|
export type { SignalPriorityPopoverProps, PriorityFactor } from "./components/signal-priority-popover"
|
|
44
44
|
export * from "./components/filter-chip"
|