iter(g92): 徽标支持数字角标与红点

This commit is contained in:
HIsheR
2026-10-26 13:11:29 +08:00
parent 8e6c84ade3
commit ac5c5cd233
8 changed files with 92 additions and 24 deletions
+8
View File
@@ -1092,6 +1092,14 @@
"acceptance": "FormItemProps 新增可选 hint,渲染在控件下方;校验失败时 hint 让位(hidden)只留错误文案,校验通过自动恢复;样式走令牌;文档参数表(formItem 前缀)与演示同步;npm run check 全绿", "acceptance": "FormItemProps 新增可选 hint,渲染在控件下方;校验失败时 hint 让位(hidden)只留错误文案,校验通过自动恢复;样式走令牌;文档参数表(formItem 前缀)与演示同步;npm run check 全绿",
"notes": "自补:表单可用性;不改 formItem 返回句柄与 form 聚合逻辑", "notes": "自补:表单可用性;不改 formItem 返回句柄与 form 聚合逻辑",
"status": "done" "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"
} }
] ]
} }
+21 -8
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "ui-arch-registry-index/0.1", "$schema": "ui-arch-registry-index/0.1",
"generatedAt": "2026-10-26T05:10:23.912Z", "generatedAt": "2026-10-26T05:11:11.108Z",
"repoRoot": ".", "repoRoot": ".",
"packages": [ "packages": [
{ {
@@ -891,21 +891,34 @@
{ {
"n": "label", "n": "label",
"t": "string", "t": "string",
"r": 1, "d": "徽标文案;与 count / dot 三选一,dot 时作可访问名"
"d": "徽标文案"
}, },
{ {
"n": "variant", "n": "variant",
"t": "'default' | 'success' | 'warning' | 'danger'", "t": "'default' | 'success' | 'warning' | 'danger'",
"d": "语义色;缺省 default", "d": "语义色;缺省 default"
"df": "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' })", "example": "badge({ label: '成功', variant: 'success' })",
"steps": [ "steps": [
"选择语义色:default 中性、success 成功、warning 警告、danger 危险", "纯状态文案直接传 label,配 variant 定语义色",
"传入 label 即可,纯展示组件无状态", "要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+",
"状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button" "只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」)"
] ]
}, },
{ {
+3
View File
@@ -361,6 +361,9 @@ const content = h(
badge({ label: '成功', variant: 'success' }), badge({ label: '成功', variant: 'success' }),
badge({ label: '警告', variant: 'warning' }), badge({ label: '警告', variant: 'warning' }),
badge({ label: '危险', variant: 'danger' }), badge({ label: '危险', variant: 'danger' }),
badge({ count: 5, label: '未读' }),
badge({ count: 128, max: 99, label: '未读' }),
badge({ dot: true, label: '有未读消息' }),
alert({ message: '信息提示:这是一条 info 提示条。' }), alert({ message: '信息提示:这是一条 info 提示条。' }),
alert({ message: '警告提示:操作可能存在风险。', variant: 'warning' }), alert({ message: '警告提示:操作可能存在风险。', variant: 'warning' }),
h('div', { class: 'row' }, spinner(), spinner({ size: 26 })), h('div', { class: 'row' }, spinner(), spinner({ size: 26 })),
+9 -6
View File
@@ -1,6 +1,6 @@
# @ui-arch 组件库 Agent 文档(无图形版) # @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)。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
## 快速上手 ## 快速上手
@@ -418,8 +418,11 @@ card({ title: '用户表' }, dataTable({ data, columns }))
参数: 参数:
- label(必填):string —— 徽标文案 - label:string —— 徽标文案;与 count / dot 三选一,dot 时作可访问名
- variant(默认 default):'default' | 'success' | 'warning' | 'danger' —— 语义色;缺省 default - 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 危险 1. 纯状态文案直接传 label,配 variant 定语义色
2. 传入 label 即可,纯展示组件无状态 2. 要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+
3. 状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button 3. 只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」)
现场演示:apps/docs/demo.html#sec-feedback 现场演示:apps/docs/demo.html#sec-feedback
+12 -2
View File
@@ -1,7 +1,17 @@
import { h } from '@ui-arch/frame'; import { h } from '@ui-arch/frame';
import type { BadgeProps } from './types.js'; import type { BadgeProps } from './types.js';
/*** 徽标:variant 决定语义色,纯展示不持有状态 ***/ /*** 徽标:文字 / 数字角标 / 纯红点三种形态,variant 决定语义色,纯展示不持有状态 ***/
export function badge(props: BadgeProps): HTMLElement { 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);
} }
+4 -1
View File
@@ -239,8 +239,11 @@ export interface DividerProps {
/*** 徽标入参 ***/ /*** 徽标入参 ***/
export interface BadgeProps { export interface BadgeProps {
label: string; // 徽标文案 label?: string; // 徽标文案;与 count / dot 三选一
variant?: 'default' | 'success' | 'warning' | 'danger'; // 语义色;缺省 default variant?: 'default' | 'success' | 'warning' | 'danger'; // 语义色;缺省 default
count?: number; // 数字角标:非负整数渲染为数字,超过 max 显示 `${max}+`
max?: number; // 数字上限;缺省 99
dot?: boolean; // 只显示小红点(不带文字),用 label 作可访问名
} }
/*** 头像入参 ***/ /*** 头像入参 ***/
+20 -7
View File
@@ -762,21 +762,34 @@
{ {
"n": "label", "n": "label",
"t": "string", "t": "string",
"r": 1, "d": "徽标文案;与 count / dot 三选一,dot 时作可访问名"
"d": "徽标文案"
}, },
{ {
"n": "variant", "n": "variant",
"t": "'default' | 'success' | 'warning' | 'danger'", "t": "'default' | 'success' | 'warning' | 'danger'",
"d": "语义色;缺省 default", "d": "语义色;缺省 default"
"df": "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' })", "example": "badge({ label: '成功', variant: 'success' })",
"steps": [ "steps": [
"选择语义色:default 中性、success 成功、warning 警告、danger 危险", "纯状态文案直接传 label,配 variant 定语义色",
"传入 label 即可,纯展示组件无状态", "要显示数量传 count(如未读数),超过 max(缺省 99)自动渲染成 99+",
"状态语义靠 variant 承载,不要自造颜色;纯展示不可交互,需要操作请配 button" "只提示「有更新」用 dot: true,配合 label 给出读屏名(如「有未读消息」)"
] ]
}, },
{ {
+15
View File
@@ -1039,6 +1039,21 @@ button.ua-step-dot:hover {
font-size: var(--ua-font-size-sm); font-size: var(--ua-font-size-sm);
line-height: 1.6; 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 { .ua-badge-default {
background: var(--ua-color-border); background: var(--ua-color-border);
color: var(--ua-color-text); color: var(--ua-color-text);