Clean up design of classification card

This commit is contained in:
Nicolas Mowen 2025-10-20 17:03:27 -06:00
parent cb9dd09929
commit 72896f4631
5 changed files with 60 additions and 77 deletions

View File

@ -41,8 +41,8 @@
"invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens."
},
"train": {
"title": "Train",
"aria": "Select Train"
"title": "Recent Classifications",
"aria": "Select Recent Classifications"
},
"categories": "Classes",
"createCategory": {

View File

@ -72,59 +72,58 @@ export function ClassificationCard({
}, [showArea, imageLoaded]);
return (
<>
<div
<div
className={cn(
"relative flex size-48 cursor-pointer flex-col overflow-hidden rounded-lg outline outline-[3px]",
selected
? "shadow-selected outline-selected"
: "outline-transparent duration-500",
)}
>
<img
ref={imgRef}
className={cn(
"relative flex cursor-pointer flex-col rounded-lg outline outline-[3px]",
className,
selected
? "shadow-selected outline-selected"
: "outline-transparent duration-500",
"absolute bottom-0 left-0 right-0 top-0 size-full",
imgClassName,
isMobile && "w-full",
)}
>
<div className="relative w-full select-none overflow-hidden rounded-lg">
<img
ref={imgRef}
onLoad={() => setImageLoaded(true)}
className={cn("size-44", imgClassName, isMobile && "w-full")}
src={`${baseUrl}${data.filepath}`}
onClick={(e) => {
e.stopPropagation();
onClick(data, e.metaKey || e.ctrlKey);
}}
/>
{imageArea != undefined && (
<div className="absolute bottom-1 right-1 z-10 rounded-lg bg-black/50 px-2 py-1 text-xs text-white">
{t("information.pixels", { ns: "common", area: imageArea })}
</div>
)}
onLoad={() => setImageLoaded(true)}
src={`${baseUrl}${data.filepath}`}
onClick={(e) => {
e.stopPropagation();
onClick(data, e.metaKey || e.ctrlKey);
}}
/>
{false && imageArea != undefined && (
<div className="absolute bottom-1 right-1 z-10 rounded-lg bg-black/50 px-2 py-1 text-xs text-white">
{t("information.pixels", { ns: "common", area: imageArea })}
</div>
<div className="select-none p-2">
<div className="flex w-full flex-row items-center justify-between gap-2">
<div className="flex flex-col items-start text-xs text-primary-variant">
<div className="smart-capitalize">
{data.name == "unknown" ? t("details.unknown") : data.name}
)}
<div className="absolute bottom-0 left-0 right-0 flex h-12 select-none gap-2 bg-gradient-to-t from-black/60 to-transparent p-2">
<div className="flex w-full flex-row items-center justify-between gap-2">
<div className="text-xs flex flex-col items-start text-white">
<div className="smart-capitalize">
{data.name == "unknown" ? t("details.unknown") : data.name}
</div>
{data.score && (
<div
className={cn(
"",
scoreStatus == "match" && "text-success",
scoreStatus == "potential" && "text-orange-400",
scoreStatus == "unknown" && "text-danger",
)}
>
{Math.round(data.score * 100)}%
</div>
{data.score && (
<div
className={cn(
"",
scoreStatus == "match" && "text-success",
scoreStatus == "potential" && "text-orange-400",
scoreStatus == "unknown" && "text-danger",
)}
>
{Math.round(data.score * 100)}%
</div>
)}
</div>
<div className="flex flex-row items-start justify-end gap-5 md:gap-4">
{children}
</div>
)}
</div>
<div className="flex flex-row items-start justify-end gap-5 md:gap-4">
{children}
</div>
</div>
</div>
</>
</div>
);
}

View File

@ -20,15 +20,14 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { isDesktop, isMobile } from "react-device-detect";
import { LuPlus } from "react-icons/lu";
import { useTranslation } from "react-i18next";
import { cn } from "@/lib/utils";
import React, { ReactNode, useCallback, useMemo, useState } from "react";
import TextEntryDialog from "./dialog/TextEntryDialog";
import { Button } from "../ui/button";
import { MdCategory } from "react-icons/md";
import axios from "axios";
import { toast } from "sonner";
import { Separator } from "../ui/separator";
type ClassificationSelectionDialogProps = {
className?: string;
@ -97,7 +96,7 @@ export default function ClassificationSelectionDialog({
);
return (
<div className={className ?? ""}>
<div className={className ?? "flex"}>
{newClass && (
<TextEntryDialog
open={true}
@ -128,23 +127,22 @@ export default function ClassificationSelectionDialog({
isMobile && "gap-2 pb-4",
)}
>
<SelectorItem
className="flex cursor-pointer gap-2 smart-capitalize"
onClick={() => setNewClass(true)}
>
<LuPlus />
{t("createCategory.new")}
</SelectorItem>
{classes.sort().map((category) => (
<SelectorItem
key={category}
className="flex cursor-pointer gap-2 smart-capitalize"
onClick={() => onCategorizeImage(category)}
>
<MdCategory />
{category.replaceAll("_", " ")}
</SelectorItem>
))}
<Separator />
<SelectorItem
className="flex cursor-pointer gap-2 smart-capitalize"
onClick={() => setNewClass(true)}
>
{t("createCategory.new")}
</SelectorItem>
</div>
</SelectorContent>
</Selector>

View File

@ -60,7 +60,7 @@ export default function TrainFilterDialog({
moreFiltersSelected ? "text-white" : "text-secondary-foreground",
)}
/>
{isDesktop && t("more")}
{isDesktop && t("filter")}
</Button>
);
const content = (
@ -122,7 +122,7 @@ export default function TrainFilterDialog({
return (
<PlatformAwareSheet
trigger={trigger}
title={t("more")}
title={t("filter")}
content={content}
contentClassName={cn(
"w-auto lg:min-w-[275px] scrollbar-container h-full overflow-auto px-4",

View File

@ -650,7 +650,7 @@ function DatasetGrid({
<Tooltip>
<TooltipTrigger>
<LuTrash2
className="size-5 cursor-pointer text-primary-variant hover:text-primary"
className="size-5 cursor-pointer text-primary-variant hover:text-danger"
onClick={(e) => {
e.stopPropagation();
onDelete([image]);
@ -817,22 +817,8 @@ function StateTrainGrid({
image={data.filename}
onRefresh={onRefresh}
>
<TbCategoryPlus className="size-5 cursor-pointer text-primary-variant hover:text-primary" />
<TbCategoryPlus className="size-7 cursor-pointer p-1 text-white hover:rounded-full hover:bg-primary-foreground" />
</ClassificationSelectionDialog>
<Tooltip>
<TooltipTrigger>
<LuTrash2
className="size-5 cursor-pointer text-primary-variant hover:text-primary"
onClick={(e) => {
e.stopPropagation();
onDelete([data.filename]);
}}
/>
</TooltipTrigger>
<TooltipContent>
{t("button.deleteClassificationAttempts")}
</TooltipContent>
</Tooltip>
</ClassificationCard>
))}
</div>