From 6a011df4274b43a21512b8ab8d123e7e33e69f86 Mon Sep 17 00:00:00 2001
From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
Date: Wed, 5 Nov 2025 22:33:37 -0600
Subject: [PATCH] fix popover
---
.../overlay/detail/SearchDetailDialog.tsx | 120 +++++++++++-------
1 file changed, 76 insertions(+), 44 deletions(-)
diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx
index d3d0b8e5c..67f2259c6 100644
--- a/web/src/components/overlay/detail/SearchDetailDialog.tsx
+++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx
@@ -88,8 +88,8 @@ type TabsWithActionsProps = {
config?: FrigateConfig;
setSearch: (s: SearchResult | undefined) => void;
setSimilarity?: () => void;
- showControls?: boolean;
- setShowControls?: (v: boolean) => void;
+ isPopoverOpen: boolean;
+ setIsPopoverOpen: (open: boolean) => void;
};
function TabsWithActions({
@@ -100,8 +100,8 @@ function TabsWithActions({
config,
setSearch,
setSimilarity,
- showControls,
- setShowControls,
+ isPopoverOpen,
+ setIsPopoverOpen,
}: TabsWithActionsProps) {
const { t } = useTranslation(["views/explore", "views/faceLibrary"]);
@@ -152,8 +152,8 @@ function TabsWithActions({
{pageToggle === "tracking_details" && (
)}
@@ -162,40 +162,69 @@ function TabsWithActions({
type AnnotationSettingsPopoverProps = {
search: SearchResult;
- showControls?: boolean;
- setShowControls?: (v: boolean) => void;
+ open: boolean;
+ setIsOpen: (open: boolean) => void;
};
function AnnotationSettingsPopover({
search,
- showControls,
- setShowControls,
+ open,
+ setIsOpen,
}: AnnotationSettingsPopoverProps) {
const { t } = useTranslation(["views/explore"]);
const { annotationOffset, setAnnotationOffset } = useDetailStream();
const [showZones, setShowZones] = useState(true);
+ const ignoreNextOpenRef = useRef(false);
+
+ useEffect(() => {
+ setIsOpen(false);
+ ignoreNextOpenRef.current = false;
+ }, [search, setIsOpen]);
+
+ const handleOpenChange = useCallback(
+ (nextOpen: boolean) => {
+ if (nextOpen) {
+ if (ignoreNextOpenRef.current) {
+ ignoreNextOpenRef.current = false;
+ return;
+ }
+ setIsOpen(true);
+ } else {
+ setIsOpen(false);
+ }
+ },
+ [setIsOpen],
+ );
+
+ const registerTriggerCloseIntent = useCallback(() => {
+ if (open) {
+ ignoreNextOpenRef.current = true;
+ }
+ }, [open]);
+
return (
-
-
-
-
-
-
-
-
-
- {t("trackingDetails.adjustAnnotationSettings")}
-
-
-
+
+ {
+ if (open && (event.key === "Enter" || event.key === " ")) {
+ registerTriggerCloseIntent();
+ }
+ }}
+ >
+
+
void;
setInputFocused: React.Dispatch>;
setSimilarity?: () => void;
- showControls?: boolean;
- setShowControls?: (v: boolean) => void;
+ isPopoverOpen: boolean;
+ setIsPopoverOpen: (open: boolean) => void;
};
function DialogContentComponent({
@@ -245,8 +274,8 @@ function DialogContentComponent({
setSearch,
setInputFocused,
setSimilarity,
- showControls,
- setShowControls,
+ isPopoverOpen,
+ setIsPopoverOpen,
}: DialogContentComponentProps) {
if (page === "tracking_details") {
return (
@@ -263,8 +292,8 @@ function DialogContentComponent({
config={config}
setSearch={setSearch}
setSimilarity={setSimilarity}
- showControls={showControls}
- setShowControls={setShowControls}
+ isPopoverOpen={isPopoverOpen}
+ setIsPopoverOpen={setIsPopoverOpen}
/>
) : undefined
}
@@ -321,8 +350,8 @@ function DialogContentComponent({
config={config}
setSearch={setSearch}
setSimilarity={setSimilarity}
- showControls={showControls}
- setShowControls={setShowControls}
+ isPopoverOpen={isPopoverOpen}
+ setIsPopoverOpen={setIsPopoverOpen}
/>
{
+ setIsPopoverOpen(open);
setIsOpen(open);
if (!open) {
// short timeout to allow the mobile page animation
@@ -410,9 +441,7 @@ export default function SearchDetailDialog({
}
}, [search]);
- // show/hide annotation settings
-
- const [showControls, setShowControls] = useState(false);
+ // show/hide annotation settings is handled inside TabsWithActions
const searchTabs = useMemo(() => {
if (!config || !search) {
@@ -521,6 +550,9 @@ export default function SearchDetailDialog({
isMobile && "px-4",
)}
onInteractOutside={(e) => {
+ if (isPopoverOpen) {
+ e.preventDefault();
+ }
const target = e.target as HTMLElement;
if (target.closest(".nav-button")) {
e.preventDefault();
@@ -545,8 +577,8 @@ export default function SearchDetailDialog({
config={config}
setSearch={setSearch}
setSimilarity={setSimilarity}
- showControls={showControls}
- setShowControls={setShowControls}
+ isPopoverOpen={isPopoverOpen}
+ setIsPopoverOpen={setIsPopoverOpen}
/>
)}
@@ -563,8 +595,8 @@ export default function SearchDetailDialog({
setSearch={setSearch}
setInputFocused={setInputFocused}
setSimilarity={setSimilarity}
- showControls={showControls}
- setShowControls={setShowControls}
+ isPopoverOpen={isPopoverOpen}
+ setIsPopoverOpen={setIsPopoverOpen}
/>