refactor: 提取 useToast hook + Toast 组件,消除 4 处重复的通知逻辑
将 state + setTimeout 自动消失逻辑封装为 useToast hook, Toast UI 统一为组件支持 top/bottom 两种位置,净减约 12 行。
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
interface ToastProps {
|
||||
message: string;
|
||||
position?: "top" | "bottom";
|
||||
}
|
||||
|
||||
const positionClass = {
|
||||
top: "top-10",
|
||||
bottom: "bottom-8",
|
||||
};
|
||||
|
||||
export default function Toast({ message, position = "top" }: ToastProps) {
|
||||
const isTop = position === "top";
|
||||
const y = isTop ? -12 : 12;
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{message && (
|
||||
<motion.div
|
||||
className={`fixed left-1/2 z-60 -translate-x-1/2 rounded-xl bg-elevated px-4 py-2.5 text-xs font-medium text-heading shadow-lg ring-1 ring-subtle ${positionClass[position]}`}
|
||||
initial={{ opacity: 0, y, x: "-50%" }}
|
||||
animate={{ opacity: 1, y: 0, x: "-50%" }}
|
||||
exit={{ opacity: 0, y, x: "-50%" }}
|
||||
transition={{ type: "spring", stiffness: 400, damping: 25 }}
|
||||
>
|
||||
{message}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user