- 优化设计系统和主题配置 - 增强Tailwind配置,添加更丰富的色彩系统 - 新增多种动画效果和过渡动画 - 改进字体系统和间距设置 - 添加阴影变体和渐变效果 - 改进项目列表页面UI/UX - 重新设计页面头部,添加渐变背景和统计信息 - 优化项目卡片布局和响应式设计 - 增强加载和错误状态的视觉效果 - 添加交错动画效果 - 优化项目卡片组件 - 重新设计卡片布局,添加背景装饰 - 改进统计信息展示,使用渐变背景和徽章 - 增强悬停效果和交互反馈 - 优化菜单和按钮设计 - 改进表单和模态框体验 - 重新设计模态框头部和布局 - 增强表单字段的视觉设计和验证反馈 - 添加加载状态和成功状态指示 - 改进按钮样式和交互效果 - 增强加载状态和反馈机制 - 重新设计EmptyState组件,添加装饰效果 - 增强LoadingSpinner,支持多种动画样式 - 改进ErrorMessage组件,支持多种消息类型 - 新增SkeletonLoader组件用于骨架屏加载 - 添加微交互和动画效果 - 新增AnimatedButton组件,支持涟漪效果 - 创建PageTransition组件用于页面过渡 - 添加多种动画工具组件 - 增强按钮和卡片的微交互效果 - 优化响应式设计和移动端体验 - 改进容器布局和间距设置 - 优化移动端的触摸体验 - 确保所有组件在不同屏幕尺寸下的完美适配 遵循前端开发规范,提升界面美观性和用户体验
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import React from 'react';
|
|
import { Loader2, Circle } from 'lucide-react';
|
|
|
|
interface LoadingSpinnerProps {
|
|
size?: 'small' | 'medium' | 'large';
|
|
text?: string;
|
|
variant?: 'spinner' | 'dots' | 'pulse' | 'bars';
|
|
color?: 'primary' | 'secondary' | 'white';
|
|
}
|
|
|
|
/**
|
|
* 增强的加载动画组件
|
|
* 支持多种动画样式和尺寸
|
|
*/
|
|
export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
|
|
size = 'medium',
|
|
text,
|
|
variant = 'spinner',
|
|
color = 'primary'
|
|
}) => {
|
|
const sizeMap = {
|
|
small: { icon: 16, text: 'text-sm', padding: 'p-3' },
|
|
medium: { icon: 24, text: 'text-base', padding: 'p-6' },
|
|
large: { icon: 32, text: 'text-lg', padding: 'p-8' }
|
|
};
|
|
|
|
const colorMap = {
|
|
primary: 'text-primary-600',
|
|
secondary: 'text-gray-600',
|
|
white: 'text-white'
|
|
};
|
|
|
|
const currentSize = sizeMap[size];
|
|
const currentColor = colorMap[color];
|
|
|
|
const renderSpinner = () => {
|
|
switch (variant) {
|
|
case 'dots':
|
|
return (
|
|
<div className="flex space-x-1">
|
|
{[0, 1, 2].map((i) => (
|
|
<Circle
|
|
key={i}
|
|
size={currentSize.icon / 3}
|
|
className={`${currentColor} animate-loading-dots`}
|
|
style={{ animationDelay: `${i * 0.2}s` }}
|
|
fill="currentColor"
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
|
|
case 'pulse':
|
|
return (
|
|
<div className={`w-${currentSize.icon / 4} h-${currentSize.icon / 4} ${currentColor.replace('text-', 'bg-')} rounded-full animate-pulse-slow`} />
|
|
);
|
|
|
|
case 'bars':
|
|
return (
|
|
<div className="flex space-x-1">
|
|
{[0, 1, 2, 3].map((i) => (
|
|
<div
|
|
key={i}
|
|
className={`w-1 h-${currentSize.icon / 4} ${currentColor.replace('text-', 'bg-')} animate-loading-bars`}
|
|
style={{ animationDelay: `${i * 0.1}s` }}
|
|
/>
|
|
))}
|
|
</div>
|
|
);
|
|
|
|
default:
|
|
return (
|
|
<Loader2
|
|
size={currentSize.icon}
|
|
className={`animate-spin ${currentColor}`}
|
|
/>
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={`flex flex-col items-center justify-center gap-4 ${currentSize.padding} animate-fade-in`}>
|
|
{/* 加载动画 */}
|
|
<div className="relative">
|
|
{/* 背景光晕效果 */}
|
|
{color === 'primary' && (
|
|
<div className="absolute inset-0 bg-primary-200 rounded-full blur-lg opacity-30 animate-pulse"></div>
|
|
)}
|
|
|
|
{/* 主要动画 */}
|
|
<div className="relative">
|
|
{renderSpinner()}
|
|
</div>
|
|
</div>
|
|
|
|
{/* 加载文本 */}
|
|
{text && (
|
|
<div className="text-center">
|
|
<span className={`${currentColor} ${currentSize.text} font-medium animate-pulse`}>
|
|
{text}
|
|
</span>
|
|
|
|
{/* 动态点点点效果 */}
|
|
<span className="inline-flex ml-1">
|
|
{[0, 1, 2].map((i) => (
|
|
<span
|
|
key={i}
|
|
className={`${currentColor} animate-pulse`}
|
|
style={{ animationDelay: `${i * 0.3}s` }}
|
|
>
|
|
.
|
|
</span>
|
|
))}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|