add tooltips

This commit is contained in:
Josh Hawkins 2025-11-08 13:01:27 -06:00
parent 3aee75ba81
commit 073dddbf24

View File

@ -37,7 +37,6 @@ import {
FaChevronLeft, FaChevronLeft,
FaChevronRight, FaChevronRight,
FaMicrophone, FaMicrophone,
FaRedo,
FaCheck, FaCheck,
FaTimes, FaTimes,
} from "react-icons/fa"; } from "react-icons/fa";
@ -92,6 +91,7 @@ import { CameraNameLabel } from "@/components/camera/FriendlyNameLabel";
import { DialogPortal } from "@radix-ui/react-dialog"; import { DialogPortal } from "@radix-ui/react-dialog";
import { useDetailStream } from "@/context/detail-stream-context"; import { useDetailStream } from "@/context/detail-stream-context";
import { PiSlidersHorizontalBold } from "react-icons/pi"; import { PiSlidersHorizontalBold } from "react-icons/pi";
import { HiSparkles } from "react-icons/hi";
const SEARCH_TABS = ["snapshot", "tracking_details"] as const; const SEARCH_TABS = ["snapshot", "tracking_details"] as const;
export type SearchTab = (typeof SEARCH_TABS)[number]; export type SearchTab = (typeof SEARCH_TABS)[number];
@ -1122,7 +1122,7 @@ function ObjectDetailsTab({
const canRegenerate = !!( const canRegenerate = !!(
config?.cameras[search.camera].objects.genai.enabled && search.end_time config?.cameras[search.camera].objects.genai.enabled && search.end_time
); );
const showAiPlaceholder = !!( const showGenAIPlaceholder = !!(
config?.cameras[search.camera].objects.genai.enabled && config?.cameras[search.camera].objects.genai.enabled &&
!search.end_time && !search.end_time &&
(config.cameras[search.camera].objects.genai.required_zones.length === 0 || (config.cameras[search.camera].objects.genai.required_zones.length === 0 ||
@ -1396,16 +1396,16 @@ function ObjectDetailsTab({
</div> </div>
)} )}
<div className="flex flex-col gap-1.5"> <div className="flex flex-col gap-1.5">
<div className="flex items-start justify-start gap-2"> <div className="flex items-center justify-start gap-3">
<div className="text-sm text-primary/40"> <div className="text-sm text-primary/40">
{t("details.description.label")} {t("details.description.label")}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-3">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<button <button
aria-label={t("button.edit", { ns: "common" })} aria-label={t("button.edit", { ns: "common" })}
className="text-primary/40 hover:text-primary" className="text-primary/40 hover:text-primary/80"
onClick={() => { onClick={() => {
originalDescRef.current = desc ?? ""; originalDescRef.current = desc ?? "";
setIsEditingDesc(true); setIsEditingDesc(true);
@ -1426,7 +1426,7 @@ function ObjectDetailsTab({
<TooltipTrigger asChild> <TooltipTrigger asChild>
<button <button
aria-label={t("itemMenu.audioTranscription.label")} aria-label={t("itemMenu.audioTranscription.label")}
className="text-primary/40 hover:text-primary" className="text-primary/40 hover:text-primary/80"
onClick={onTranscribe} onClick={onTranscribe}
> >
<FaMicrophone className="size-4" /> <FaMicrophone className="size-4" />
@ -1441,21 +1441,21 @@ function ObjectDetailsTab({
{canRegenerate && ( {canRegenerate && (
<div className="relative"> <div className="relative">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <Tooltip>
<Tooltip> <TooltipTrigger asChild>
<TooltipTrigger asChild> <DropdownMenuTrigger asChild>
<button <button
aria-label={t("details.button.regenerate.label")} aria-label={t("details.button.regenerate.label")}
className="text-primary/40 hover:text-primary" className="text-primary/40 hover:text-primary/80"
> >
<FaRedo className="size-4" /> <HiSparkles className="size-4" />
</button> </button>
</TooltipTrigger> </DropdownMenuTrigger>
<TooltipContent> </TooltipTrigger>
{t("details.button.regenerate.title")} <TooltipContent>
</TooltipContent> {t("details.button.regenerate.title")}
</Tooltip> </TooltipContent>
</DropdownMenuTrigger> </Tooltip>
<DropdownMenuContent> <DropdownMenuContent>
{search.has_snapshot && ( {search.has_snapshot && (
<DropdownMenuItem <DropdownMenuItem
@ -1481,7 +1481,7 @@ function ObjectDetailsTab({
</div> </div>
{!isEditingDesc ? ( {!isEditingDesc ? (
showAiPlaceholder ? ( showGenAIPlaceholder ? (
<div className="flex h-32 flex-col items-center justify-center gap-3 border p-4 text-sm text-primary/40"> <div className="flex h-32 flex-col items-center justify-center gap-3 border p-4 text-sm text-primary/40">
<div className="flex"> <div className="flex">
<ActivityIndicator /> <ActivityIndicator />
@ -1504,27 +1504,42 @@ function ObjectDetailsTab({
onBlur={handleDescriptionBlur} onBlur={handleDescriptionBlur}
autoFocus autoFocus
/> />
<div className="flex flex-row justify-end gap-2"> <div className="flex flex-row justify-end gap-4">
<button <Tooltip>
aria-label={t("button.save", { ns: "common" })} <TooltipTrigger asChild>
className="text-primary/40 hover:text-primary" <button
onClick={() => { aria-label={t("button.save", { ns: "common" })}
setIsEditingDesc(false); className="text-primary/40 hover:text-primary/80"
updateDescription(); onClick={() => {
}} setIsEditingDesc(false);
> updateDescription();
<FaCheck className="size-4" /> }}
</button> >
<button <FaCheck className="size-4" />
aria-label={t("button.cancel", { ns: "common" })} </button>
className="text-primary/40 hover:text-primary" </TooltipTrigger>
onClick={() => { <TooltipContent>
setIsEditingDesc(false); {t("button.save", { ns: "common" })}
setDesc(originalDescRef.current ?? ""); </TooltipContent>
}} </Tooltip>
>
<FaTimes className="size-4" /> <Tooltip>
</button> <TooltipTrigger asChild>
<button
aria-label={t("button.cancel", { ns: "common" })}
className="text-primary/40 hover:text-primary"
onClick={() => {
setIsEditingDesc(false);
setDesc(originalDescRef.current ?? "");
}}
>
<FaTimes className="size-4" />
</button>
</TooltipTrigger>
<TooltipContent>
{t("button.cancel", { ns: "common" })}
</TooltipContent>
</Tooltip>
</div> </div>
</div> </div>
)} )}