From 893fe79d2261923730c5e78ecb73cf17bd85977e Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Mon, 27 Oct 2025 07:44:34 -0500 Subject: [PATCH] UI tweaks (#20687) * add blurred icon button component * apply component to explore, face, and classification views * apply to exports and fix bug where play button was unclickable --- web/public/locales/en/views/exports.json | 6 + .../components/button/BlurredIconButton.tsx | 28 ++++ web/src/components/card/ExportCard.tsx | 126 ++++++++++-------- .../components/menu/SearchResultActions.tsx | 41 +++--- web/src/pages/FaceLibrary.tsx | 20 ++- .../classification/ModelTrainingView.tsx | 15 +-- 6 files changed, 142 insertions(+), 94 deletions(-) create mode 100644 web/src/components/button/BlurredIconButton.tsx diff --git a/web/public/locales/en/views/exports.json b/web/public/locales/en/views/exports.json index 729899443..4a79d20e1 100644 --- a/web/public/locales/en/views/exports.json +++ b/web/public/locales/en/views/exports.json @@ -9,6 +9,12 @@ "desc": "Enter a new name for this export.", "saveExport": "Save Export" }, + "tooltip": { + "shareExport": "Share export", + "downloadVideo": "Download video", + "editName": "Edit name", + "deleteExport": "Delete export" + }, "toast": { "error": { "renameExportFailed": "Failed to rename export: {{errorMessage}}" diff --git a/web/src/components/button/BlurredIconButton.tsx b/web/src/components/button/BlurredIconButton.tsx new file mode 100644 index 000000000..8fe17f869 --- /dev/null +++ b/web/src/components/button/BlurredIconButton.tsx @@ -0,0 +1,28 @@ +import React, { forwardRef } from "react"; +import { cn } from "@/lib/utils"; + +type BlurredIconButtonProps = React.HTMLAttributes; + +const BlurredIconButton = forwardRef( + ({ className = "", children, ...rest }, ref) => { + return ( +
+
+
+ {children} +
+
+ ); + }, +); + +BlurredIconButton.displayName = "BlurredIconButton"; + +export default BlurredIconButton; diff --git a/web/src/components/card/ExportCard.tsx b/web/src/components/card/ExportCard.tsx index d57a30b52..d95c6f318 100644 --- a/web/src/components/card/ExportCard.tsx +++ b/web/src/components/card/ExportCard.tsx @@ -4,7 +4,6 @@ import { Button } from "../ui/button"; import { useCallback, useState } from "react"; import { isDesktop, isMobile } from "react-device-detect"; import { FaDownload, FaPlay, FaShareAlt } from "react-icons/fa"; -import Chip from "../indicators/Chip"; import { Skeleton } from "../ui/skeleton"; import { Dialog, @@ -22,6 +21,8 @@ import { cn } from "@/lib/utils"; import { shareOrCopy } from "@/utils/browserUtil"; import { useTranslation } from "react-i18next"; import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay"; +import BlurredIconButton from "../button/BlurredIconButton"; +import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; type ExportProps = { className: string; @@ -156,56 +157,77 @@ export default function ExportCard({ )} {hovered && ( -
+ <>
-
- {!exportedRecording.in_progress && ( - - shareOrCopy( - `${baseUrl}export?id=${exportedRecording.id}`, - exportedRecording.name.replaceAll("_", " "), - ) - } - > - - - )} - {!exportedRecording.in_progress && ( - - - - - - )} - {!exportedRecording.in_progress && ( - - setEditName({ - original: exportedRecording.name, - update: undefined, - }) - } - > - - - )} - - onDelete({ - file: exportedRecording.id, - exportName: exportedRecording.name, - }) - } - > - - +
+
+ {!exportedRecording.in_progress && ( + + + + shareOrCopy( + `${baseUrl}export?id=${exportedRecording.id}`, + exportedRecording.name.replaceAll("_", " "), + ) + } + > + + + + {t("tooltip.shareExport")} + + )} + {!exportedRecording.in_progress && ( + + + + + + + + + {t("tooltip.downloadVideo")} + + + + )} + {!exportedRecording.in_progress && ( + + + + setEditName({ + original: exportedRecording.name, + update: undefined, + }) + } + > + + + + {t("tooltip.editName")} + + )} + + + + onDelete({ + file: exportedRecording.id, + exportName: exportedRecording.name, + }) + } + > + + + + {t("tooltip.deleteExport")} + +
{!exportedRecording.in_progress && ( @@ -220,13 +242,13 @@ export default function ExportCard({ )} -
+ )} {loading && ( )} -
+
{exportedRecording.name.replaceAll("_", " ")}
diff --git a/web/src/components/menu/SearchResultActions.tsx b/web/src/components/menu/SearchResultActions.tsx index 45e9a55d8..28644d3a7 100644 --- a/web/src/components/menu/SearchResultActions.tsx +++ b/web/src/components/menu/SearchResultActions.tsx @@ -42,6 +42,7 @@ import useSWR from "swr"; import { Trans, useTranslation } from "react-i18next"; import { BsFillLightningFill } from "react-icons/bs"; +import BlurredIconButton from "../button/BlurredIconButton"; type SearchResultActionsProps = { searchResult: SearchResult; @@ -213,15 +214,13 @@ export default function SearchResultActions({ {config?.semantic_search?.enabled && searchResult.data.type == "object" && ( - -
- {/* blurred circular hover background */} -
- -
+ + + + {t("itemMenu.findSimilar.label")} @@ -236,14 +235,13 @@ export default function SearchResultActions({ searchResult.data.type == "object" && !searchResult.plus_id && ( - -
-
- -
+ + + + {t("itemMenu.submitToPlus.label")} @@ -252,11 +250,10 @@ export default function SearchResultActions({ )} - -
-
- -
+ + + + {menuItems} diff --git a/web/src/pages/FaceLibrary.tsx b/web/src/pages/FaceLibrary.tsx index c01a0875a..e308727c3 100644 --- a/web/src/pages/FaceLibrary.tsx +++ b/web/src/pages/FaceLibrary.tsx @@ -5,6 +5,7 @@ import TextEntryDialog from "@/components/overlay/dialog/TextEntryDialog"; import UploadImageDialog from "@/components/overlay/dialog/UploadImageDialog"; import FaceSelectionDialog from "@/components/overlay/FaceSelectionDialog"; import { Button, buttonVariants } from "@/components/ui/button"; +import BlurredIconButton from "@/components/button/BlurredIconButton"; import { AlertDialog, AlertDialogAction, @@ -858,20 +859,15 @@ function FaceAttemptGroup({ faceNames={faceNames} onTrainAttempt={(name) => onTrainAttempt(data, name)} > -
-
- -
+ + + - -
-
- onReprocess(data)} - /> -
+ + onReprocess(data)}> + + {t("button.reprocessFace")} diff --git a/web/src/views/classification/ModelTrainingView.tsx b/web/src/views/classification/ModelTrainingView.tsx index ed96406e6..5c7a649c3 100644 --- a/web/src/views/classification/ModelTrainingView.tsx +++ b/web/src/views/classification/ModelTrainingView.tsx @@ -51,6 +51,7 @@ import { toast } from "sonner"; import useSWR from "swr"; import ClassificationSelectionDialog from "@/components/overlay/ClassificationSelectionDialog"; import { TbCategoryPlus } from "react-icons/tb"; +import BlurredIconButton from "@/components/button/BlurredIconButton"; import { useModelState } from "@/api/ws"; import { ModelState } from "@/types/ws"; import ActivityIndicator from "@/components/indicators/activity-indicator"; @@ -811,10 +812,9 @@ function StateTrainGrid({ image={data.filename} onRefresh={onRefresh} > -
-
- -
+ + +
@@ -961,10 +961,9 @@ function ObjectTrainGrid({ image={data.filename} onRefresh={onRefresh} > -
-
- -
+ + + )}