Files
aurora-admin/frameworks-mobile/Popover.html
T
aurora-admin f1fbfc2ddb
Regression / regression (push) Canceled after 0s
feat(品牌标识): 几何 K 图标(favicon/顶栏标记/theme-color) + 并行会话成果入库
## 品牌标识(本次会话)

起因:品牌此前没有任何图形标识 —— 唯一 favicon 是内联 data-URI 里的字母「A」,
那是 v2.0.0「Aurora Admin → Kole UI」改名漏掉的一处(PC 顶栏也是「A」,
移动端站已是「K」;移动端文档站则完全没有 favicon)。

- 几何:24 网格三个互不接触的笔画(竖 + 两斜),圆头描边;
  描边 2.25 → 16px 标签页尺寸下正好 1.5px = 规范原文「描边1.5px」
- 取色分两套(刻意):favicon 硬编码品牌蓝/白(渲染在浏览器标签栏,不继承 kole-dark);
  顶栏标记走 currentColor(实测暗色下自动转 rgb(20,22,28))
- 新增 theme-color 双条(light #FFFFFF / dark #1C1F26,取 --kole-color-card-bg)
- 修 site/app.js hero 标语 KOLE ADMIN → KOLE UI(改名变形残留)
- 移动端 7 个模板补 favicon(此前计数 0)

验收:门禁 9 条全 OK(site-routing/site-routes/mobile-docs/mobile-site/isolation/
theme/nav/i18n/icons);PC 回归 1464/1464 · 移动端 807/807,各连跑 8 次一致;
两端 favicon 405 字节逐字节一致;PC 站控制台错误 1→0。

## 并行会话成果(本次一并入库)

- 图标系统:2576 图标(TDesign/Element Plus,MIT)+ 11 端注入 + 5 个构建门禁工具
  + IconPreview 预览页 + ICON-SPEC.md 冻结规格
- 移动端平台:47 组件 × 6 端 + 文档站 53 页 + 隔离门禁
- PC 组件:103 个大后台组件 / 组件11 批次
- uni-app:PC 端试点 + 移动端端实现 + 真实编译验证

## 工程

- .gitignore 补 .scratch/ 与 .zcode-preexisting-*.txt(会话中间产物,实测 9.1MB,不入库)
- CHANGELOG 补品牌标识条目
- ROADMAP 登 S8-P4(品牌标识任务包 + og:image/apple-touch-icon 未做部分)
2026-09-21 10:05:48 +08:00

191 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Kole UI Mobile · Popover(H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui-mobile/colors_and_type.css">
<link rel="stylesheet" href="Popover.css">
<style>
body { margin: 0; background: var(--kole-color-page-bg); font-family: var(--kole-font-family); color: var(--kole-color-text-body); }
.demo { max-width: 375px; margin: 0 auto; padding: var(--kole-m-gutter) 0; }
.demo-label { margin: 0; padding: var(--kole-space-12) var(--kole-m-gutter) var(--kole-space-8);
font-size: var(--kole-m-font-size-label); color: var(--kole-color-text-secondary); }
/* 展示舞台:气泡是绝对定位的(贴着触发器),所以舞台只给留白,不加 overflow 裁剪 */
.demo-stage { display: flex; align-items: flex-start; justify-content: center; gap: var(--kole-space-16);
padding: var(--kole-space-64) var(--kole-m-gutter); background: var(--kole-color-card-bg);
border-block: 1px solid var(--kole-color-border); }
.demo-stage--grid { display: grid; grid-template-columns: 1fr 1fr; justify-items: center;
row-gap: var(--kole-space-64); }
.demo-stage--center { justify-content: center; padding: var(--kole-space-64) var(--kole-m-gutter); }
.demo-hint { margin: 0; padding: var(--kole-space-8) var(--kole-m-gutter) 0;
font-size: var(--kole-m-font-size-caption); color: var(--kole-color-text-tertiary); }
.demo-outside { min-height: var(--kole-m-touch-target); padding: 0 var(--kole-m-gutter);
border: 1px dashed var(--kole-color-border-strong); border-radius: var(--kole-radius-base);
background: var(--kole-color-page-bg); color: var(--kole-color-text-secondary);
font-family: inherit; font-size: var(--kole-m-font-size-label); cursor: pointer; touch-action: manipulation; }
.demo-outside:focus-visible { outline: 2px solid var(--kole-color-focus-ring); outline-offset: 2px; }
.demo-block[hidden] { display: none; }
</style>
</head>
<body>
<div class="demo">
<section class="demo-block" data-demo="placements">
<p class="demo-label">四个方向(placement=top / bottom / left / right:气泡永远贴着它自己的触发器)</p>
<div class="demo-stage demo-stage--grid" data-assert="popover-placements">
<div class="kole-m-popover" id="pop-top" data-placement="top" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-top|data-open|true">上方</button>
<div class="kole-m-popover__panel kole-m-popover__panel--top kole-m-popover__panel--arrow"
role="dialog" aria-label="上方气泡">
<p class="kole-m-popover__text">气泡在上方</p>
</div>
</div>
<div class="kole-m-popover" id="pop-bottom" data-placement="bottom" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-bottom|data-open|true">下方</button>
<div class="kole-m-popover__panel kole-m-popover__panel--bottom kole-m-popover__panel--arrow"
role="dialog" aria-label="下方气泡">
<p class="kole-m-popover__text">气泡在下方</p>
</div>
</div>
<div class="kole-m-popover" id="pop-left" data-placement="left" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-left|data-open|true">左侧</button>
<div class="kole-m-popover__panel kole-m-popover__panel--left kole-m-popover__panel--arrow"
role="dialog" aria-label="左侧气泡">
<p class="kole-m-popover__text">气泡在左侧</p>
</div>
</div>
<div class="kole-m-popover" id="pop-right" data-placement="right" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-right|data-open|true">右侧</button>
<div class="kole-m-popover__panel kole-m-popover__panel--right kole-m-popover__panel--arrow"
role="dialog" aria-label="右侧气泡">
<p class="kole-m-popover__text">气泡在右侧</p>
</div>
</div>
</div>
<p class="demo-hint">四个气泡各自相对自己的触发器定位,互不影响;点一下对应按钮即可看到它出现在那一侧。</p>
</section>
<section class="demo-block" data-demo="arrow">
<p class="demo-label">无箭头(arrow=false:小屏上空间紧张时省掉三角,气泡位置不变)</p>
<div class="demo-stage demo-stage--center" data-assert="popover-arrow">
<div class="kole-m-popover" id="pop-noarrow" data-placement="bottom" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-noarrow|data-open|true">无箭头气泡</button>
<div class="kole-m-popover__panel kole-m-popover__panel--bottom" role="dialog" aria-label="无箭头气泡">
<p class="kole-m-popover__text">不带箭头,仅靠位置表达归属</p>
</div>
</div>
</div>
</section>
<section class="demo-block" data-demo="title">
<p class="demo-label">带标题(title + text:标题给出这条气泡在说什么,正文再补一句)</p>
<div class="demo-stage demo-stage--center" data-assert="popover-title">
<div class="kole-m-popover" id="pop-title" data-placement="bottom" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-sets-attr:#pop-title|data-open|true">运费说明</button>
<div class="kole-m-popover__panel kole-m-popover__panel--bottom kole-m-popover__panel--arrow"
role="dialog" aria-label="运费说明">
<p class="kole-m-popover__title">运费规则</p>
<p class="kole-m-popover__text">单笔满 99 元免运费,偏远地区不参与。</p>
</div>
</div>
</div>
</section>
<section class="demo-block" data-demo="outside">
<p class="demo-label">点击外部关闭(气泡没有遮罩可依赖:落点在气泡与触发器之外时收起)</p>
<div class="demo-stage demo-stage--center" data-assert="popover-outside">
<div class="kole-m-popover" id="pop-outside" data-placement="bottom" data-open="false">
<button class="kole-m-popover__trigger" type="button" aria-expanded="false" aria-haspopup="dialog"
data-behavior="click-toggles-class:#pop-outside-panel|is-open">先点我展开</button>
<div class="kole-m-popover__panel kole-m-popover__panel--bottom kole-m-popover__panel--arrow"
id="pop-outside-panel" role="dialog" aria-label="待关闭的气泡">
<p class="kole-m-popover__text">展开后,再点下面的「外部区域」即可收起</p>
</div>
</div>
<div class="kole-m-popover" id="pop-outside-open" data-placement="bottom" data-open="true">
<button class="kole-m-popover__trigger" type="button" aria-expanded="true" aria-haspopup="dialog">已展开的气泡</button>
<div class="kole-m-popover__panel kole-m-popover__panel--bottom kole-m-popover__panel--arrow is-open"
role="dialog" aria-label="已展开的气泡">
<p class="kole-m-popover__text">这条默认就是展开的,用来对照「点外部后是否真的收起」</p>
</div>
</div>
</div>
<p class="demo-hint">
<button class="demo-outside" type="button"
data-behavior="click-sets-attr:#pop-outside-open|data-open|false">外部区域(点这里收起)</button>
</p>
</section>
</div>
<script>
/* 演示页交互:触发器切换自己的气泡(is-open + data-open + aria-expanded 同一函数写入);
点击「气泡与触发器之外」的落点收起 —— 气泡没有遮罩可依赖,所以靠 document 上的
pointerdown 判定落点,这与生产端各框架实现同口径。 */
(function () {
function setOpen(root, open) {
var panel = root.querySelector('.kole-m-popover__panel');
var trig = root.querySelector('.kole-m-popover__trigger');
root.setAttribute('data-open', open ? 'true' : 'false');
if (panel) panel.classList.toggle('is-open', open);
if (trig) trig.setAttribute('aria-expanded', open ? 'true' : 'false');
}
function rootOf(el) {
return el.closest ? el.closest('.kole-m-popover') : null;
}
document.querySelectorAll('.kole-m-popover').forEach(function (root) {
var trig = root.querySelector('.kole-m-popover__trigger');
if (!trig) return;
trig.addEventListener('click', function () {
setOpen(root, root.getAttribute('data-open') !== 'true');
});
});
document.addEventListener('pointerdown', function (e) {
var inRoot = rootOf(e.target);
document.querySelectorAll('.kole-m-popover').forEach(function (root) {
if (root === inRoot) return;
if (root.getAttribute('data-open') === 'true') setOpen(root, false);
});
});
/* demo-outside 是触发器之外的落点:click 里也收一次,保证键盘用户能用 */
document.querySelectorAll('.demo-outside').forEach(function (btn) {
btn.addEventListener('click', function () {
document.querySelectorAll('.kole-m-popover[data-open="true"]').forEach(function (root) {
setOpen(root, false);
});
});
});
})();
</script>
<script>
/* ?demo=<id> → 只显示该演示块(文档站按块预览用;无参数时全部显示,测试与回归走无参数路径) */
(function () {
var id = new URLSearchParams(location.search).get('demo');
if (!id) return;
var blocks = Array.prototype.slice.call(document.querySelectorAll('.demo-block'));
var hit = false;
blocks.forEach(function (b) {
var on = b.getAttribute('data-demo') === id;
if (on) hit = true;
b.hidden = !on;
});
if (!hit) { blocks.forEach(function (b) { b.hidden = false; }); return; }
document.body.classList.add('demo-single');
var demoBox = document.querySelector('.demo');
if (demoBox) demoBox.style.minHeight = 'auto';
blocks.forEach(function (b) {
var label = b.querySelector('.demo-label');
if (label && !b.hidden) label.hidden = true;
});
})();
</script>
</body>
</html>