diff --git a/web/public/locales/en/views/chat.json b/web/public/locales/en/views/chat.json index 13498e6329..a2fc7ed799 100644 --- a/web/public/locales/en/views/chat.json +++ b/web/public/locales/en/views/chat.json @@ -13,6 +13,8 @@ "arguments": "Arguments:", "response": "Response:", "attachment_chip_remove": "Remove attachment", + "open_in_explore": "Open in Explore", + "attach_event_aria": "Attach event {{eventId}}", "attachment_picker_paste_label": "Or paste event ID", "attachment_picker_attach": "Attach", "attachment_picker_placeholder": "Attach an event", diff --git a/web/src/components/chat/ChatAttachmentChip.tsx b/web/src/components/chat/ChatAttachmentChip.tsx new file mode 100644 index 0000000000..30891db429 --- /dev/null +++ b/web/src/components/chat/ChatAttachmentChip.tsx @@ -0,0 +1,90 @@ +import { useApiHost } from "@/api"; +import { useTranslation } from "react-i18next"; +import { LuX, LuExternalLink } from "react-icons/lu"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; + +type ChatAttachmentChipProps = { + eventId: string; + mode: "composer" | "bubble"; + onRemove?: () => void; +}; + +/** + * Small horizontal chip rendering an event as an "attachment": a thumbnail, + * a short label, an optional remove X (composer mode), and an external-link + * icon that opens the event in Explore. + */ +export function ChatAttachmentChip({ + eventId, + mode, + onRemove, +}: ChatAttachmentChipProps) { + const apiHost = useApiHost(); + const { t } = useTranslation(["views/chat"]); + + return ( +
+
+ { + (e.currentTarget as HTMLImageElement).style.visibility = "hidden"; + }} + /> +
+ + {eventId} + + + + e.stopPropagation()} + aria-label={t("open_in_explore")} + > + + + + {t("open_in_explore")} + + {mode === "composer" && onRemove && ( + + )} +
+ ); +}