ui: 个人中心空状态插图优化,替换纯文字为图标动画 + CTA 按钮

提取可复用 EmptyState 组件,决策记录和收藏餐厅空状态
增加浮动图标、光晕动画和"去创建第一个房间"引导按钮
This commit is contained in:
2026-02-26 15:18:22 +08:00
parent 12279117f3
commit e86f643c26
2 changed files with 77 additions and 6 deletions
+58
View File
@@ -0,0 +1,58 @@
"use client";
import { motion } from "framer-motion";
import type { LucideIcon } from "lucide-react";
interface EmptyStateProps {
icon: LucideIcon;
title: string;
subtitle?: string;
ctaLabel?: string;
onCta?: () => void;
color?: string;
}
export default function EmptyState({
icon: Icon,
title,
subtitle,
ctaLabel,
onCta,
color = "purple",
}: EmptyStateProps) {
const colorMap: Record<string, { glow: string; icon: string; btn: string; btnHover: string }> = {
purple: { glow: "bg-purple-600/15", icon: "text-purple-400/60", btn: "bg-purple-600 hover:bg-purple-500", btnHover: "" },
amber: { glow: "bg-amber-500/15", icon: "text-amber-400/60", btn: "bg-amber-600 hover:bg-amber-500", btnHover: "" },
rose: { glow: "bg-rose-500/15", icon: "text-rose-400/60", btn: "bg-rose-600 hover:bg-rose-500", btnHover: "" },
sky: { glow: "bg-sky-500/15", icon: "text-sky-400/60", btn: "bg-sky-600 hover:bg-sky-500", btnHover: "" },
};
const c = colorMap[color] ?? colorMap.purple;
return (
<div className="flex flex-col items-center py-6">
<motion.div
className="relative flex h-14 w-14 items-center justify-center"
animate={{ y: [0, -3, 0] }}
transition={{ duration: 2.5, repeat: Infinity, ease: "easeInOut" }}
>
<div className={`absolute inset-0 rounded-xl ${c.glow} blur-md`} />
<Icon size={24} className={`relative ${c.icon}`} strokeWidth={1.5} />
</motion.div>
<p className="mt-3 text-sm font-semibold text-secondary">{title}</p>
{subtitle && (
<p className="mt-1 text-xs text-muted">{subtitle}</p>
)}
{ctaLabel && onCta && (
<motion.button
onClick={onCta}
className={`mt-4 rounded-lg px-4 py-1.5 text-xs font-semibold text-white transition-colors ${c.btn}`}
whileTap={{ scale: 0.95 }}
>
{ctaLabel}
</motion.button>
)}
</div>
);
}