mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 00:35:32 +08:00
refactor(ui): improve icon rendering consistency and spacing
Standardize icon sizes and improve rendering consistency across the application interface. Changes: - ProviderIcon: Add fontSize sync with size prop for embedded SVG scaling, improve fallback text sizing calculation - AppSwitcher: Replace brand icon components with unified ProviderIcon, standardize icon size to 20px across all app tabs - ProviderCard: Reduce icon size from 26px to 20px for better visual balance in card layout - DeepLinkImportDialog: Increase confirmation icon size from 64px to 80px for better visibility - BasicFormFields: Reduce icon picker button spacing from space-y-6 to space-y-2 for improved layout density Icon rendering improvements: - Embedded SVGs now properly scale with fontSize set to match size prop - Fallback initials use responsive font sizing (50% of icon size, minimum 12px) - Consistent 20px standard for navigation and card icons - Better visual hierarchy with appropriate sizing for different contexts This refactor improves visual consistency and makes icon rendering more predictable across different components.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { AppId } from "@/lib/api";
|
||||
import { ClaudeIcon, CodexIcon, GeminiIcon } from "./BrandIcons";
|
||||
import { ProviderIcon } from "@/components/ProviderIcon";
|
||||
|
||||
interface AppSwitcherProps {
|
||||
activeApp: AppId;
|
||||
@@ -11,6 +11,17 @@ export function AppSwitcher({ activeApp, onSwitch }: AppSwitcherProps) {
|
||||
if (app === activeApp) return;
|
||||
onSwitch(app);
|
||||
};
|
||||
const iconSize = 20;
|
||||
const appIconName: Record<AppId, string> = {
|
||||
claude: "claude",
|
||||
codex: "openai",
|
||||
gemini: "gemini",
|
||||
};
|
||||
const appDisplayName: Record<AppId, string> = {
|
||||
claude: "Claude",
|
||||
codex: "Codex",
|
||||
gemini: "Gemini",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="inline-flex bg-gray-100 dark:bg-gray-800 rounded-lg p-1 gap-1">
|
||||
@@ -23,15 +34,17 @@ export function AppSwitcher({ activeApp, onSwitch }: AppSwitcherProps) {
|
||||
: "text-gray-500 hover:text-gray-900 hover:bg-white/50 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800/60"
|
||||
}`}
|
||||
>
|
||||
<ClaudeIcon
|
||||
size={16}
|
||||
<ProviderIcon
|
||||
icon={appIconName.claude}
|
||||
name={appDisplayName.claude}
|
||||
size={iconSize}
|
||||
className={
|
||||
activeApp === "claude"
|
||||
? "text-foreground"
|
||||
: "text-gray-500 dark:text-gray-400 group-hover:text-foreground transition-colors"
|
||||
}
|
||||
/>
|
||||
<span>Claude</span>
|
||||
<span>{appDisplayName.claude}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@@ -43,15 +56,17 @@ export function AppSwitcher({ activeApp, onSwitch }: AppSwitcherProps) {
|
||||
: "text-gray-500 hover:text-gray-900 hover:bg-white/50 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800/60"
|
||||
}`}
|
||||
>
|
||||
<CodexIcon
|
||||
size={16}
|
||||
<ProviderIcon
|
||||
icon={appIconName.codex}
|
||||
name={appDisplayName.codex}
|
||||
size={iconSize}
|
||||
className={
|
||||
activeApp === "codex"
|
||||
? "text-foreground"
|
||||
: "text-gray-500 dark:text-gray-400 group-hover:text-foreground transition-colors"
|
||||
}
|
||||
/>
|
||||
<span>Codex</span>
|
||||
<span>{appDisplayName.codex}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@@ -63,15 +78,17 @@ export function AppSwitcher({ activeApp, onSwitch }: AppSwitcherProps) {
|
||||
: "text-gray-500 hover:text-gray-900 hover:bg-white/50 dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-800/60"
|
||||
}`}
|
||||
>
|
||||
<GeminiIcon
|
||||
size={16}
|
||||
<ProviderIcon
|
||||
icon={appIconName.gemini}
|
||||
name={appDisplayName.gemini}
|
||||
size={iconSize}
|
||||
className={
|
||||
activeApp === "gemini"
|
||||
? "text-foreground"
|
||||
: "text-gray-500 dark:text-gray-400 group-hover:text-foreground transition-colors"
|
||||
}
|
||||
/>
|
||||
<span>Gemini</span>
|
||||
<span>{appDisplayName.gemini}</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -338,7 +338,7 @@ export function DeepLinkImportDialog() {
|
||||
<ProviderIcon
|
||||
icon={request.icon}
|
||||
name={request.name || request.icon}
|
||||
size={64}
|
||||
size={80}
|
||||
className="drop-shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -32,6 +32,9 @@ export const ProviderIcon: React.FC<ProviderIconProps> = ({
|
||||
return {
|
||||
width: sizeValue,
|
||||
height: sizeValue,
|
||||
// 内嵌 SVG 使用 1em 作为尺寸基准,这里同步 fontSize 让图标实际跟随 size 放大
|
||||
fontSize: sizeValue,
|
||||
lineHeight: 1,
|
||||
};
|
||||
}, [size]);
|
||||
|
||||
@@ -57,6 +60,8 @@ export const ProviderIcon: React.FC<ProviderIconProps> = ({
|
||||
.join("")
|
||||
.toUpperCase()
|
||||
.slice(0, 2);
|
||||
const fallbackFontSize =
|
||||
typeof size === "number" ? `${Math.max(size * 0.5, 12)}px` : "0.5em";
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
@@ -68,7 +73,7 @@ export const ProviderIcon: React.FC<ProviderIconProps> = ({
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
fontSize: `${typeof size === "number" ? size * 0.4 : 14}px`,
|
||||
fontSize: fallbackFontSize,
|
||||
}}
|
||||
>
|
||||
{initials}
|
||||
|
||||
@@ -141,12 +141,12 @@ export function ProviderCard({
|
||||
</button>
|
||||
|
||||
{/* 供应商图标 */}
|
||||
<div className="h-9 w-9 rounded-lg bg-white/5 flex items-center justify-center border border-gray-200 dark:border-white/10 group-hover:scale-105 transition-transform duration-300">
|
||||
<div className="h-8 w-8 rounded-lg bg-white/5 flex items-center justify-center border border-gray-200 dark:border-white/10 group-hover:scale-105 transition-transform duration-300">
|
||||
<ProviderIcon
|
||||
icon={provider.icon}
|
||||
name={provider.name}
|
||||
color={provider.iconColor}
|
||||
size={26}
|
||||
size={20}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ export function BasicFormFields({ form }: BasicFormFieldsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<div className="space-y-6 mx-auto max-w-[56rem] px-6 py-6 w-full">
|
||||
<div className="space-y-2 mx-auto max-w-[56rem] px-6 py-6 w-full">
|
||||
<IconPicker
|
||||
value={currentIcon}
|
||||
onValueChange={handleIconSelect}
|
||||
|
||||
Reference in New Issue
Block a user