Skip to content

Commit 9246c4e

Browse files
committed
Add hints to tags for copying and opening links
1 parent 9f19f5e commit 9246c4e

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

src/components/result/GenericResultView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ export function GenericResultView({
355355
>
356356
<span className="rfs-text-sm rfs-text-muted-foreground">{pid}</span>
357357
</a>
358-
<div className="rfs-flex rfs-flex-wrap rfs-gap-2 rfs-truncate">
358+
<div className="rfs-flex rfs-flex-wrap rfs-gap-2 rfs-truncate rfs-items-center">
359359
{tags && tags.map((tag, i) => <GenericResultViewTag key={i} result={result} {...tag} />)}
360360
</div>
361361
<div className="rfs-grow">{description}</div>

src/components/result/GenericResultViewTag.tsx

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { MouseEvent, ReactNode, useCallback, useMemo } from "react"
1+
import { MouseEvent, ReactNode, useCallback, useEffect, useMemo, useState } from "react"
22
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
33
import { Badge } from "@/components/ui/badge"
44
import { SearchResult } from "@elastic/search-ui"
55
import { autoUnwrap } from "@/components/result/utils"
66
import { useCopyToClipboard } from "usehooks-ts"
7+
import { CheckIcon } from "lucide-react"
78

89
export interface GenericResultViewTagProps {
910
/**
@@ -32,7 +33,7 @@ export interface GenericResultViewTagProps {
3233
*/
3334
singleValueMapper?: (value: string) => ReactNode
3435
onClick?: (e: MouseEvent<HTMLDivElement>, tagValue: ReactNode, fieldValue: string | string[]) => void
35-
clickBehavior?: "copy-text" | "follow-url"
36+
clickBehavior?: "copy-text" | "follow-url" | string
3637
}
3738

3839
export function GenericResultViewTag({
@@ -45,6 +46,16 @@ export function GenericResultViewTag({
4546
clickBehavior = "copy-text",
4647
onClick
4748
}: GenericResultViewTagProps) {
49+
const [showCopiedNotice, setShowCopiedNotice] = useState(false)
50+
51+
useEffect(() => {
52+
if (showCopiedNotice) {
53+
setTimeout(() => {
54+
setShowCopiedNotice(false)
55+
}, 1000)
56+
}
57+
}, [showCopiedNotice])
58+
4859
const fieldValue = useMemo(() => {
4960
return autoUnwrap(result[field]) as string | string[]
5061
}, [field, result])
@@ -70,26 +81,44 @@ export function GenericResultViewTag({
7081
const handleClick = useCallback(
7182
(fieldValue: string | string[], value: ReactNode, e: MouseEvent<HTMLDivElement>) => {
7283
if (onClick) onClick(e, value, fieldValue)
73-
if (clickBehavior === "copy-text") {
84+
if (clickBehavior === "copy-text" && !showCopiedNotice) {
7485
copyTagValue(e)
86+
setShowCopiedNotice(true)
7587
} else if (clickBehavior === "follow-url" && !Array.isArray(fieldValue)) {
7688
window.open(fieldValue, "_blank")
7789
}
7890
},
79-
[clickBehavior, copyTagValue, onClick]
91+
[clickBehavior, copyTagValue, onClick, showCopiedNotice]
8092
)
8193

94+
const clickBehaviourText = useMemo(() => {
95+
if (onClick) return null // We don't know what will happen on click...
96+
if (clickBehavior === "copy-text") {
97+
return "Click to copy"
98+
} else if (clickBehavior === "follow-url") {
99+
return "Click to open"
100+
} else return null
101+
}, [clickBehavior, onClick])
102+
82103
const base = useCallback(
83104
(fieldValue: string | string[], value: ReactNode, key?: string) => {
84105
return (
85106
<Badge key={key} variant="secondary" className="rfs-truncate" onClick={(e) => handleClick(fieldValue, value, e)}>
86107
<span className="rfs-flex rfs-truncate">
87-
{icon} {value}
108+
{showCopiedNotice ? (
109+
<>
110+
<CheckIcon className="rfs-size-4 rfs-mr-2" /> <span>Copied</span>
111+
</>
112+
) : (
113+
<>
114+
{icon} {value}
115+
</>
116+
)}
88117
</span>
89118
</Badge>
90119
)
91120
},
92-
[handleClick, icon]
121+
[handleClick, icon, showCopiedNotice]
93122
)
94123

95124
if (!label) return Array.isArray(value) ? value.map((v, i) => base(fieldValue[value.indexOf(v)], v, field + i)) : base(fieldValue, value)
@@ -99,15 +128,21 @@ export function GenericResultViewTag({
99128
return value.map((entry, i) => (
100129
<Tooltip delayDuration={500} key={field + i}>
101130
<TooltipTrigger>{base(fieldValue[value.indexOf(entry)], entry)}</TooltipTrigger>
102-
<TooltipContent>{label}</TooltipContent>
131+
<TooltipContent>
132+
<div>{label}</div>
133+
<div className="rfs-text-xs rfs-text-muted-foreground">{clickBehaviourText}</div>
134+
</TooltipContent>
103135
</Tooltip>
104136
))
105137
}
106138

107139
return (
108140
<Tooltip delayDuration={500}>
109141
<TooltipTrigger>{base(fieldValue, value)}</TooltipTrigger>
110-
<TooltipContent>{label}</TooltipContent>
142+
<TooltipContent>
143+
<div>{label}</div>
144+
<div className="rfs-text-xs rfs-text-muted-foreground">{clickBehaviourText}</div>
145+
</TooltipContent>
111146
</Tooltip>
112147
)
113148
}

0 commit comments

Comments
 (0)