收口前端平台组件库能力

新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
This commit is contained in:
2026-06-10 10:24:18 +08:00
parent a4ee6ff698
commit 1ad25e30f8
226 changed files with 23364 additions and 7825 deletions

View File

@@ -0,0 +1,74 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import { expect, test } from 'vitest';
import { PlatformStatGrid } from './PlatformStatGrid';
test('renders platform stat cards with value-first layout', () => {
render(
<PlatformStatGrid
items={[
{ label: '图案组', value: 35 },
{ label: '卡片', value: 95 },
{ label: '状态', value: 'ready' },
]}
/>,
);
const value = screen.getByText('35');
const label = screen.getByText('图案组');
const grid = value.closest('div')?.parentElement?.parentElement;
const card = value.parentElement;
expect(grid?.className).toContain('grid-cols-3');
expect(grid?.className).toContain('text-center');
expect(card?.className).toContain('bg-white/76');
expect(value.className).toContain('text-lg');
expect(label.className).toContain('tracking-[0.14em]');
});
test('supports label-first plain cards and responsive four-column grid', () => {
render(
<PlatformStatGrid
items={[
{ label: '需要消除', value: '12 次' },
{ label: '总物品数', value: '36 件' },
]}
columns="twoToFour"
order="labelFirst"
surface="plain"
itemClassName={(item) =>
item.label === '总物品数' ? 'total-item-card' : null
}
/>,
);
const label = screen.getByText('需要消除');
const value = screen.getByText('12 次');
const grid = label.closest('div')?.parentElement?.parentElement;
const totalCard = screen.getByText('总物品数').parentElement;
expect(grid?.className).toContain('grid-cols-2');
expect(grid?.className).toContain('sm:grid-cols-4');
expect(label.nextElementSibling).toBe(value);
expect(totalCard?.className).toContain('border');
expect(totalCard?.className).toContain('total-item-card');
});
test('supports compact stat chips without labels', () => {
render(
<PlatformStatGrid
items={[{ value: '6 个' }, { value: '可发布' }]}
columns="two"
density="compact"
/>,
);
const chip = screen.getByText('6 个');
const card = chip.parentElement;
expect(card?.className).toContain('py-2');
expect(chip.className).toContain('text-sm');
expect(screen.queryByText('状态')).toBeNull();
});