refactor(ui): extract shared components and deduplicate MCP/Skills panels (#897)

* refactor(ui): add tooltips and icons to MCP and Skills panels

* refactor: deduplicate UnifiedSkillsPanel and UnifiedMcpPanel shared code
This commit is contained in:
PeanutSplash
2026-02-04 10:10:45 +08:00
committed by GitHub
parent f0e8ba1d8f
commit e65360e68a
9 changed files with 254 additions and 302 deletions
+31
View File
@@ -0,0 +1,31 @@
import React from "react";
import { Badge } from "@/components/ui/badge";
import type { AppId } from "@/lib/api/types";
import { APP_IDS, APP_ICON_MAP } from "@/config/appConfig";
interface AppCountBarProps {
totalLabel: string;
counts: Record<AppId, number>;
}
export const AppCountBar: React.FC<AppCountBarProps> = ({ totalLabel, counts }) => {
return (
<div className="flex-shrink-0 py-4 glass rounded-xl border border-white/10 mb-4 px-6 flex items-center justify-between gap-4">
<Badge variant="outline" className="bg-background/50 h-7 px-3">
{totalLabel}
</Badge>
<div className="flex items-center gap-2 overflow-x-auto no-scrollbar">
{APP_IDS.map((app) => (
<Badge
key={app}
variant="secondary"
className={APP_ICON_MAP[app].badgeClass}
>
<span className="opacity-75">{APP_ICON_MAP[app].label}:</span>
<span className="font-bold ml-1">{counts[app]}</span>
</Badge>
))}
</div>
</div>
);
};
+44
View File
@@ -0,0 +1,44 @@
import React from "react";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import type { AppId } from "@/lib/api/types";
import { APP_IDS, APP_ICON_MAP } from "@/config/appConfig";
interface AppToggleGroupProps {
apps: Record<AppId, boolean>;
onToggle: (app: AppId, enabled: boolean) => void;
}
export const AppToggleGroup: React.FC<AppToggleGroupProps> = ({ apps, onToggle }) => {
return (
<div className="flex items-center gap-1.5 flex-shrink-0">
{APP_IDS.map((app) => {
const { label, icon, activeClass } = APP_ICON_MAP[app];
const enabled = apps[app];
return (
<Tooltip key={app}>
<TooltipTrigger asChild>
<button
type="button"
onClick={() => onToggle(app, !enabled)}
className={`w-7 h-7 rounded-lg flex items-center justify-center transition-all ${
enabled
? activeClass
: "opacity-35 hover:opacity-70"
}`}
>
{icon}
</button>
</TooltipTrigger>
<TooltipContent side="bottom">
<p>{label}{enabled ? " ✓" : ""}</p>
</TooltipContent>
</Tooltip>
);
})}
</div>
);
};
+18
View File
@@ -0,0 +1,18 @@
import React from "react";
interface ListItemRowProps {
isLast?: boolean;
children: React.ReactNode;
}
export const ListItemRow: React.FC<ListItemRowProps> = ({ isLast, children }) => {
return (
<div
className={`group flex items-center gap-3 px-4 py-2.5 hover:bg-muted/50 transition-colors ${
!isLast ? "border-b border-border-default" : ""
}`}
>
{children}
</div>
);
};