Files
testing-tool/components/PageSkeleton.tsx
T
LingandRX 373fc0496c Develop (#26)
统一简化多个页面里的CopyButton调用,删除不再需要的空回调参数

* feat: 添加clearCookies函数的单元测试并修复cookie域名处理逻辑

* feat: 增强 data URI 处理,支持带参数的前缀并更新相关测试

* fix: 修正 AGENTS.md 中 TypeScript 类型检查命令的描述

* feat: 添加 settings.local.json 文件以配置 Bash 权限

* perf: 预设背景色避免 Popup 弹窗白屏闪烁

* perf: 避免图标过早实例化,传递组件引用而非 JSX 节点

* feat: 添加 useLazyTranslation 和 preloadNamespaces 函数以支持动态加载 i18n 命名空间

* feat: 使用 useLazyTranslation 替换 useTranslation 以支持懒加载翻译

* feat: 添加 PageSkeleton 组件及其测试用例以支持页面加载骨架屏

* feat: 使用骨架屏替换加载状态指示器,优化用户体验

* feat: 优化 CopyButton 组件的复制功能,添加定时器管理复制状态

* feat: 调整 chunk 大小警告阈值以优化构建性能
2026-05-20 20:07:44 +08:00

104 lines
2.7 KiB
TypeScript

/**
* PageSkeleton 组件 - 页面加载骨架屏
*
* 用于 Suspense fallback 和初始加载状态,提供平滑的视觉过渡
* 避免白屏闪烁,减少布局偏移
*/
import { Box, Skeleton, Stack, useTheme } from '@mui/material';
import { alpha } from '@mui/material';
interface PageSkeletonProps {
/** 骨架屏类型 */
variant?: 'dashboard' | 'tool';
}
/**
* 仪表盘卡片骨架屏
*/
function DashboardCardSkeleton() {
const theme = useTheme();
const borderColor = alpha(theme.palette.divider, 0.5);
return (
<Box
sx={{
borderRadius: 4,
border: '1px solid',
borderColor,
p: 2.5,
height: 100,
}}
>
<Stack direction="row" justifyContent="space-between" alignItems="flex-start">
<Stack direction="row" spacing={1.5} alignItems="center">
<Skeleton variant="rounded" width={40} height={40} sx={{ borderRadius: 3 }} />
<Box>
<Skeleton variant="text" width={100} height={20} />
<Skeleton variant="text" width={140} height={14} sx={{ mt: 0.5 }} />
</Box>
</Stack>
<Skeleton variant="circular" width={12} height={12} />
</Stack>
</Box>
);
}
/**
* 工具页面骨架屏
*/
function ToolPageSkeleton() {
return (
<Box sx={{ p: 2.5 }}>
{/* 标题区域 */}
<Skeleton variant="text" width={180} height={28} sx={{ mb: 2 }} />
{/* 输入区域 */}
<Skeleton variant="rounded" width="100%" height={120} sx={{ borderRadius: 3, mb: 2 }} />
{/* 控制栏 */}
<Stack direction="row" spacing={1} sx={{ mb: 2 }}>
<Skeleton variant="rounded" width={100} height={36} sx={{ borderRadius: 2 }} />
<Skeleton variant="rounded" width={80} height={36} sx={{ borderRadius: 2 }} />
<Box sx={{ flex: 1 }} />
<Skeleton variant="rounded" width={90} height={36} sx={{ borderRadius: 2 }} />
</Stack>
{/* 结果区域 */}
<Skeleton variant="rounded" width="100%" height={160} sx={{ borderRadius: 3 }} />
</Box>
);
}
/**
* 页面加载骨架屏
*
* @param props - PageSkeletonProps
* @returns 骨架屏 JSX 元素
*/
export default function PageSkeleton({ variant = 'dashboard' }: PageSkeletonProps) {
if (variant === 'tool') {
return <ToolPageSkeleton />;
}
return (
<Box
sx={{
display: 'grid',
gridTemplateColumns: {
xs: '1fr',
sm: 'repeat(auto-fill, minmax(300px, 1fr))',
},
gridAutoRows: '1fr',
gap: 2,
p: 2,
}}
>
{Array.from({ length: 6 }).map((_, index) => (
<DashboardCardSkeleton key={index} />
))}
</Box>
);
}
PageSkeleton.displayName = 'PageSkeleton';