chore: update StatCard component for improved icon and count rendering in StatisticsView

This commit is contained in:
Steven 2025-10-14 23:15:16 +08:00
parent 56758f107c
commit 228cc6105d
2 changed files with 46 additions and 34 deletions

View file

@ -1,37 +1,55 @@
import { cloneElement, isValidElement } from "react";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import type { StatCardProps } from "@/types/statistics"; import type { StatCardProps } from "@/types/statistics";
export const StatCard = ({ icon, label, count, onClick, tooltip, className }: StatCardProps) => { export const StatCard = ({ icon, label, count, onClick, tooltip, className }: StatCardProps) => {
const content = ( const iconNode = isValidElement(icon)
<div ? cloneElement(icon, {
className: cn("h-3.5 w-3.5", icon.props.className),
})
: icon;
const countNode = (() => {
if (typeof count === "number" || typeof count === "string") {
return <span className="text-foreground/80">{count}</span>;
}
if (isValidElement(count)) {
return cloneElement(count, {
className: cn("text-foreground/80", count.props.className),
});
}
return <span className="text-foreground/80">{count}</span>;
})();
const button = (
<button
type="button"
onClick={onClick}
className={cn( className={cn(
"w-auto border pl-1.5 pr-2 py-0.5 rounded-md flex justify-between items-center", "inline-flex items-center gap-1 rounded-md border border-border/40 bg-background/80 px-1 pr-2 py-0.5 text-sm leading-none text-muted-foreground transition-colors",
"cursor-pointer hover:bg-muted transition-colors", "hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring/70 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
className, className,
)} )}
onClick={onClick}
> >
<div className="w-auto flex justify-start items-center mr-1"> <span className="flex h-5 w-5 items-center justify-center text-muted-foreground/80">{iconNode}</span>
{icon} <span className="truncate text-sm text-foreground/70">{label}</span>
<span className="block text-sm opacity-80">{label}</span> <span className="ml-1 flex items-center text-sm">{countNode}</span>
</div> </button>
<span className="text-sm truncate opacity-80">{count}</span>
</div>
); );
if (tooltip) { if (!tooltip) {
return ( return button;
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>{content}</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
} }
return content; return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>{button}</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}; };

View file

@ -46,10 +46,10 @@ const StatisticsView = observer(() => {
/> />
</div> </div>
<div className="pt-1 w-full flex flex-row justify-start items-center gap-1 flex-wrap"> <div className="pt-2 w-full flex flex-wrap items-center gap-2">
{isRootPath && hasPinnedMemos && ( {isRootPath && hasPinnedMemos && (
<StatCard <StatCard
icon={<BookmarkIcon className="w-4 h-auto mr-1 opacity-70" />} icon={<BookmarkIcon className="opacity-70" />}
label={t("common.pinned")} label={t("common.pinned")}
count={userStore.state.currentUserStats!.pinnedMemos.length} count={userStore.state.currentUserStats!.pinnedMemos.length}
onClick={() => handleFilterClick("pinned")} onClick={() => handleFilterClick("pinned")}
@ -57,20 +57,14 @@ const StatisticsView = observer(() => {
)} )}
<StatCard <StatCard
icon={<LinkIcon className="w-4 h-auto mr-1 opacity-70" />} icon={<LinkIcon className="opacity-70" />}
label={t("memo.links")} label={t("memo.links")}
count={memoTypeStats.linkCount} count={memoTypeStats.linkCount}
onClick={() => handleFilterClick("property.hasLink")} onClick={() => handleFilterClick("property.hasLink")}
/> />
<StatCard <StatCard
icon={ icon={memoTypeStats.undoCount > 0 ? <ListTodoIcon className="opacity-70" /> : <CheckCircleIcon className="opacity-70" />}
memoTypeStats.undoCount > 0 ? (
<ListTodoIcon className="w-4 h-auto mr-1 opacity-70" />
) : (
<CheckCircleIcon className="w-4 h-auto mr-1 opacity-70" />
)
}
label={t("memo.to-do")} label={t("memo.to-do")}
count={ count={
memoTypeStats.undoCount > 0 ? ( memoTypeStats.undoCount > 0 ? (
@ -88,7 +82,7 @@ const StatisticsView = observer(() => {
/> />
<StatCard <StatCard
icon={<Code2Icon className="w-4 h-auto mr-1 opacity-70" />} icon={<Code2Icon className="opacity-70" />}
label={t("memo.code")} label={t("memo.code")}
count={memoTypeStats.codeCount} count={memoTypeStats.codeCount}
onClick={() => handleFilterClick("property.hasCode")} onClick={() => handleFilterClick("property.hasCode")}