refactor(ui): redesign update notification to match Linear design system

- Replace gradient background with solid colors and subtle borders
- Remove decorative Info icon from settings panel that had no functionality
- Change update badge icon from Sparkles to Download for better clarity
- Simplify update button states with consistent blue primary color
- Remove all gradient effects in favor of flat design
- Unify hover states and transitions across all update-related UI

The update notification now seamlessly integrates with the app's Linear-inspired
aesthetic, providing a clean and non-intrusive user experience.
This commit is contained in:
Jason
2025-09-11 12:06:49 +08:00
parent 319e5fa61a
commit 54b88d9c89
2 changed files with 23 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { X, Info, RefreshCw, FolderOpen, Download, ExternalLink } from "lucide-react"; import { X, RefreshCw, FolderOpen, Download, ExternalLink } from "lucide-react";
import { getVersion } from "@tauri-apps/api/app"; import { getVersion } from "@tauri-apps/api/app";
import "../lib/tauri-api"; import "../lib/tauri-api";
import { relaunchApp } from "../lib/updater"; import { relaunchApp } from "../lib/updater";
@@ -192,11 +192,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
</h3> </h3>
<div className="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg"> <div className="p-4 bg-gray-100 dark:bg-gray-800 rounded-lg">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex items-start gap-3"> <div>
<Info
size={18}
className="text-gray-500 mt-0.5"
/>
<div className="text-sm"> <div className="text-sm">
<p className="font-medium text-gray-900 dark:text-gray-100"> <p className="font-medium text-gray-900 dark:text-gray-100">
CC Switch CC Switch
@@ -222,10 +218,10 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
disabled={isCheckingUpdate || isDownloading} disabled={isCheckingUpdate || isDownloading}
className={`px-3 py-1.5 text-xs font-medium rounded-lg transition-all ${ className={`px-3 py-1.5 text-xs font-medium rounded-lg transition-all ${
isCheckingUpdate || isDownloading isCheckingUpdate || isDownloading
? "bg-white dark:bg-gray-700 text-gray-400 dark:text-gray-500" ? "bg-gray-100 dark:bg-gray-700 text-gray-400 dark:text-gray-500 cursor-not-allowed"
: hasUpdate : hasUpdate
? "bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white" ? "bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 text-white"
: "bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 text-blue-500 dark:text-blue-400" : "bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 text-blue-500 dark:text-blue-400 border border-gray-200 dark:border-gray-600"
}`} }`}
> >
{isDownloading ? ( {isDownloading ? (
@@ -241,7 +237,7 @@ export default function SettingsModal({ onClose }: SettingsModalProps) {
) : hasUpdate ? ( ) : hasUpdate ? (
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<Download size={12} /> <Download size={12} />
{updateInfo?.availableVersion} v{updateInfo?.availableVersion}
</span> </span>
) : ( ) : (
"检查更新" "检查更新"

View File

@@ -1,9 +1,9 @@
import { X, Sparkles } from "lucide-react"; import { X, Download } from "lucide-react";
import { useUpdate } from "../contexts/UpdateContext"; import { useUpdate } from "../contexts/UpdateContext";
interface UpdateBadgeProps { interface UpdateBadgeProps {
className?: string; className?: string;
onClick?: () => void; // 点击徽标的回调(例如打开设置) onClick?: () => void;
} }
export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) { export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) {
@@ -17,12 +17,13 @@ export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) {
return ( return (
<div <div
className={` className={`
flex items-center gap-2 px-3 py-1.5 flex items-center gap-1.5 px-2.5 py-1
bg-gradient-to-r from-blue-500/20 to-purple-500/20 bg-white dark:bg-gray-800
border border-blue-500/30 border border-gray-200 dark:border-gray-700
rounded-full text-xs rounded-lg text-xs
shadow-sm
transition-all duration-200 transition-all duration-200
${onClick ? "cursor-pointer hover:border-blue-400/50" : ""} ${onClick ? "cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-750" : ""}
${className} ${className}
`} `}
role={onClick ? "button" : undefined} role={onClick ? "button" : undefined}
@@ -36,9 +37,9 @@ export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) {
} }
}} }}
> >
<Sparkles className="w-3 h-3 text-blue-400 animate-pulse" /> <Download className="w-3 h-3 text-blue-500 dark:text-blue-400" />
<span className="text-gray-200 font-medium"> <span className="text-gray-700 dark:text-gray-300 font-medium">
{updateInfo.availableVersion} v{updateInfo.availableVersion}
</span> </span>
<button <button
onClick={(e) => { onClick={(e) => {
@@ -46,13 +47,14 @@ export function UpdateBadge({ className = "", onClick }: UpdateBadgeProps) {
dismissUpdate(); dismissUpdate();
}} }}
className=" className="
-mr-1 p-0.5 rounded-full ml-1 -mr-0.5 p-0.5 rounded
hover:bg-white/10 transition-colors hover:bg-gray-100 dark:hover:bg-gray-700
focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-colors
focus:outline-none focus:ring-2 focus:ring-blue-500/20
" "
aria-label="关闭更新提醒" aria-label="关闭更新提醒"
> >
<X className="w-3 h-3 text-gray-400 hover:text-gray-200" /> <X className="w-3 h-3 text-gray-400 dark:text-gray-500" />
</button> </button>
</div> </div>
); );