diff --git a/web/src/views/motion-search/MotionSearchView.tsx b/web/src/views/motion-search/MotionSearchView.tsx
index e5cb2f4784..d2b06b6e70 100644
--- a/web/src/views/motion-search/MotionSearchView.tsx
+++ b/web/src/views/motion-search/MotionSearchView.tsx
@@ -770,6 +770,34 @@ export default function MotionSearchView({
};
}, [cancelMotionSearchJobViaBeacon]);
+ const handleBack = useCallback(() => {
+ if (onBack) {
+ onBack();
+ } else {
+ navigate(-1);
+ }
+ }, [navigate, onBack]);
+
+ // Dismissing the entry dialog (escape / click outside) before a search has
+ // run leaves nothing behind it, so cancel the flow instead of revealing an
+ // empty page.
+ const handleSearchDialogOpenChange = useCallback(
+ (nextOpen: boolean) => {
+ if (
+ !nextOpen &&
+ !isSearching &&
+ !hasSearched &&
+ searchResults.length === 0
+ ) {
+ handleBack();
+ return;
+ }
+
+ setIsSearchDialogOpen(nextOpen);
+ },
+ [handleBack, hasSearched, isSearching, searchResults.length],
+ );
+
const handleNewSearch = useCallback(() => {
if (jobId && jobCamera) {
void cancelMotionSearchJob(jobId, jobCamera);
@@ -1238,7 +1266,7 @@ export default function MotionSearchView({
(onBack ? onBack() : navigate(-1))}
+ onClick={handleBack}
>
{isDesktop && (