# PSJ Glass UI Design System

这是一个独立的静态设计系统网站，用来沉淀后续产品统一的视觉语言。

## 文件结构

```text
psj-ui-system/
├── index.html      # 设计规范首页
├── cheatsheet.html # 独立速查页
├── styles.css      # 字体、tokens、玻璃材质、组件、动效、响应式规则
├── app.js          # 主题、导航、搜索和分类筛选
├── demos.js        # 12 个布局、6 个 Token、18 个 SVG 独立演示
├── demos.css       # 演示专用样式，避免影响产品组件
├── materials.css   # 全站统一材质：清透 / 磨砂 / 高覆盖、深色模式
├── components.js   # 56 个原生控件演示与局部交互
├── components.css  # 控件结构，不混入业务逻辑
├── motion.js       # 51 个按用途设计的动效演示，视区暂停与交互
├── motion.css      # 动效结构和关键帧
├── assets/         # 测评系统冰丝背景、本站二维码
├── reference-components.json # 分类和用途索引
└── fonts/          # HarmonyOS Sans SC 字体文件
```

## 复用方式

1. 新项目先引入 `styles.css`（基础）和 `materials.css`（统一材质），保持 `fonts` / `assets` 相对路径。
2. 页面中使用 `glass-card`、`glass-panel`、`button`、`field`、`metric-card` 等语义类。
3. 不要在业务页面里随手创建新的颜色、圆角和阴影；新增组件先补状态，再进入业务项目。

## 数据表格（从中转站后台沉淀）

首页 `#table` 与演示页 `cheatsheet.html?q=table` 共用同一个渲染器。只展示虚构数据，不访问中转站 API。

引入 `styles.css`、`components.css`、`materials.css` 与 `components.js` 后：

```js
document.querySelector('#records').innerHTML = PSJComponents.table({
  caption: '项目记录',
  columns: [
    { key: 'name', label: '项目名称' },
    { key: 'amount', label: '费用（元）', numeric: true },
    { key: 'status', label: '状态', status: true },
    { key: 'action', label: '查看详情', action: true },
  ],
  rows: [{ name: '示例项目', amount: '0.092460',
    status: { label: '正常', tone: 'success' }, action: '查看' }],
  emptyText: '暂无记录',
});
document.querySelector('#records').addEventListener('click', event => {
  const button = event.target.closest('[data-table-action]');
  if (button) console.log(button.dataset.tableAction, Number(button.dataset.rowIndex));
});
```

- 使用原生 `table / caption / thead / tbody / th scope="col"`；所有文字值自动转义，不传入 HTML。
- 文本左对齐；`numeric` 列的表头与数据均右对齐、使用等宽数字。金额由调用方格式化，费用推荐六位小数。
- `code: true` 用于请求 ID 等代码值；状态 tone 支持 `success / warning / neutral`，状态同时提供文字。
- 空数组保留表头并显示跨列空状态；容器可键盘聚焦和横向滚动，不将窄屏数据截断。
- 操作通过 `data-table-action` 和当前 `data-row-index` 交给业务层处理；排序或换页后索引对应新传入的 rows。
- `.ui-table`、`.ui-table-scroll`、`.ui-data-table`、`.ui-table-number` 可直接用于 React/Vue 的等价原生表格结构；不依赖演示容器。
- 不把整行变成按钮，不加入业务额度、课程鉴权或真实学生数据。

## 代码原则

- 使用原生 HTML/CSS/JS，便于迁移到 Next、Vue、React 或静态页。
- CSS 按模块注释，方便人工维护。
- 动效必须支持 `prefers-reduced-motion`。
- 玻璃效果不能牺牲文字和表格可读性。
- 共用玻璃底层采用 20px 背景模糊，日间白色覆盖 40%；底部文字说明区同样使用该模糊参数。

## 演示维护

- `demos.js` 的 layouts、tokens、svgBodies 分别维护三类预览。每一项必须有独立实现，不能退回空方块占位。
- 交互在 `initialize` 中绑定到各自演示容器，筛选重建后重新绑定；不调用业务接口。
- SVG 的暂停/重播同时处理 CSS 动画和 SVG 原生动画。进度环和仪表盘提供键盘可操作的数值滑块。
- 断点卡片是列数演示（非完整设备模拟器），可在手机、平板、桌面示意之间切换。
- 组件演示不调用产品 API。上传只展示文件名，保存只演示状态变化；不是业务后端。
- 外层速查卡片不设置 backdrop-filter，防止形成新的 backdrop root，使内部玻璃控件只能模糊一块纯色。
- 字体、图表色板、SVG 插画不强制透明；文字清晰度与图形语义优先于装饰。
- `motion.js` 使用 IntersectionObserver 暂停离屏 CSS 动画，重新筛选时清理观察器和动画帧。
- 本地运行：`python3 -m http.server 4177`，打开 `/cheatsheet.html`；静态校验：`node tests/demos.cjs`。
