refactor: 提取 Button 组件,统一按钮变体、尺寸和加载状态

新增 Button.tsx 支持 5 种变体(primary/secondary/danger/ghost/purple)、
3 种尺寸(sm/md/lg)、pill/rounded 形状及内置 loading 状态,
替换 8 个文件中 16 处重复的按钮样板代码。
This commit is contained in:
2026-02-26 18:39:14 +08:00
parent 19edcaeeb5
commit 455b9e04d8
9 changed files with 178 additions and 115 deletions
+26 -22
View File
@@ -34,6 +34,7 @@ import { isRegistered } from "@/lib/userId";
import ShareCardModal from "@/components/ShareCardModal";
import RestaurantImage from "@/components/RestaurantImage";
import AuthModal from "@/components/AuthModal";
import Button from "@/components/Button";
import { useToast } from "@/hooks/useToast";
interface MatchResultProps {
@@ -107,24 +108,26 @@ function NoMatchResult({
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.55 }}
>
<motion.button
<Button
onClick={onReset}
disabled={resetting}
className="flex items-center justify-center gap-2 rounded-full bg-accent px-8 py-3 text-sm font-bold text-white shadow-lg shadow-accent/20 transition-colors hover:bg-accent-hover disabled:opacity-50"
whileTap={{ scale: 0.95 }}
shape="pill"
loading={resetting}
loadingText="重置中..."
icon={<RotateCcw size={15} />}
className="px-8 py-3"
>
<RotateCcw size={15} className={resetting ? "animate-spin" : ""} />
{resetting ? "重置中..." : "再来一轮"}
</motion.button>
</Button>
<motion.button
<Button
onClick={() => router.push("/")}
className="flex items-center justify-center gap-2 rounded-full bg-surface px-8 py-3 text-sm font-bold text-muted ring-1 ring-border transition-colors hover:bg-elevated"
whileTap={{ scale: 0.95 }}
variant="secondary"
shape="pill"
icon={<Home size={15} />}
className="px-8 py-3"
>
<Home size={15} />
</motion.button>
</Button>
</motion.div>
</motion.div>
);
@@ -487,14 +490,15 @@ export default function MatchResult({
</motion.a>
)}
<motion.button
<Button
onClick={handleOpenShareCard}
className="flex items-center justify-center gap-2 rounded-full bg-surface px-8 py-3 text-sm font-bold text-secondary ring-1 ring-border transition-colors hover:bg-elevated"
whileTap={{ scale: 0.95 }}
variant="secondary"
shape="pill"
icon={<Share2 size={15} />}
className="px-8 py-3"
>
<Share2 size={15} />
</motion.button>
</Button>
</motion.div>
{/* Registration nudge */}
@@ -511,14 +515,14 @@ export default function MatchResult({
<p className="mt-1 text-xs text-muted">
+ 10
</p>
<motion.button
<Button
onClick={() => setShowAuth(true)}
className="mt-3 flex h-10 w-full items-center justify-center gap-2 rounded-xl bg-accent text-sm font-bold text-white shadow-lg shadow-accent/20 transition-colors hover:bg-accent-hover"
whileTap={{ scale: 0.95 }}
fullWidth
icon={<UserPlus size={15} />}
className="mt-3"
>
<UserPlus size={15} />
</motion.button>
</Button>
</motion.div>
)}