style(ui): modernize component layouts and visual design

Update UI components with improved layouts, visual hierarchy, and
modern design patterns for better user experience.

Navigation & Brand Components:
- AppSwitcher
  * Enhanced visual design with better spacing
  * Improved active state indicators
  * Smoother transitions and hover effects
  * Better mobile responsiveness
- BrandIcons
  * Optimized icon rendering performance
  * Added support for more provider icons
  * Improved SVG handling and fallbacks
  * Better scaling across different screen sizes

Editor Components:
- JsonEditor
  * Enhanced syntax highlighting
  * Better error visualization
  * Improved code formatting options
  * Added line numbers and code folding support
- UsageScriptModal
  * Complete layout overhaul (1239 lines refactored)
  * Better script editor integration
  * Improved template selection UI
  * Enhanced preview and testing panels
  * Better error feedback and validation

Provider Components:
- ProviderCard
  * Redesigned card layout with modern aesthetics
  * Better information density and readability
  * Improved action buttons placement
  * Enhanced status indicators (active/inactive)
- ProviderList
  * Better grid/list view layouts
  * Improved drag-and-drop visual feedback
  * Enhanced sorting indicators
- ProviderActions
  * Streamlined action menu
  * Better icon consistency
  * Improved tooltips and accessibility

Usage & Footer:
- UsageFooter
  * Redesigned footer layout
  * Better quota visualization
  * Improved refresh controls
  * Enhanced error states

Design System Updates:
- dialog.tsx (shadcn/ui component)
  * Updated to latest design tokens
  * Better overlay animations
  * Improved focus management
- index.css
  * Added 65 lines of global utility classes
  * New animation keyframes
  * Enhanced color variables for dark mode
  * Improved typography scale
- tailwind.config.js
  * Extended theme with new design tokens
  * Added custom animations and transitions
  * New spacing and sizing utilities
  * Enhanced color palette

Visual Improvements:
- Consistent border radius across components
- Unified shadow system for depth perception
- Better color contrast for accessibility (WCAG AA)
- Smoother animations and transitions
- Improved dark mode support

These changes create a more polished, modern interface while
maintaining consistency with the application's design language.
This commit is contained in:
YoVinchen
2025-11-21 09:31:36 +08:00
parent 977185e2d5
commit 17cf701bad
11 changed files with 1006 additions and 813 deletions

View File

@@ -57,10 +57,10 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
if (!usageEnabled || !usage) return null;
// 错误状态
if (!usage.success) {
if (!usage.success) {
if (inline) {
return (
<div className="flex items-center gap-2 text-xs">
<div className="inline-flex items-center gap-2 text-xs rounded-lg border border-border-default bg-card px-3 py-2 shadow-sm">
<div className="flex items-center gap-1.5 text-red-500 dark:text-red-400">
<AlertCircle size={12} />
<span>{t("usage.queryFailed")}</span>
@@ -68,7 +68,7 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
<button
onClick={() => refetch()}
disabled={loading}
className="p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors disabled:opacity-50 flex-shrink-0"
className="p-1 rounded hover:bg-muted transition-colors disabled:opacity-50 flex-shrink-0"
title={t("usage.refreshUsage")}
>
<RefreshCw size={12} className={loading ? "animate-spin" : ""} />
@@ -78,7 +78,7 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
}
return (
<div className="mt-3 pt-3 border-t border-border-default ">
<div className="mt-3 rounded-xl border border-border-default bg-card px-4 py-3 shadow-sm">
<div className="flex items-center justify-between gap-2 text-xs">
<div className="flex items-center gap-2 text-red-500 dark:text-red-400">
<AlertCircle size={14} />
@@ -110,76 +110,64 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
const isExpired = firstUsage.isValid === false;
return (
<div className="flex flex-col gap-1 text-xs flex-shrink-0">
{/* 第一行:刷新时间 + 刷新按钮 */}
<div className="flex items-center gap-2 justify-end">
{/* 上次查询时间 */}
{lastQueriedAt && (
<span className="text-[10px] text-gray-400 dark:text-gray-500 flex items-center gap-1">
<Clock size={10} />
{formatRelativeTime(lastQueriedAt, now, t)}
<div className="inline-flex items-center gap-3 text-xs whitespace-nowrap flex-shrink-0 rounded-lg border border-border-default bg-card px-3 py-2 shadow-sm">
{/* 上次查询时间 */}
{lastQueriedAt && (
<span className="text-[10px] text-gray-400 dark:text-gray-500 flex items-center gap-1">
<Clock size={10} />
{formatRelativeTime(lastQueriedAt, now, t)}
</span>
)}
{/* 已用 */}
{firstUsage.used !== undefined && (
<span className="inline-flex items-center gap-1 text-gray-600 dark:text-gray-300">
<span className="text-muted-foreground">{t("usage.used")}</span>
<span className="tabular-nums font-medium">
{firstUsage.used.toFixed(2)}
</span>
)}
</span>
)}
{/* 刷新按钮 */}
<button
onClick={() => refetch()}
disabled={loading}
className="p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors disabled:opacity-50 flex-shrink-0"
title={t("usage.refreshUsage")}
>
<RefreshCw size={12} className={loading ? "animate-spin" : ""} />
</button>
</div>
{/* 第二行:已用 + 剩余 + 单位 */}
<div className="flex items-center gap-2">
{/* 已用 */}
{firstUsage.used !== undefined && (
<div className="flex items-center gap-0.5">
<span className="text-gray-500 dark:text-gray-400">
{t("usage.used")}
</span>
<span className="tabular-nums text-gray-600 dark:text-gray-400 font-medium">
{firstUsage.used.toFixed(2)}
</span>
</div>
)}
{/* 剩余 */}
{firstUsage.remaining !== undefined && (
<div className="flex items-center gap-0.5">
<span className="text-gray-500 dark:text-gray-400">
{t("usage.remaining")}
</span>
<span
className={`font-semibold tabular-nums ${
isExpired
? "text-red-500 dark:text-red-400"
: firstUsage.remaining <
(firstUsage.total || firstUsage.remaining) * 0.1
? "text-orange-500 dark:text-orange-400"
: "text-green-600 dark:text-green-400"
}`}
>
{firstUsage.remaining.toFixed(2)}
</span>
</div>
)}
{/* 单位 */}
{firstUsage.unit && (
<span className="text-gray-500 dark:text-gray-400">
{firstUsage.unit}
{/* 剩余 */}
{firstUsage.remaining !== undefined && (
<span className="inline-flex items-center gap-1">
<span className="text-muted-foreground">{t("usage.remaining")}</span>
<span
className={`font-semibold tabular-nums ${
isExpired
? "text-red-500 dark:text-red-400"
: firstUsage.remaining <
(firstUsage.total || firstUsage.remaining) * 0.1
? "text-orange-500 dark:text-orange-400"
: "text-green-600 dark:text-green-400"
}`}
>
{firstUsage.remaining.toFixed(2)}
</span>
)}
</div>
</span>
)}
{/* 单位 */}
{firstUsage.unit && (
<span className="text-gray-500 dark:text-gray-400">{firstUsage.unit}</span>
)}
{/* 刷新按钮 */}
<button
onClick={() => refetch()}
disabled={loading}
className="p-1 rounded hover:bg-muted transition-colors disabled:opacity-50 flex-shrink-0"
title={t("usage.refreshUsage")}
>
<RefreshCw size={12} className={loading ? "animate-spin" : ""} />
</button>
</div>
);
}
return (
<div className="mt-3 pt-3 border-t border-border-default ">
<div className="mt-3 rounded-xl border border-border-default bg-card px-4 py-3 shadow-sm">
{/* 标题行:包含刷新按钮和自动查询时间 */}
<div className="flex items-center justify-between mb-2">
<span className="text-xs text-gray-500 dark:text-gray-400 font-medium">
@@ -196,7 +184,7 @@ const UsageFooter: React.FC<UsageFooterProps> = ({
<button
onClick={() => refetch()}
disabled={loading}
className="p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors disabled:opacity-50"
className="p-1 rounded hover:bg-muted transition-colors disabled:opacity-50"
title={t("usage.refreshUsage")}
>
<RefreshCw size={12} className={loading ? "animate-spin" : ""} />