From ac5c5cd2331c10ed0cfb8b7f8a62e247eabc138d Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 13:11:29 +0800 Subject: [PATCH] =?UTF-8?q?iter(g92):=20=E5=BE=BD=E6=A0=87=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=95=B0=E5=AD=97=E8=A7=92=E6=A0=87=E4=B8=8E=E7=BA=A2?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 ++++++++ .ua/index.json | 29 +++++++++++++++++++++-------- apps/demo/main.ts | 3 +++ llms-full.txt | 15 +++++++++------ packages/skin/ui/src/badge.ts | 14 ++++++++++++-- packages/skin/ui/src/types.ts | 5 ++++- packages/skin/ui/ua.manifest.json | 27 ++++++++++++++++++++------- packages/skin/ui/ui.css | 15 +++++++++++++++ 8 files changed, 92 insertions(+), 24 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index de58541..3eb5091 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -1092,6 +1092,14 @@ "acceptance": "FormItemProps 新增可选 hint,渲染在控件下方;校验失败时 hint 让位(hidden)只留错误文案,校验通过自动恢复;样式走令牌;文档参数表(formItem 前缀)与演示同步;npm run check 全绿", "notes": "自补:表单可用性;不改 formItem 返回句柄与 form 聚合逻辑", "status": "done" + }, + { + "id": "g92", + "title": "徽标支持数字角标与纯红点", + "motivation": "badge 只能塞一段文字,做「未读 5 条」「99+」「有更新的小红点」时得自己拼 span + 手写样式,红色点还会硬编码颜色绕过令牌", + "acceptance": "BadgeProps 新增 count / max / dot,label 改为可选;count 超过 max(缺省 99)显示 N+,负数归零;dot 渲染 8px 圆点并以 role=img + label 作可访问名;新增样式只消费 --ua-* 令牌;文档与演示(三种形态)同步;npm run check 全绿", + "notes": "自补:组件能力补齐;保持纯展示、无内部状态", + "status": "open" } ] } diff --git a/.ua/index.json b/.ua/index.json index b637e5a..ce1a7a7 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T05:10:23.912Z", + "generatedAt": "2026-10-26T05:11:11.108Z", "repoRoot": ".", "packages": [ { @@ -891,21 +891,34 @@ { "n": "label", "t": "string", - "r": 1, - "d": "徽标文案" + "d": "徽标文案;与 count / dot 三选一,dot 时作可访问名" }, { "n": "variant", "t": "'default' | 'success' | 'warning' | 'danger'", - "d": "语义色;缺省 default", - "df": "default" + "d": "语义色;缺省 default" + }, + { + "n": "count", + "t": "number", + "d": "数字角标:超过 max 显示 N+,负数归零" + }, + { + "n": "max", + "t": "number", + "d": "数字上限;缺省 99" + }, + { + "n": "dot", + "t": "boolean", + "d": "只显示小红点(无文字),role=img + label 作名称" } ], "example": "badge({ label: '成功', variant: 'success' })", "steps": [ - "选择语义色:default 中性、success 成功、warning 警告、danger 危险", - "传入 label 即可,纯展示组件无状态", - "状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button" + "纯状态文案直接传 label,配 variant 定语义色", + "要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+", + "只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」)" ] }, { diff --git a/apps/demo/main.ts b/apps/demo/main.ts index 9d0ce74..7d036ef 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -361,6 +361,9 @@ const content = h( badge({ label: '成功', variant: 'success' }), badge({ label: '警告', variant: 'warning' }), badge({ label: '危险', variant: 'danger' }), + badge({ count: 5, label: '未读' }), + badge({ count: 128, max: 99, label: '未读' }), + badge({ dot: true, label: '有未读消息' }), alert({ message: '信息提示:这是一条 info 提示条。' }), alert({ message: '警告提示:操作可能存在风险。', variant: 'warning' }), h('div', { class: 'row' }, spinner(), spinner({ size: 26 })), diff --git a/llms-full.txt b/llms-full.txt index 4f9b3ea..6945e77 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T05:10:23.912Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T05:11:11.108Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -418,8 +418,11 @@ card({ title: '用户表' }, dataTable({ data, columns })) 参数: -- label(必填):string —— 徽标文案 -- variant(默认 default):'default' | 'success' | 'warning' | 'danger' —— 语义色;缺省 default +- label:string —— 徽标文案;与 count / dot 三选一,dot 时作可访问名 +- variant:'default' | 'success' | 'warning' | 'danger' —— 语义色;缺省 default +- count:number —— 数字角标:超过 max 显示 N+,负数归零 +- max:number —— 数字上限;缺省 99 +- dot:boolean —— 只显示小红点(无文字),role=img + label 作名称 示例: @@ -429,9 +432,9 @@ badge({ label: '成功', variant: 'success' }) 手把手: -1. 选择语义色:default 中性、success 成功、warning 警告、danger 危险 -2. 传入 label 即可,纯展示组件无状态 -3. 状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button +1. 纯状态文案直接传 label,配 variant 定语义色 +2. 要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+ +3. 只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」) 现场演示:apps/docs/demo.html#sec-feedback diff --git a/packages/skin/ui/src/badge.ts b/packages/skin/ui/src/badge.ts index 6dbd6dd..ea2008c 100644 --- a/packages/skin/ui/src/badge.ts +++ b/packages/skin/ui/src/badge.ts @@ -1,7 +1,17 @@ import { h } from '@ui-arch/frame'; import type { BadgeProps } from './types.js'; -/*** 徽标:variant 决定语义色,纯展示不持有状态 ***/ +/*** 徽标:文字 / 数字角标 / 纯红点三种形态,variant 决定语义色,纯展示不持有状态 ***/ export function badge(props: BadgeProps): HTMLElement { - return h('span', { class: `ua-badge ua-badge-${props.variant ?? 'default'}` }, props.label); + const tone = `ua-badge ua-badge-${props.variant ?? 'default'}`; + if (props.dot) { + // 红点:无可见文字,靠 aria-label 给出含义(如「有未读」) + return h('span', { class: `${tone} ua-badge-dot`, role: 'img', 'aria-label': props.label ?? '有更新' }); + } + if (props.count != null) { + const max = props.max ?? 99; // 缺省上限 99 + const shown = props.count > max ? `${max}+` : String(Math.max(0, props.count)); // 负数归零,超限折成 N+ + return h('span', { class: `${tone} ua-badge-count`, 'aria-label': props.label ? `${props.label} ${shown}` : undefined }, shown); + } + return h('span', { class: tone }, props.label); } diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index 43c772e..2a24501 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -239,8 +239,11 @@ export interface DividerProps { /*** 徽标入参 ***/ export interface BadgeProps { - label: string; // 徽标文案 + label?: string; // 徽标文案;与 count / dot 三选一 variant?: 'default' | 'success' | 'warning' | 'danger'; // 语义色;缺省 default + count?: number; // 数字角标:非负整数渲染为数字,超过 max 显示 `${max}+` + max?: number; // 数字上限;缺省 99 + dot?: boolean; // 只显示小红点(不带文字),用 label 作可访问名 } /*** 头像入参 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 9ffbeac..8d9e9f5 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -762,21 +762,34 @@ { "n": "label", "t": "string", - "r": 1, - "d": "徽标文案" + "d": "徽标文案;与 count / dot 三选一,dot 时作可访问名" }, { "n": "variant", "t": "'default' | 'success' | 'warning' | 'danger'", - "d": "语义色;缺省 default", - "df": "default" + "d": "语义色;缺省 default" + }, + { + "n": "count", + "t": "number", + "d": "数字角标:超过 max 显示 N+,负数归零" + }, + { + "n": "max", + "t": "number", + "d": "数字上限;缺省 99" + }, + { + "n": "dot", + "t": "boolean", + "d": "只显示小红点(无文字),role=img + label 作名称" } ], "example": "badge({ label: '成功', variant: 'success' })", "steps": [ - "选择语义色:default 中性、success 成功、warning 警告、danger 危险", - "传入 label 即可,纯展示组件无状态", - "状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button" + "纯状态文案直接传 label,配 variant 定语义色", + "要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+", + "只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」)" ] }, { diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index eaa711d..3ac9b36 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -1039,6 +1039,21 @@ button.ua-step-dot:hover { font-size: var(--ua-font-size-sm); line-height: 1.6; } +.ua-badge-count { + min-width: 18px; + padding: 0 5px; + text-align: center; + font-variant-numeric: tabular-nums; + background: var(--ua-color-danger); + color: var(--ua-color-bg); +} +.ua-badge-dot { + width: 8px; + height: 8px; + padding: 0; + border-radius: 999px; + background: var(--ua-color-danger); +} .ua-badge-default { background: var(--ua-color-border); color: var(--ua-color-text);