refactor(ui): simplify AppSwitcher styles and migrate to local SVG icons

- Replace complex gradient animations with clean, minimal tab design
- Migrate from @lobehub/icons CDN to local SVG assets for better reliability
- Fix clippy warning in error.rs (use inline format args)
- Improve code formatting in skill service and commands
- Reduce CSS complexity in AppSwitcher component (removed blur effects and gradients)
- Update BrandIcons to use imported local SVG files instead of dynamic image loading

This improves performance, reduces external dependencies, and provides a cleaner UI experience.
This commit is contained in:
YoVinchen
2025-11-22 01:20:21 +08:00
parent e7545f8cdf
commit de7f93d513
8 changed files with 64 additions and 123 deletions
+20 -56
View File
@@ -1,84 +1,48 @@
import { useEffect, useState } from "react";
interface IconProps {
size?: number;
className?: string;
}
const LOBE_ICONS_VERSION = "latest"; // pin if needed, e.g. "1.4.0"
const LOBE_BASE = `https://cdn.jsdelivr.net/npm/@lobehub/icons-static-svg@${LOBE_ICONS_VERSION}/icons`;
function IconImage({
urls,
alt,
size,
className,
}: {
urls: string[];
alt: string;
size: number;
className?: string;
}) {
const [index, setIndex] = useState(0);
useEffect(() => {
setIndex(0);
}, [urls.join("|")]);
const src = urls[index] ?? urls[urls.length - 1];
return (
<img
src={src}
width={size}
height={size}
className={className}
alt={alt}
loading="lazy"
referrerPolicy="no-referrer"
onError={() => {
if (index < urls.length - 1) {
setIndex((i) => i + 1);
}
}}
/>
);
}
// 导入本地 SVG 图标
import ClaudeSvg from "@/icons/extracted/claude.svg?url";
import OpenAISvg from "@/icons/extracted/openai.svg?url";
import GeminiSvg from "@/icons/extracted/gemini.svg?url";
export function ClaudeIcon({ size = 16, className = "" }: IconProps) {
return (
<IconImage
urls={[`${LOBE_BASE}/claude-color.svg`, `${LOBE_BASE}/claude.svg`]}
size={size}
<img
src={ClaudeSvg}
width={size}
height={size}
className={className}
alt="Claude"
loading="lazy"
/>
);
}
export function CodexIcon({ size = 16, className = "" }: IconProps) {
return (
<IconImage
urls={[
`${LOBE_BASE}/openai-color.svg`,
`${LOBE_BASE}/chatgpt-color.svg`,
`${LOBE_BASE}/openai.svg`,
`${LOBE_BASE}/chatgpt.svg`,
]}
size={size}
className={className}
<img
src={OpenAISvg}
width={size}
height={size}
className={`dark:brightness-0 dark:invert ${className}`}
alt="Codex"
loading="lazy"
/>
);
}
export function GeminiIcon({ size = 16, className = "" }: IconProps) {
return (
<IconImage
urls={[`${LOBE_BASE}/gemini-color.svg`, `${LOBE_BASE}/gemini.svg`]}
size={size}
<img
src={GeminiSvg}
width={size}
height={size}
className={className}
alt="Gemini"
loading="lazy"
/>
);
}