feat(S9-P7): CSS 端接线为样式底座——11 页 H5 内联组件样式并入 CSS 文件并 link 接线(单一样式真源);PLATFORMS 将 css 列重定义为样式层/交付物;值冲突按 components.css 裁决(令牌/逻辑属性优先),顺带修复 Select 定位与选择列居中两处内联版缺陷

This commit is contained in:
aurora-admin
2026-09-25 04:22:03 +08:00
parent b59247231a
commit f07f38b09d
20 changed files with 2482 additions and 2113 deletions
+199
View File
@@ -4,6 +4,205 @@
## [Unreleased]
### 变更 · CSS 端接线为样式底座:H5 端单一样式真源 | S9-P7
- 103 个组件中 92 个此前已由演示页 `<link>` 消费组件 CSS;本轮把剩余 **11 页**
(Button / Card / Dropdown / EmployeeCard / Input / Modal / Segmented / Select / Table / Tree / TreeTable)
的内联组件样式并入 `frameworks/<Prefix>.css`,演示页改为「markup + link CSS(+ 交互 JS)」,
内联只保留演示脚手架。CSS 端文件自本轮起是组件样式的**唯一权威**,
v1.4.0 遗留的「框架 CSS + 页面内联」双份维护不再需要。
- 值冲突按 components.css 规范层裁决(令牌优先、逻辑属性优先,裁决表见 ROADMAP S9-P7);
接线顺带修复两处内联版渲染缺陷:Select 触发器缺 `position: relative`(caret 此前锚定错误)、
Table / TreeTable 选择列未按契约居中。
- 移动端 47/47 此前已全部接线,本轮未改动。
- 全局导入形态随本轮重建刷新:`dist/tokens/tokens.css` + `dist/components/index.css`
(103 组件聚合,令牌之后引入即可);单组件 = `dist/components/<slug>.css`。
PLATFORMS.md 已把 `css` 列重定义为「样式层/交付物」。
### 新增 · 代码块 JS↔TS 切换 + 逐端专属内容齐备 + 组合场景 | S10
> 用户反馈三点:① 代码块上方的切换器与顶栏技术栈选择器重复,且切出来的内容**实际一模一样**;
> ② 不同组件讲的内容雷同;③ 预览「表现得不好」,希望能看到组件**配合**展示(卡片外壳、登录样例)。
> 本轮把三条都落到可验证产物上。
- **代码块切换器改为 JS ↔ TS**(`site/app.js` 的 `codeForms`):端由顶栏决定,
块内只在该端的 JavaScript / TypeScript 两种写法之间切换。原先的四端 tab 与顶栏功能重复
(实测 `button/react` 页面上重复出现 5 组同样的 tab)。
H5 / CSS 端交付静态标记与类名,没有可标注的类型面,故只给单一形态、不显示切换器。
- **597 段 TypeScript 形态**(`site/examples/*.json` 的 `code.tsx` / `code.vue3ts` / `code.vue2ts`,
199 示例 × 3 端):由 `tools/gen-ts-variants.mjs` 生成,原则是**只标注、不重构**——
在既有 JS 片段上插入类型标注与泛型参数,不移动、不重排任何结构。
首版曾尝试把同构标签提炼成「类型化规格数组 + 遍历渲染」,产出更"TS 味",
但实测生成了大量坏代码(`return (const cities = …)`、缺闭合标签的 Vue 模板、`Vue.extend({ … };` 少括号),
且**全部通过了原门禁**——判据只查结构性规则,查不出「代码结构被破坏」。
因此新增 `tools/check-ts-quality.mjs`:对 597 段做**真实编译**(esbuild 验 tsx 与 script 段、
vue-template-compiler 验 Vue 2 模板),当前 0 失败。
- **逐端专属内容 515 份齐备**(`site/end-content/<slug>.<end>.json`,103 组件 × 5 端):
此前只有 197 份,缺的时候页面回退显示同一句「本端的专属用法说明尚未提供」——
这正是「不同组件内容雷同」的直接来源。缺额由 `tools/gen-end-content.mjs` 从事实包补齐,
取料只认该端实现源码解析出的 API(`consumedApi`),不引入契约 `dims`(那是设计词汇层)。
- **组合场景 103 份**(`site/scenes/<slug>.json` + 预览产物 `site/scenes/<slug>.html`):
组件页新增「组合场景」一节,讲该组件与别的组件**配合**出现的形态(表单卡片里的字段、
列表页卡片与工具条、工具条触发的确认流、详情卡片里的内容等)。
门禁 `tools/verify-scenes.mjs` 的第一条就是**组件必须是场景主角**:
`markup.html` 必须用到该组件自己 CSS 里的类名——直接把「外面做卡片、主要部分仍是该组件」编码成判据。
协作者取自组件族的真实耦合关系,外壳类 `ksc-*` 与四端标记由 `tools/gen-scenes.mjs` 生成。
### 修复 · 非 H5 端的示例预览整片 403(路径基准错误)
`site/app.js` 的 `endPreviewSrc` 把逐端预渲染产物的地址写成 `../end-preview/<slug>.<end>.html`,
在 `/site/` 基址下解析到仓库根 `/end-preview/`,而产物实际在 `site/end-preview/`——
实测 `button/react` 页 5 个示例 iframe **全部 403**,只拿到错误页(body 长度 93)。
产物本身没问题:`frameworks/` 部署在站点上一级,而 `end-preview/` 在 `site/` 内部,
两者基准不同,不能照抄同一个前缀。改为相对站点根的 `end-preview/…`。
### 修复 · 逐端预览渲染的是空组件(预览「表现不好」的根因)
`tools/build-end-preview.mjs` 只给开关型/数据型组件传初始 props,纯展示组件因此渲染成空壳:
Button 的产物是 `<button class="btn btn-default btn-md"><span class="btn-label"></span></button>`,
305 份产物里 **68 份文本为空、79 份不足 6 字符**——示例卡片里看到的就是一个没有文字的按钮。
修法:从 `site/examples/<slug>.json` 的**第一个固化的示例**反推该端的真实初始 props
(只取字符串字面量 / 裸布尔 / 数字,`{表达式}` 与数组对象型 prop 一律跳过,
避免把字符串塞进 `data` 导致 `nodes.forEach is not a function`)。
`button.react` 的产物由空壳变为「主按钮(点击切加载态)」。
### 修复 · 组件页在 h5 端请求了不存在的 end-content 文件
`endKey()` 直接把路由端名拼进文件名,h5 页会去取 `button.h5.json`(磁盘上是 `button.html.json`),
404 后长期走兜底文案——实测 `verify-site-routes` 抓到 37 条控制台报错。
改为经 `END_IMPL_KIND` 映射(它本就是「端 → 该端实现文件键」的定义)。
### 修复 · 若干门禁假红与真缺陷(都是本轮实测发现的)
- `tools/verify-component-page.mjs`:示例代码断言原本假定「代码块是四端 tab」,
已改为断言**只出现本端的 JS/TS 形态**、切换器不出现别的端名、TS 形态确实含类型标注;
另外补了强缓存清理(示例正文用 `force-cache` 取,产物重写后门禁会拿到上一版而假红)。
- `tools/verify-examples.mjs`:新增两条判据——Vue 2 模板**根元素带 `v-for`** 会编译失败
(`Cannot use v-for on stateful component root element`,`alert-ex-2` 实例已修)、
TS 专属标记的识别补上 `Record<…>` 与 `JSX.Element`(原判据只认 `: void|string|…`,把合法写法判成「无标记」)。
- `site/logger.js`:不再把浏览器对 ResizeObserver 的提示(`loop completed with undelivered notifications`)
记为页面错误——它没有 error 对象、不影响渲染,而本站示例/场景 iframe 正是靠 ResizeObserver
做高度自适应,这条噪声会随帧数线性增长(实测 37 条)并淹没真实报错。
- `site/style.css`:组合场景代码区补深底浅字(原先继承默认黑字,在深底上对比度 1.04:1)、
补 `overflow: auto`(320px 下顶出整页 `overflow=263px`);端标识胶囊 `.ex-end` 补独立配色。
- `site/app.js`:end-content 异步渲染后补跑表格包裹(`.kole-doc-table`)——
该节走自己的回调、不在既有的两处刷新点上,实测导致「所有 table 都被包裹」这条**间歇失败**。
- `.dockerignore`:排除 `site/end-content/_facts`(4.7MB 构建期事实包,站点从不 fetch 它,
且内嵌 `frameworks/` 源码全文)。内容文件 `site/end-content/*.json` 照常发布。
### 验证
| 门禁 | 结果 |
|---|---|
| PC 回归 `tools/run-regression.mjs` | **100%(1464/1464,103 页)· 连跑八次一致** |
| 移动端回归 | 100%(807/807,47 页) |
| `verify:examples --require-ts` | 15 项通过(199 示例 / 796 片段) |
| `verify:scenes` | 9 项通过(103 份场景) |
| `verify:end-content` | 8 项通过(515 份内容) |
| `check-ts-quality`(真实编译) | 597 段 · 0 失败 |
| `verify-component-page` | 110 项通过(连跑 4 次一致) |
| `verify:i18n` / `verify:theme` / `verify:site-routes` / `smoke:site` / `verify:playground` / `verify:nav` / `verify:templates` / `verify:api-docs` / `verify:isolation` | 全部通过 |
| 零运行时依赖 | `zero-dep OK` |
### 修复 · 组件页「调用代码」是空壳(生成器兜底 → 真实三端调用代码)|ROADMAP S9-P6
> 103 个组件页此前展示的 jsx / vue3 / vue2 代码块,大量是生成器兜底的零信息量骨架:
> 例如 icon 页 7 个使用场景的三种端代码**逐字完全相同**,都只有
> `import { KoleIcon } from 'kole-ui/react';` 加一句 `<KoleIcon />`。
> 根因不在文档层:演示页把真实用法写在内联脚本里(`fill('row-size', TIERS.map(...))`),
> 而构建期生成器只读静态标记,于是走「策略 3」兜底输出最小骨架;门禁只校验「片段非空 + prop 可溯源」——
> **空话成了唯一永不失败的解**。
- **修复**:新增固化层。`site/examples/<slug>.json` 顶层带 `curated: true` 时,`precompute.mjs`
保留其 `code` / `source` / `notes`,预览层(`html` / `preview`)仍以本次生成为准(演示页改结构不会让产物失真)。
103 个组件的 199 个示例、597 段三端片段改写为可照抄的真实调用,逐条依据演示页脚本的实参,
`notes` 记录「文件:行 + 实参」出处。
- **新增门禁**:`npm run verify:examples` 由 9 条增至 **13 条** —— 同组件同端片段不得跨示例逐字重复;
有 props/slots 的组件不得交零属性无内容骨架;`source` 不得是生成器兜底态 `api-derived`;
Vue2 片段必须是可编译形态(模板恰好一个根元素、无 `<template v-for>` / `v-model:arg`)。
另支持 `--only=slug1,slug2` 分片校验;失败详情带总数,避免前序组件的条目把后续的挤出显示。
- **判据修正**:`contract.dims` 不再作为 prop 来源。实测它是设计词汇层 —— `state` 出现在 35 个组件里
只有 4 个实现消费、`feature` 10/2、`action` / `scan` / `layout` / `selection` 全 0 消费。
当 prop 源会放行实现根本不接收的属性(即「照抄却不生效」的假用法);prop 现须能指到
`api.props` 或组件源码里的标识符。据此修正了 2 个组件:`enhancedtabnav`(去掉 `state`/`feature`)、
`pagetransition`(去掉 `effect`/`direction`,并去掉与组件内部工具栏重复的渲染)。
- **变异验证**:同一份数据在旧门禁下 `exit 0`(9 checks 全过)、新门禁下 `exit 1`,证明新断言确实在抓该缺陷;
Vue2 单根断言用「往模板插入兄弟元素」实测变红(报 `vue2 模板根元素 2 个`),随后按 md5 逐字节还原比对。
- **验收**:`node tools/verify-examples.mjs --verbose` → `13 checks passed(199 个示例 / 796 个片段)`;
退化统计由「跨示例重复 150 / 零属性空壳 327 / api-derived 兜底 130」全部归零;
重建站点后 `site/data.json` 内嵌新片段 199 处、`api-derived` 残留 0,固化标记 103/103 存活,
抽样文件 md5 与构建前逐字节一致。
- **新增规格文档** `EXAMPLES-CURATION.md`:固化产物的字段边界、事实源、三端写法与硬规则。
- **遗留待决**:`逐示例片段固化与待决事项.md`(D1–D6)。
### 修复 · 图标预览页尺寸档(`site/icon-preview.html`)|ROADMAP S9-P4
> 该页自 2026-09-20 上线起,**尺寸档四个按钮全是坏的**:点击只改 SVG 的 `width`/`height` 属性,
> 而 `.ip-cell .glyph svg { width: 1em; height: 1em }` 是作者样式表规则,按 CSS 层叠压过表现属性 ——
> 四档一律渲染成 `.glyph` 的 `font-size`(实测恒为 16px)。用户可见症状:点 24 / 32 毫无反应。
- **修复**:`.ip-cell .glyph svg` 去掉写死的 `width`/`height`,只留 `display: block`,
尺寸交给 SVG 属性驱动(与组件页图标集合区同一手法)。
- **新增门禁** `tools/verify-icon-preview.mjs`(`npm run verify:icon-preview`,**26 条断言**):
该页此前**没有任何功能门禁**(仅 `pack-deploy.mjs` 提过它),这正是缺陷存活三天的原因。
核心判据是**实测渲染宽度**(`getBoundingClientRect` 与属性值同时校验)——旧判据只断言
「按钮有响应 / 属性已改 / 无控制台错误」,按钮确实响应了、属性也确实改了,因此漏过。
另含搜索收窄 / 仅线性(1304,与组件页同源)/ 剪贴板复制 / 暗色无白底残留 / 0 个 4xx。
- **变异验证**(证明门禁有区分力):把 CSS 还原成修复前形态重跑 → `尺寸档 20/24/32 FAIL
—— 属性改了但渲染尺寸没跟随`,退出码 1;16 档仍通过(恰好与 1em 的 16px 重合,正是原缺陷的形态)。
- **验收**:`npm run verify:icon-preview` → `OK — all checks passed`(四档 attr 与 rendered 均 = 16/20/24/32)。
### 文档站 · icon 组件页补「图标集合」区(对齐 Element 图标页形态)
> 起因:用户点名 `element.eleme.cn/#/zh-CN/component/icon` ——「会显示组件用法和每个组件样式的展示」。
> 实测该页两节:**使用方法**(用法示例)+ **图标集合**(全部图标网格,每格图形 + 名字);
> 本站 icon 组件页此前只有前者(7 段用法示例),图标全集要跳去独立工具页 `site/icon-preview.html` 才看得到。
- **新增「图标集合」区**(仅 icon 组件页,其余 102 页不受影响):工具条(搜索 / 尺寸 16·20·24·32 /
仅线性 / 实时计数)+ 13 个分组折叠网格,**全部 2576 个图标**,每格渲染真实 SVG 并标注图标名。
- **交互**:点击复制图标名、Shift + 点击复制内联 SVG(判据与独立预览页同源,实测「仅线性」
两处计数一致:1304 / 2576);搜索命中实时收窄并自动展开命中分组;空结果给提示而非空白。
- **数据链路**:`site/icons.json`(名字/分组,52KB)+ `.design_library/kole-ui/icons/registry.json`
(路径数据 708KB,进入视口才取)。实测全量 2576 格建 DOM 约 75ms、布局 90ms、堆 10.7MB,
故不做虚拟滚动;折叠组浏览器整块跳过布局(实测 3ms)。非 icon 页实测 **0 次**图标数据请求。
- **降级**:路径数据取不到时给统一失败态(计数条与区块主体同一说法),页面其余章节完好 ——
实测踩到过「计数条说加载失败、主体停在『加载中…』」的自相矛盾,已修并纳入门禁。
- **门禁扩容**:`verify-component-page.mjs` 新增 28 条图标集合断言(全量渲染数 = icons.json 的
names 长度、每格有真实 path、点击复制读**剪贴板**、尺寸档读**实测渲染宽度**、降级路径、其它页零请求),
总断言 79 → **107 条**;`verify-theme.mjs` / `verify-dark.mjs` 的对比度路由清单加入
`/site/component/icon`(实测该区占探针 600 节点预算里 524 个,是站点文本最密的一块)。
- **实测发现并登记**:`site/icon-preview.html` 的尺寸档按钮自上线起就是坏的(CSS `width: 1em`
压过 SVG 的 width 属性,四档全渲染成 16px)→ 已追加 ROADMAP **S9-P4**(含实测数据与修法)。
- **回归**:PC 100%(1464 通过 / 0 失败 / N/A 50,共 1514 条)· 移动端 100%(807 通过 / 0 失败 / N/A 10),
八次连跑一致,0 超时;移动端与既有端实现零污染(`git status` 空)。
### 计划 · S9 PC「组件 × 端」独立页(批次台账 + 单批门禁)
> 起因:用户判断「PC 端的组件内容层几乎都一样,每端都该有组件自己的页面,批数 = 组件 × 端数,
> 一批一批独立来」。本节只交付**计划与判据**,页面渲染逻辑未动。
- **实测坐实问题**:Playwright 对 6 个组件的 4 个端详情页做 DOM 比对 —— 9 个章节里
**7 个四端逐字相同**;预览 iframe 四端**全部**是 `../frameworks/<Prefix>.html`(H5 演示页);
端切换实际只改「代码 tab 默认选中」与「实现资源表行数」。
- **根因**:PC 索引 103 个条目**既无 `ends` 也无逐组件 `files`**(移动端索引两者齐备),
端清单硬编码在 `site/app.js:39` 的 `FW_FILES` —— 数据层不表达端,渲染层只能退化成 tab 切换器。
- **可行性的实测**:React(esbuild + react-dom/server)、Vue 2(vue-template-compiler +
vue-server-renderer)、Vue 3(@vue/compiler-sfc + vue/server-renderer)三条离线预渲染链路
全部跑通,产物类名与 H5 端逐字一致;工具链装在 `.tmp/` 隔离目录,**主仓库零运行时依赖不变**。
- 新增 **批次台账** `tools/lib/pc-end-batches.mjs` → `tools/pc-end-batches.json`:
**618 批 = 103 组件 × 6 端**(可开工 518 / 受阻 100,受阻项全部是 uni-app 端依赖 S7-P26)。
波次按端排(W1 H5 → W2 React → W3 Vue 2 → W4 Vue 3 → W5 CSS → W6 uni-app),
档位按分类排(通用 → 反馈 → 数据录入 → 数据展示 → 导航 → 系统)。
- 新增 **单批门禁** `tools/verify-pc-end-batch.mjs`(`npm run verify:end-batch`):
12 项检查分六组(A 路由与端声明 / B 预览真分端 / C 示例代码逐字 / D 资源只列该端 /
E API 来源可追溯 / F 无跨端串味)。红灯基线实测:`react/button` 6/12,六组件一致。
空集判失败(`--all` 选不到批次时不报假绿)。
- 新增 **`S9-P1` 数据层补端维度 / `S9-P2` 单端渲染管线 / `S9-P3` 逐端内容层分栏** 三个
前置任务包(写入 `ROADMAP.md`),完成后 518 批可按波次逐批推进。
- 交付说明:`S9-PC端独立页批次计划.md`。
- **回归**:PC 1464/1464 = 100%(103 页);`verify:isolation` 31 条全过;`zero-dep OK`。
`site/` / `frameworks/` / `tests/` 零改动。
### 发布脱敏 · 对外产物滤掉基础设施细节(安全)
> 起因:抓一次公网 `/site/m/changelog.html` 就能拿到内网网段、服务器目录布局与部署时序 ——
+6 -2
View File
@@ -14,7 +14,7 @@
| 轴 | 取值 | 决定什么 |
|---|---|---|
| **平台 platform** | `pc` | `mobile` | **组件清单与命名空间**。两端要的组件本来就不一样:PC 是中后台(表格/树/穿梭框/筛选面板),移动端是触屏优先(导航栏/标签栏/动作面板/下拉刷新/滑动单元格)。两套清单**不重叠**(有断言:slug 不得撞名) |
| **端 end** | `css` | `html`(H5 原生) | `jsx`(React) | `vue2` | `vue3` | `uniapp` | **同一组件在某个技术栈里的实现**。同一个组件在若干端上逐端实现,行为与视觉必须一致 |
| **端 end** | `css` | `html`(H5 原生) | `jsx`(React) | `vue2` | `vue3` | `uniapp` | 同一组件在某个技术栈里的实现。其中 **`css` 不是组件框架端,而是样式层/交付物**:它是该组件样式的唯一权威(S9-P7),被 H5 端 `<link>` 消费、被其余端各自打包、并单独作为 `dist/components/<slug>.css` 分发。组件实现端 = `html` | `jsx` | `vue2` | `vue3` | `uniapp`,行为与视觉必须一致;**H5 端契约 = markup + link 组件 CSS(+ 交互 JS)**,内联只允许演示脚手架样式 |
矩阵长这样(✅ = 本次已交付,⬜ = 规划中):
@@ -23,6 +23,10 @@
| **pc**(103 个中后台组件) | ✅ 103 | ✅ 103 | ✅ 103 | ✅ 103 | ✅ 103 | ⬜ **3 / 103 试点**(ROADMAP S7-P26) |
| **mobile**(47 个移动端组件) | ✅ 47 | ✅ 47 | ✅ 47 | ✅ 47 | ✅ 47 | ✅ **47 / 47** |
> **读这张表的 css 列**:它统计的是**样式层交付物**(每组件一份权威样式文件),
> 不是第五种组件框架。全局导入形态 = `dist/tokens/tokens.css` + `dist/components/index.css`
> (103 组件聚合,令牌之后引入即可);单组件导入 = `dist/components/<slug>.css`。
**uni-app 要单独说清楚**:它是一个「端」,不是第三个平台。
- **移动端 × uni-app**(`frameworks-mobile/<Prefix>.uniapp.vue`)→ 目标 `app-plus`(App)/ `mp-weixin`(微信小程序)/ `h5`。
@@ -49,7 +53,7 @@
| 回归报告 | `tests/report.json` | `tests/mobile-report.json` |
| 文档站 | `site/`(SPA + History API 路由) | `site/m/`(**静态页**,不进 PC 路由表) |
| 自包含数据 | `site/data.json`(对外承诺,103) | `site/m/data.mobile.json`(移动端承诺,47 × 6 端源码) |
| 分发产物 | `dist/components|react|vue3|vue2` | `dist/mobile/*`;PC×uni-app → `dist/uniapp-pc/*` |
| 分发产物 | `dist/components/*`(`index.css` = 全局聚合入口,`tokens/` = 令牌三格式)· `dist/react|vue3|vue2` | `dist/mobile/*`;PC×uni-app → `dist/uniapp-pc/*` |
| 构建 | `build-site.ps1` + `tools/build-dist.mjs` | `tools/build-mobile.mjs`(Node,跨平台) |
| 门禁 | `tools/verify-cross-platform.mjs` 等 | `tools/verify-mobile-isolation.mjs` · `tools/verify-uniapp.mjs` · `tools/verify-mobile-docs.mjs` · `tools/verify-mobile-site.mjs` |
+2235 -1820
View File
File diff suppressed because it is too large Load Diff
+8 -10
View File
@@ -5,9 +5,9 @@
white-space: nowrap; font-size: 14px; line-height: 22px;
border-radius: 4px; min-width: 64px; padding: 0 12px;
box-sizing: border-box; transition: background .15s, border-color .15s;
font-family: "PingFang SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif;
}
.btn:focus-visible { outline: 2px solid rgba(47,84,235,0.2); outline-offset: 2px; }
font-family: var(--kole-font-family);
flex-shrink: 0;}
.btn:focus-visible { outline: 2px solid var(--kole-color-focus-ring); outline-offset: 2px; }
.btn-primary { background: var(--kole-color-brand); color: var(--kole-color-text-inverse); }
.btn-primary:hover { background: var(--kole-color-brand-hover); }
@@ -25,13 +25,11 @@
.btn-danger { background: var(--kole-color-error); color: var(--kole-color-text-inverse); }
.btn-danger:hover { filter: brightness(.92); }
.btn-lg { height: 40px; }
.btn-md { height: 32px; }
.btn-sm { height: 24px; }
.btn-lg { height: var(--kole-control-height-large); }
.btn-md { height: var(--kole-control-height-default); }
.btn-sm { height: var(--kole-control-height-small); }
.btn-disabled, .btn:disabled {
background: var(--kole-color-disabled-bg); border-color: transparent; color: var(--kole-color-text-disabled); cursor: not-allowed;
}
.btn-disabled, .btn:disabled { background: var(--kole-color-disabled-bg); border-color: transparent; color: var(--kole-color-text-placeholder); cursor: not-allowed; }
.btn-disabled:hover, .btn:disabled:hover { background: var(--kole-color-disabled-bg); filter: none; }
.btn .btn-icon { flex-shrink: 0; }
@@ -41,5 +39,5 @@
.btn .spinner {
width: 14px; height: 14px; border: 2px solid currentColor; border-top-color: transparent;
border-radius: 50%; animation: kole-btn-spin .6s linear infinite;
}
display: inline-block;}
@keyframes kole-btn-spin { to { transform: rotate(360deg); } }
+3 -42
View File
@@ -6,49 +6,10 @@
<title>Kole UI · Button (H5)</title>
<!-- 复用设计系统 token,保证与组件库一致 -->
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Button.css">
<style>
/* 以下按钮样式对齐 components.css 与 button.json 契约 */
.btn {
display: inline-flex; align-items: center; justify-content: center;
gap: var(--space-4); border: 1px solid transparent; cursor: pointer;
white-space: nowrap; font-size: var(--font-size-body); line-height: var(--line-height-body);
border-radius: var(--radius-base); min-width: 64px; padding: 0 var(--space-12);
flex-shrink: 0; transition: background .15s, border-color .15s;
font-family: var(--font-family); box-sizing: border-box;
}
.btn:focus-visible { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }
.btn-primary { background: var(--color-brand); color: var(--color-text-inverse); }
.btn-primary:hover { background: var(--color-brand-hover); }
.btn-primary:active { background: var(--color-brand-active); }
.btn-default { background: var(--color-bg-card); border-color: var(--color-border); color: var(--color-text-body); }
.btn-default:hover { border-color: var(--color-brand); }
.btn-text { background: transparent; color: var(--color-brand); }
.btn-text:hover { background: var(--color-brand-bg); }
.btn-link { background: transparent; border: none; color: var(--color-brand); min-width: auto; padding: 0; }
.btn-link:hover { background: var(--color-brand-bg); }
.btn-danger { background: var(--color-error); color: var(--color-text-inverse); }
.btn-danger:hover { filter: brightness(.92); }
.btn-lg { height: var(--control-height-large); }
.btn-md { height: var(--control-height-default); }
.btn-sm { height: var(--control-height-small); }
.btn-disabled, .btn:disabled {
background: var(--color-bg-disabled); border-color: transparent;
color: var(--color-text-placeholder); cursor: not-allowed;
}
.btn-disabled:hover, .btn:disabled:hover { background: var(--color-bg-disabled); filter: none; }
/* 加载态:旋转 spinner + 文字 */
.btn.is-loading { cursor: progress; position: relative; }
.btn.is-loading .btn-label { opacity: .65; }
.btn .spinner {
width: 14px; height: 14px; border: 2px solid currentColor; border-top-color: transparent;
border-radius: 50%; animation: btn-spin .6s linear infinite; display: inline-block;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* 演示页布局 */
body { margin: 0; padding: 24px; background: var(--color-bg-page); color: var(--color-text-body);
font-family: var(--font-family); }
/* 演示页布局脚手架 —— 组件样式已并入 Button.css(S9-P7 单一样式真源) */
body { margin: 0; padding: 24px; background: var(--color-bg-page); color: var(--color-text-body); font-family: var(--font-family); }
h1 { font-size: var(--font-size-h1); margin: 0 0 4px; }
.sub { color: var(--color-text-secondary); margin: 0 0 24px; font-size: var(--font-size-caption); }
.group { margin-bottom: 24px; }
+2 -21
View File
@@ -5,31 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Dropdown (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Dropdown.css">
<style>
/* 对齐 组件2.txt Dropdown 规范:项高32px、内边距左右12px、悬停 #F5F7FA、危险 #CF1322、面板圆角6px/阴影中/最小宽120px */
/* 演示页布局脚手架 —— 组件样式已并入 Dropdown.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-dropdown { position: relative; display: inline-block; }
.kole-dropdown-trigger {
border: 1px solid var(--kole-color-border); background: var(--kole-color-card-bg); border-radius: 4px; height: 32px; padding: 0 12px;
cursor: pointer; font-size: 14px; color: var(--kole-color-text-body); display: inline-flex; align-items: center; gap: 4px;
}
.kole-dropdown-trigger:hover { border-color: var(--kole-color-brand); }
.kole-dropdown-panel {
position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; min-width: 120px;
background: var(--kole-color-card-bg); border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); padding: 4px 0;
}
.kole-dropdown-item {
display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 12px; cursor: pointer;
font-size: 14px; color: var(--kole-color-text-body); white-space: nowrap;
}
.kole-dropdown-item:hover { background: var(--kole-color-page-bg); }
.kole-dropdown-item.is-danger { color: var(--kole-color-error); }
.kole-dropdown-item.is-disabled { color: var(--kole-color-text-disabled); cursor: not-allowed; }
.kole-dropdown-item.is-disabled:hover { background: transparent; }
.kole-dropdown-divider { height: 1px; background: var(--kole-color-border-strong); margin: 4px 0; }
</style>
</head>
<body>
+2 -22
View File
@@ -5,33 +5,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · EmployeeCard (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./EmployeeCard.css">
<style>
/* 对齐 组件9.txt EmployeeCard 规范:头像/姓名/工号/部门/职位/状态、悬停快捷操作、标签、可显联系方式、圆角8px/阴影低/内边距16px */
/* 演示页布局脚手架 —— 组件样式已并入 EmployeeCard.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.row { display: flex; flex-wrap: wrap; gap: 16px; }
.kole-emp-card { width: 280px; background: var(--kole-color-card-bg); border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); padding: 16px; position: relative; box-sizing: border-box; }
.kole-emp-top { display: flex; align-items: center; gap: 12px; }
.kole-emp-avatar { width: 48px; height: 48px; border-radius: 50%; background: var(--kole-color-brand-bg); color: var(--kole-color-brand); display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 18px; flex-shrink: 0; overflow: hidden; }
.kole-emp-avatar img { width: 100%; height: 100%; object-fit: cover; }
.kole-emp-name { font-size: 16px; font-weight: 600; color: var(--kole-color-text-title); display: flex; align-items: center; gap: 8px; }
.kole-emp-status { font-size: 12px; padding: 0 6px; border-radius: 2px; line-height: 18px; }
.kole-emp-status.active { background: var(--kole-color-tag-green-bg); color: var(--kole-color-success); }
.kole-emp-status.left { background: var(--kole-color-disabled-bg); color: var(--kole-color-text-secondary); }
.kole-emp-id { font-size: 12px; color: var(--kole-color-text-secondary); margin-top: 2px; }
.kole-emp-meta { margin-top: 12px; font-size: 13px; color: var(--kole-color-text-tertiary); line-height: 22px; }
.kole-emp-tags { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 6px; }
.kole-emp-tag { background: var(--kole-color-brand-bg); color: var(--kole-color-brand); font-size: 12px; padding: 1px 8px; border-radius: 2px; }
.kole-emp-contact { margin-top: 12px; font-size: 13px; color: var(--kole-color-text-tertiary); line-height: 22px; border-top: 1px solid var(--kole-color-border-strong); padding-top: 10px; }
.kole-emp-actions {
position: absolute; top: 12px; right: 12px; display: none; gap: 4px;
background: var(--kole-color-card-bg); border: 1px solid var(--kole-color-border); border-radius: 4px; padding: 2px;
}
.kole-emp-card:hover .kole-emp-actions { display: flex; }
.kole-emp-actions button { border: none; background: none; cursor: pointer; color: var(--kole-color-text-secondary); font-size: 12px; padding: 2px 6px; border-radius: 3px; }
.kole-emp-actions button:hover { color: var(--kole-color-brand); background: var(--kole-color-brand-bg); }
</style>
</head>
<body>
+1 -5
View File
@@ -6,11 +6,7 @@
padding: 0 12px; background: var(--kole-color-card-bg); border: 1px solid var(--kole-color-border);
border-radius: 4px; transition: border-color .15s, box-shadow .15s; box-sizing: border-box;
}
.kole-input input {
border: none; outline: none; background: transparent; font-size: 14px;
color: var(--kole-color-text-body); min-width: 160px; flex: 1;
font-family: "PingFang SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif;
}
.kole-input input { border: none; outline: none; background: transparent; font-size: 14px; color: var(--kole-color-text-body); min-width: 160px; flex: 1; font-family: var(--kole-font-family); }
.kole-input input::placeholder { color: var(--kole-color-text-placeholder); }
.kole-input:focus-within { border-color: var(--kole-color-brand); box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-input.is-error { border-color: var(--kole-color-error); }
+2 -28
View File
@@ -5,36 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Input (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Input.css">
<style>
/* 对齐 components.css 与 input.json 契约 */
/* 演示页布局脚手架 —— 组件样式已并入 Input.css(S9-P7 单一样式真源) */
.field { display: inline-flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
.kole-input {
display: inline-flex; align-items: center; gap: 8px; height: 32px;
padding: 0 12px; background: var(--kole-color-card-bg); border: 1px solid var(--kole-color-border);
border-radius: 4px; transition: border-color .15s, box-shadow .15s; box-sizing: border-box;
}
.kole-input input {
border: none; outline: none; background: transparent; font-size: 14px;
color: var(--kole-color-text-body); min-width: 160px; flex: 1; font-family: var(--font-family);
}
.kole-input input::placeholder { color: var(--kole-color-text-placeholder); }
.kole-input:focus-within { border-color: var(--kole-color-brand); box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-input.is-error { border-color: var(--kole-color-error); }
.kole-input.is-error:focus-within { border-color: var(--kole-color-error); box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-input.is-disabled, .kole-input:disabled { background: var(--kole-color-disabled-bg); border-color: transparent; }
.kole-input.is-disabled input, .kole-input:disabled input { color: var(--kole-color-text-disabled); cursor: not-allowed; }
.kole-input .affix { display: inline-flex; flex-shrink: 0; color: var(--kole-color-text-secondary); align-items: center; }
.kole-input .action {
display: inline-flex; flex-shrink: 0; padding: 0; border: none; background: none;
cursor: pointer; color: var(--kole-color-text-secondary); align-items: center;
}
.kole-input .action:hover { color: var(--kole-color-brand); }
.kole-input-lg { height: 40px; }
.kole-input-sm { height: 24px; }
.kole-input-sm input { font-size: 12px; min-width: 120px; }
.error-text { font-size: 12px; color: var(--kole-color-error); line-height: 20px; }
/* 演示页布局 */
body { margin: 0; padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
+2 -24
View File
@@ -5,34 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Modal (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Modal.css">
<style>
/* 对齐 components.css 与 modal.json 契约 */
/* 演示页布局脚手架 —— 组件样式已并入 Modal.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-mask {
position: fixed; inset: 0; background: rgba(0,0,0,0.45);
display: flex; align-items: center; justify-content: center; z-index: 1000;
}
.kole-modal {
background: var(--kole-color-card-bg); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.12);
display: flex; flex-direction: column; max-width: 90vw;
}
.kole-modal--small { width: 320px; }
.kole-modal--default { width: 480px; }
.kole-modal--large { width: 680px; }
.kole-modal__header {
display: flex; align-items: center; justify-content: space-between;
padding: 16px 24px; font-size: 16px; font-weight: 600; color: var(--kole-color-text-title);
}
.kole-modal__close { border: none; background: none; cursor: pointer; color: var(--kole-color-text-secondary); font-size: 16px; line-height: 1; }
.kole-modal__close:hover { color: var(--kole-color-text-body); }
.kole-modal__body { padding: 0 24px 24px; color: var(--kole-color-text-body); font-size: 14px; line-height: 22px; }
.kole-modal__footer { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 24px 16px; }
.btn-base { border-radius: 4px; padding: 4px 16px; height: 32px; cursor: pointer; font-size: 14px; }
.btn-ghost { border: 1px solid var(--kole-color-border); background: var(--kole-color-card-bg); color: var(--kole-color-text-body); }
.btn-primary { border: 1px solid var(--kole-color-brand); background: var(--kole-color-brand); color: var(--kole-color-text-inverse); }
</style>
</head>
<body>
+2 -13
View File
@@ -5,23 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Segmented (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Segmented.css">
<style>
/* 对齐 组件2.txt Segmented 规范:高32px、选项内边距8px 16px、容器 #F5F7FA、圆角4px、选中白底、禁用 #BFBFBF */
/* 演示页布局脚手架 —— 组件样式已并入 Segmented.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-segmented {
display: inline-flex; align-items: center; background: var(--kole-color-page-bg); border-radius: 4px; padding: 2px;
}
.kole-segmented-item {
height: 28px; padding: 0 16px; display: inline-flex; align-items: center; gap: 6px;
border-radius: 4px; cursor: pointer; font-size: 14px; color: var(--kole-color-text-body); border: none; background: none;
transition: background .15s, color .15s;
}
.kole-segmented-item:hover:not(.is-active):not(.is-disabled) { color: var(--kole-color-brand); }
.kole-segmented-item.is-active { background: var(--kole-color-card-bg); color: var(--kole-color-text-body); box-shadow: 0 1px 2px rgba(0,0,0,0.08); font-weight: 500; }
.kole-segmented-item.is-disabled { color: var(--kole-color-text-disabled); cursor: not-allowed; }
</style>
</head>
<body>
+1 -1
View File
@@ -10,7 +10,7 @@
.kole-select.is-open .kole-select-trigger { border-color: var(--kole-color-brand); box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-select.is-disabled .kole-select-trigger { background: var(--kole-color-disabled-bg); border-color: transparent; color: var(--kole-color-text-disabled); cursor: not-allowed; }
.kole-select-trigger .placeholder { color: var(--kole-color-text-placeholder); }
.kole-select-trigger .caret { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); transition: transform .15s; color: var(--kole-color-text-secondary); }
.kole-select-trigger .caret { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); transition: transform .15s; color: var(--kole-color-text-secondary); pointer-events: none;}
.kole-select.is-open .caret { transform: translateY(-50%) rotate(180deg); }
.kole-select-trigger .tag {
display: inline-flex; align-items: center; gap: 4px; background: var(--kole-color-brand-bg); color: var(--kole-color-brand);
+2 -40
View File
@@ -5,53 +5,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Select (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Select.css">
<style>
/* 对齐 components.css 与 select.json 契约(触发器样式同 Input) */
/* 演示页布局脚手架 —— 组件样式已并入 Select.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.group { margin-bottom: 24px; }
.group h2 { font-size: 16px; margin: 0 0 12px; color: var(--kole-color-text-title); }
.row { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
.kole-select { position: relative; display: inline-block; min-width: 220px; }
.kole-select-trigger {
display: flex; align-items: center; gap: 8px; min-height: 32px; height: auto;
padding: 2px 28px 2px 12px; background: var(--kole-color-card-bg); border: 1px solid var(--kole-color-border);
border-radius: 4px; box-sizing: border-box; cursor: pointer; transition: border-color .15s, box-shadow .15s;
font-size: 14px; color: var(--kole-color-text-body); flex-wrap: wrap;
}
.kole-select-trigger:hover { border-color: var(--kole-color-brand); }
.kole-select.is-open .kole-select-trigger { border-color: var(--kole-color-brand); box-shadow: 0 0 0 2px rgba(47,84,235,0.2); }
.kole-select.is-disabled .kole-select-trigger { background: var(--kole-color-disabled-bg); border-color: transparent; color: var(--kole-color-text-disabled); cursor: not-allowed; }
.kole-select-trigger .placeholder { color: var(--kole-color-text-placeholder); }
.kole-select-trigger .caret { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); transition: transform .15s; color: var(--kole-color-text-secondary); pointer-events: none; }
.kole-select.is-open .caret { transform: translateY(-50%) rotate(180deg); }
.kole-select-trigger .tag {
display: inline-flex; align-items: center; gap: 4px; background: var(--kole-color-brand-bg); color: var(--kole-color-brand);
border-radius: 2px; padding: 1px 6px; font-size: 12px; line-height: 20px;
}
.kole-select-trigger .tag .x { cursor: pointer; }
.kole-select-panel {
position: absolute; z-index: 10; top: calc(100% + 4px); left: 0; right: 0;
background: var(--kole-color-card-bg); border-radius: 4px; box-shadow: 0 4px 16px rgba(0,0,0,0.12);
max-height: 256px; overflow-y: auto; padding: 4px 0;
}
.kole-select-search { padding: 6px 8px; border-bottom: 1px solid var(--kole-color-border-strong); }
.kole-select-search input { width: 100%; box-sizing: border-box; border: 1px solid var(--kole-color-border); border-radius: 4px; padding: 4px 8px; font-size: 13px; outline: none; }
.kole-select-search input:focus { border-color: var(--kole-color-brand); }
.kole-select-group-label { padding: 6px 12px; font-size: 12px; color: var(--kole-color-text-secondary); }
.kole-select-option {
display: flex; align-items: center; gap: 8px; padding: 0 12px; height: 32px; cursor: pointer;
font-size: 14px; color: var(--kole-color-text-body); box-sizing: border-box;
}
.kole-select-option:hover { background: var(--kole-color-page-bg); }
.kole-select-option.is-selected { background: var(--kole-color-brand-bg); color: var(--kole-color-brand); }
.kole-select-option .check { visibility: hidden; margin-left: auto; }
.kole-select-option.is-selected .check { visibility: visible; }
.kole-select-option.is-disabled { color: var(--kole-color-text-disabled); cursor: not-allowed; }
.kole-select-empty { padding: 16px 12px; text-align: center; color: var(--kole-color-text-placeholder); font-size: 13px; }
</style>
</head>
<body>
+7
View File
@@ -26,3 +26,10 @@
border-radius: 50%; animation: kole-tbl-spin .6s linear infinite;
}
@keyframes kole-tbl-spin { to { transform: rotate(360deg); } }
/* —— 以下规则自 Table.html 内联样式并入(S9-P7 单一样式真源)—— */
.kole-table th.align-right, .kole-table td.align-right { text-align: right; }
.kole-table .link-btn { color: var(--kole-color-brand); background: none; border: none; cursor: pointer; font-size: 14px; padding: 0; }
.kole-table .link-btn + .link-btn { margin-left: 8px; }
.kole-table .link-btn.danger { color: var(--kole-color-error); }
html.kole-dark .kole-table .loading-mask { background: rgba(20,22,28,0.7); }
+2 -32
View File
@@ -5,42 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Table (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Table.css">
<style>
/* 对齐 components.css 与 table.json 契约 */
/* 演示页布局脚手架 —— 组件样式已并入 Table.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-table { width: 100%; border: 1px solid var(--kole-color-border); border-radius: 8px; overflow: hidden; background: var(--kole-color-card-bg); position: relative; }
.kole-table table { width: 100%; border-collapse: collapse; font-size: 14px; color: var(--kole-color-text-body); }
.kole-table thead th {
background: var(--kole-color-table-header-bg); color: var(--kole-color-text-body); font-weight: 600; height: 48px; text-align: left;
padding: 0 16px; border-bottom: 1px solid var(--kole-color-border); white-space: nowrap;
}
.kole-table tbody td { height: 48px; padding: 0 16px; border-bottom: 1px solid var(--kole-color-border); text-align: left; }
.kole-table tbody tr:last-child td { border-bottom: none; }
.kole-table tbody tr:hover { background: var(--kole-color-page-bg); }
.kole-table tbody tr.is-selected { background: var(--kole-color-brand-bg); }
.kole-table th.align-right, .kole-table td.align-right { text-align: right; }
.kole-table .sortable { cursor: pointer; user-select: none; }
.kole-table .sort-ind { color: var(--kole-color-text-placeholder); margin-left: 4px; }
.kole-table .sort-ind.active { color: var(--kole-color-brand); }
.kole-table .col-action { text-align: right; }
.kole-table .link-btn { color: var(--kole-color-brand); background: none; border: none; cursor: pointer; font-size: 14px; padding: 0; }
.kole-table .link-btn + .link-btn { margin-left: 8px; }
.kole-table .link-btn.danger { color: var(--kole-color-error); }
.kole-table .checkbox { width: 16px; height: 16px; cursor: pointer; vertical-align: middle; }
.kole-table .empty { padding: 48px 16px; text-align: center; color: var(--kole-color-text-placeholder); font-size: 14px; }
.kole-table .loading-mask {
position: absolute; inset: 0; background: rgba(255,255,255,0.7); display: flex;
align-items: center; justify-content: center; z-index: 2;
}
html.kole-dark .kole-table .loading-mask { background: rgba(20,22,28,0.7); }
.kole-table .spinner {
width: 20px; height: 20px; border: 2px solid var(--kole-color-brand); border-top-color: transparent;
border-radius: 50%; animation: kole-tbl-spin .6s linear infinite;
}
@keyframes kole-tbl-spin { to { transform: rotate(360deg); } }
</style>
</head>
<body>
+1 -2
View File
@@ -2,8 +2,7 @@
.kole-tree { min-width: 240px; border: 1px solid var(--kole-color-border); border-radius: 8px; padding: 4px; background: var(--kole-color-card-bg); }
.kole-tree-node {
display: flex; align-items: center; gap: 4px; height: 32px; border-radius: 4px;
cursor: pointer; user-select: none; font-size: 14px; color: var(--kole-color-text-body); padding-inline-end: 8px;
}
cursor: pointer; user-select: none; font-size: 14px; color: var(--kole-color-text-body); padding-inline-end: 8px; }
.kole-tree-node:hover { background: var(--kole-color-page-bg); }
.kole-tree-node.is-selected { background: var(--kole-color-brand-bg); color: var(--kole-color-brand); }
.kole-tree-arrow {
+2 -17
View File
@@ -5,27 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Tree (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Tree.css">
<style>
/* 对齐 组件2.txt Tree 规范:节点高32px、缩进16px/级、箭头12px、选中 #F0F5FF/#2F54EB */
/* 演示页布局脚手架 —— 组件样式已并入 Tree.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-tree { min-width: 240px; border: 1px solid var(--kole-color-border); border-radius: 8px; padding: 4px; background: var(--kole-color-card-bg); }
.kole-tree-node {
display: flex; align-items: center; gap: 4px; height: 32px; border-radius: 4px;
cursor: pointer; user-select: none; font-size: 14px; color: var(--kole-color-text-body); padding-right: 8px;
}
.kole-tree-node:hover { background: var(--kole-color-page-bg); }
.kole-tree-node.is-selected { background: var(--kole-color-brand-bg); color: var(--kole-color-brand); }
.kole-tree-arrow {
display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px;
font-size: 12px; color: var(--kole-color-text-secondary); transition: transform .15s; flex-shrink: 0;
}
.kole-tree-arrow.is-open { transform: rotate(90deg); }
.kole-tree-arrow-placeholder { width: 16px; flex-shrink: 0; }
.kole-tree-check { width: 14px; height: 14px; flex-shrink: 0; cursor: pointer; }
.kole-tree-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
</style>
</head>
<body>
+2 -17
View File
@@ -5,27 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · TreeTable (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./TreeTable.css">
<style>
/* 对齐 组件7.txt TreeTable 规范:层级缩进16px/级、展开箭头、父级汇总、选择联动 */
/* 演示页布局脚手架 —— 组件样式已并入 TreeTable.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.kole-tt { width: 100%; border: 1px solid var(--kole-color-border); border-radius: 8px; overflow: hidden; background: var(--kole-color-card-bg); }
.kole-tt table { width: 100%; border-collapse: collapse; font-size: 14px; color: var(--kole-color-text-body); }
.kole-tt thead th { background: var(--kole-color-table-header-bg); color: var(--kole-color-text-body); font-weight: 600; height: 48px; text-align: left; padding: 0 16px; border-bottom: 1px solid var(--kole-color-border); white-space: nowrap; }
.kole-tt tbody td { height: 48px; padding: 0 16px; border-bottom: 1px solid var(--kole-color-border); text-align: left; }
.kole-tt tbody tr:last-child td { border-bottom: none; }
.kole-tt tbody tr:hover { background: var(--kole-color-page-bg); }
.kole-tt tbody tr.is-selected { background: var(--kole-color-brand-bg); }
.kole-tt .align-right { text-align: right; }
.kole-tt .tree-cell { display: flex; align-items: center; gap: 4px; }
.kole-tt .tt-arrow { width: 16px; height: 16px; font-size: 12px; color: var(--kole-color-text-secondary); transition: transform .15s; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.kole-tt .tt-arrow.is-open { transform: rotate(90deg); }
.kole-tt .tt-arrow-placeholder { width: 16px; flex-shrink: 0; }
.kole-tt .tt-check { width: 14px; height: 14px; cursor: pointer; }
.kole-tt .tt-summary { color: var(--kole-color-text-secondary); font-size: 12px; margin-left: 6px; }
.kole-tt tfoot td { height: 44px; padding: 0 16px; background: var(--kole-color-table-header-bg); font-weight: 600; border-top: 1px solid var(--kole-color-border); }
</style>
</head>
<body>
+2 -16
View File
@@ -5,27 +5,13 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kole UI · Card (H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui/colors_and_type.css">
<link rel="stylesheet" href="./Card.css">
<style>
/* 对齐 components.css 与 card.json 契约 */
/* 演示页布局脚手架 —— 组件样式已并入 Card.css(S9-P7 单一样式真源) */
.demo { padding: 24px; background: var(--kole-color-page-bg); color: var(--kole-color-text-body); font-family: var(--font-family); }
h1 { font-size: 20px; margin: 0 0 4px; }
.sub { color: var(--kole-color-text-secondary); margin: 0 0 24px; font-size: 12px; }
.row { display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-start; }
.kole-card {
background: var(--kole-color-card-bg); border-radius: 8px; box-sizing: border-box;
min-width: 280px; max-width: 360px;
}
.kole-card--bordered { border: 1px solid var(--kole-color-border); }
.kole-card--shadowed { box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.kole-card__header {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
font-weight: 600; color: var(--kole-color-text-title);
}
.kole-card__title { font-size: 16px; }
.kole-card__extra { color: var(--kole-color-brand); font-size: 14px; cursor: pointer; }
.kole-card__body { color: var(--kole-color-text-body); font-size: 14px; line-height: 22px; }
.kole-card__actions { display: flex; justify-content: flex-end; gap: 8px; }
</style>
</head>
<body>
+1 -1
View File
@@ -1,5 +1,5 @@
{
"generated": "2026-09-22 23:30:01",
"generated": "2026-09-24 20:15:32",
"version": "1.0.0",
"pages": 103,
"pagesAllPass": 103,