iter(g284): 新增 progressRing 环形进度组件

This commit is contained in:
HIsheR
2026-10-26 23:12:33 +08:00
parent f20f673e76
commit c4384be959
12 changed files with 239 additions and 11 deletions
+43 -2
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "ui-arch-registry-index/0.1", "$schema": "ui-arch-registry-index/0.1",
"generatedAt": "2026-10-26T15:08:10.710Z", "generatedAt": "2026-10-26T15:11:40.469Z",
"repoRoot": ".", "repoRoot": ".",
"packages": [ "packages": [
{ {
@@ -228,7 +228,8 @@
"loading(props, ...children):区域加载遮罩,内容原地降透明度 + 转圈文案,带延迟出场避免快请求闪烁", "loading(props, ...children):区域加载遮罩,内容原地降透明度 + 转圈文案,带延迟出场避免快请求闪烁",
"relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值", "relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值",
"sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互", "sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互",
"heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细" "heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细",
"progressRing(props):环形进度,SVG 双圆靠 dasharray 画弧 + 中心百分比,value 可传信号自动重绘"
], ],
"keyTypes": [ "keyTypes": [
"ButtonProps", "ButtonProps",
@@ -4539,6 +4540,46 @@
"格子颜色是相对深浅:按序列最大值归一成四档——所以它说的是「哪天更密」,不是绝对值高低", "格子颜色是相对深浅:按序列最大值归一成四档——所以它说的是「哪天更密」,不是绝对值高低",
"默认 12 周、11px 格子;嵌进窄卡片就调小 weeks,看不出格子边界就调大 cellSize" "默认 12 周、11px 格子;嵌进窄卡片就调小 weeks,看不出格子边界就调大 cellSize"
] ]
},
{
"id": "progressRing",
"title": "环形进度 ProgressRing",
"demo": "sec-ring",
"props": [
{
"n": "value",
"t": "number | Signal<number>",
"d": "当前进度 0-100;超出范围自动夹取,信号变化时自动重绘"
},
{
"n": "size",
"t": "number",
"d": "外径(px);缺省 96"
},
{
"n": "thickness",
"t": "number",
"d": "环宽(px);缺省 8"
},
{
"n": "showText",
"t": "boolean",
"d": "是否显示中心文字;缺省 true(关掉时请自行保证 aria 可读)"
},
{
"n": "label",
"t": "string",
"d": "中心文字;缺省「N%」"
}
],
"example": "progressRing({ value: pct, size: 96 })",
"steps": [
"value 给数字就是静态环,给信号就是活环:不用自己算弧长,组件按 0-100 换算 dasharray",
"0 点固定在 12 点方向顺时针走,和进度条的心理模型一致,不需要额外传旋转参数",
"要放进表格或卡片角落就用 size: 56 + showText: false 的小环,文字由附近的主体数字承担",
"换色在父级设 color:进度弧读 currentColor,底环固定描边色(--ua-color-border),不引入第二个色源",
"这是个「环形进度条」,不是仪表盘:只表达 0-100 单一进度,多段占比请用饼图类组件"
]
} }
] ]
}, },
+1 -1
View File
@@ -21,7 +21,7 @@
- `packages/core/table-core`(@ui-arch/table-core):Headless 表格逻辑内核 - `packages/core/table-core`(@ui-arch/table-core):Headless 表格逻辑内核
- `packages/core/frame`(@ui-arch/frame):signal + hyperscript 微框架 - `packages/core/frame`(@ui-arch/frame):signal + hyperscript 微框架
- `packages/skin/ui`(@ui-arch/ui):85 个 DOM 组件(表单 / 反馈 / 浮层 / 导航 / 表格),样式只消费令牌 - `packages/skin/ui`(@ui-arch/ui):86 个 DOM 组件(表单 / 反馈 / 浮层 / 导航 / 表格),样式只消费令牌
- `packages/design/tokens`(@ui-arch/tokens):设计令牌 - `packages/design/tokens`(@ui-arch/tokens):设计令牌
- `packages/tools/cli`(@ui-arch/cli):`ua` 命令行 + MCP 注册表服务(private) - `packages/tools/cli`(@ui-arch/cli):`ua` 命令行 + MCP 注册表服务(private)
- `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html - `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html
+1 -1
View File
@@ -34,7 +34,7 @@ ui-arch-mvp/
│ │ ├── table-core/ # 表格状态内核 │ │ ├── table-core/ # 表格状态内核
│ │ └── frame/ # 信号 + hyperscript 微框架 │ │ └── frame/ # 信号 + hyperscript 微框架
│ ├── skin/ # 皮肤层(DOM 组件,可发布) │ ├── skin/ # 皮肤层(DOM 组件,可发布)
│ │ └── ui/ # 85 个组件 + ui.css │ │ └── ui/ # 86 个组件 + ui.css
│ ├── design/ # 资产层(可发布) │ ├── design/ # 资产层(可发布)
│ │ └── tokens/ # --ua-* 设计令牌 │ │ └── tokens/ # --ua-* 设计令牌
│ └── tools/ # 工程层(private,不发布) │ └── tools/ # 工程层(private,不发布)
+4 -4
View File
@@ -12,13 +12,13 @@ npm run docs # 生成人类文档站 apps/docs/index.html + Agent 全
npm run changelog # 依据 git 提交史重写 CHANGELOG.md(发版前跑;changelog:check 可查漂移) npm run changelog # 依据 git 提交史重写 CHANGELOG.md(发版前跑;changelog:check 可查漂移)
``` ```
## 组件(共 85 个) ## 组件(共 86 个)
<!-- ua:components --> <!-- ua:components -->
accordion · affix · alert · anchor · autoComplete · avatar · avatarGroup · backTop · badge · breadcrumb · button · calendar · carousel · card · cascader · checkbox · checkboxGroup · codeBlock · colorPicker · commandPalette · copyButton · countdown · dataTable · datePicker · descriptions · diffView · divider · drawer · empty · floatButton · form · grid · heatmap · highlight · image · inputNumber · inputTag · jsonViewer · kbd · layout · link · list · loading · menu · modal · mentions · multiSelect · notification · pagination · pinInput · popover · popconfirm · progress · radioGroup · rate · relativeTime · result · segmented · select · signaturePad · skeleton · slider · space · sparkline · spinner · splitter · statistic · stepper · switchButton · tabs · tag · textField · textarea · timeline · timePicker · toast · tooltip · tour · transfer · tree · treeSelect · typography · upload · virtualList · watermark accordion · affix · alert · anchor · autoComplete · avatar · avatarGroup · backTop · badge · breadcrumb · button · calendar · carousel · card · cascader · checkbox · checkboxGroup · codeBlock · colorPicker · commandPalette · copyButton · countdown · dataTable · datePicker · descriptions · diffView · divider · drawer · empty · floatButton · form · grid · heatmap · highlight · image · inputNumber · inputTag · jsonViewer · kbd · layout · link · list · loading · menu · modal · mentions · multiSelect · notification · pagination · pinInput · popover · popconfirm · progress · progressRing · radioGroup · rate · relativeTime · result · segmented · select · signaturePad · skeleton · slider · space · sparkline · spinner · splitter · statistic · stepper · switchButton · tabs · tag · textField · textarea · timeline · timePicker · toast · tooltip · tour · transfer · tree · treeSelect · typography · upload · virtualList · watermark
<!-- /ua:components --> <!-- /ua:components -->
分组:表单(button / copyButton / signaturePad / textField / inputNumber / inputTag / textarea / checkbox / checkboxGroup / colorPicker / switchButton / select / mentions / multiSelect / radioGroup / slider / rate / autoComplete / datePicker / timePicker / pinInput / segmented / upload / form + formItem / transfer / cascader)、反馈(alert / loading / toast / notification / result / spinner / progress / skeleton / badge / empty / statistic / countdown)、浮层(tooltip / popover / popconfirm / modal / drawer / menu / commandPalette)、导航(tabs / breadcrumb / pagination / accordion / stepper / tree / treeSelect / anchor)、数据展示(dataTable / jsonViewer / diffView / codeBlock / relativeTime / sparkline / heatmap / descriptions / card / list / kbd / highlight / timeline / tag / avatar / avatarGroup / image / carousel / calendar / typography / virtualList)、其他(floatButton / grid / layout / link / space / divider / splitter / backTop / affix / tour / watermark)。 分组:表单(button / copyButton / signaturePad / textField / inputNumber / inputTag / textarea / checkbox / checkboxGroup / colorPicker / switchButton / select / mentions / multiSelect / radioGroup / slider / rate / autoComplete / datePicker / timePicker / pinInput / segmented / upload / form + formItem / transfer / cascader)、反馈(alert / loading / toast / notification / result / spinner / progress / progressRing / skeleton / badge / empty / statistic / countdown)、浮层(tooltip / popover / popconfirm / modal / drawer / menu / commandPalette)、导航(tabs / breadcrumb / pagination / accordion / stepper / tree / treeSelect / anchor)、数据展示(dataTable / jsonViewer / diffView / codeBlock / relativeTime / sparkline / heatmap / descriptions / card / list / kbd / highlight / timeline / tag / avatar / avatarGroup / image / carousel / calendar / typography / virtualList)、其他(floatButton / grid / layout / link / space / divider / splitter / backTop / affix / tour / watermark)。
## 可访问性约定 ## 可访问性约定
@@ -34,7 +34,7 @@ accordion · affix · alert · anchor · autoComplete · avatar · avatarGroup
|---|---| |---|---|
| `packages/core/frame` | @ui-arch/frame:signal / computed / effect + hyperscript(无虚拟 DOM) | | `packages/core/frame` | @ui-arch/frame:signal / computed / effect + hyperscript(无虚拟 DOM) |
| `packages/core/table-core` | @ui-arch/table-core:headless 表格(filter → sort → paginate 派生管线) | | `packages/core/table-core` | @ui-arch/table-core:headless 表格(filter → sort → paginate 派生管线) |
| `packages/skin/ui` | @ui-arch/ui:85 个 DOM 组件 + ui.css(只消费 `--ua-*` 令牌) | | `packages/skin/ui` | @ui-arch/ui:86 个 DOM 组件 + ui.css(只消费 `--ua-*` 令牌) |
| `packages/design/tokens` | @ui-arch/tokens:设计令牌(暗色只换值不换名) | | `packages/design/tokens` | @ui-arch/tokens:设计令牌(暗色只换值不换名) |
| `packages/tools/cli` | @ui-arch/cli:`ua` 命令行与 stdio MCP server | | `packages/tools/cli` | @ui-arch/cli:`ua` 命令行与 stdio MCP server |
| `apps/demo` | 交互演示(esbuild 打包成单文件) | | `apps/demo` | 交互演示(esbuild 打包成单文件) |
+23
View File
@@ -69,6 +69,7 @@ import {
popconfirm, popconfirm,
popover, popover,
progress, progress,
progressRing,
radioGroup, radioGroup,
relativeTime, relativeTime,
rate, rate,
@@ -1861,6 +1862,28 @@ const content = h(
), ),
); );
// 环形进度:value 传信号,按钮改信号 → 弧长与中心文字一起重绘
content.append(
section(
'sec-ring',
'环形进度',
'progressRing:SVG 双圆靠 stroke-dasharray 画弧(0 从 12 点方向顺时针长),中心文字等宽;value 可传信号,弧长随之重绘。',
(() => {
const pct = signal(64);
const bump = (delta: number): void => pct(Math.min(100, Math.max(0, pct() + delta))); // 夹在 0-100,越界按键不产生负进度
return h(
'div',
{ class: 'row' },
progressRing({ value: pct }),
progressRing({ value: pct, size: 56, thickness: 6, showText: false }), // 无文案小环:适合塞进表格单元格
button({ label: '+10%', variant: 'ghost', onClick: () => bump(10) }),
button({ label: '-10%', variant: 'ghost', onClick: () => bump(-10) }),
button({ label: '清零', variant: 'ghost', onClick: () => pct(0) }),
);
})(),
),
);
// 悬浮按钮:fixed 定位,挂 body 不参与页面布局 // 悬浮按钮:fixed 定位,挂 body 不参与页面布局
document.body.append( document.body.append(
floatButton({ icon: '+', label: '新建工单', tooltip: '新建工单', position: 'left-bottom', onClick: () => toast.success('已新建工单') }), floatButton({ icon: '+', label: '新建工单', tooltip: '新建工单', position: 'left-bottom', onClick: () => toast.success('已新建工单') }),
+28 -1
View File
@@ -1,6 +1,6 @@
# @ui-arch 组件库 Agent 文档(无图形版) # @ui-arch 组件库 Agent 文档(无图形版)
> 自动生成于 2026-10-26T15:08:10.710Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 自动生成于 2026-10-26T15:11:40.469Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
## 快速上手 ## 快速上手
@@ -2427,6 +2427,32 @@ heatmap({ values: activity, weeks: 12, formatValue: (n, d) => d + ' 提交 ' + n
现场演示:apps/docs/demo.html#sec-heat 现场演示:apps/docs/demo.html#sec-heat
### progressRing — 环形进度 ProgressRing
参数:
- value:number | Signal<number> —— 当前进度 0-100;超出范围自动夹取,信号变化时自动重绘
- size:number —— 外径(px);缺省 96
- thickness:number —— 环宽(px);缺省 8
- showText:boolean —— 是否显示中心文字;缺省 true(关掉时请自行保证 aria 可读)
- label:string —— 中心文字;缺省「N%」
示例:
```
progressRing({ value: pct, size: 96 })
```
手把手:
1. value 给数字就是静态环,给信号就是活环:不用自己算弧长,组件按 0-100 换算 dasharray
2. 0 点固定在 12 点方向顺时针走,和进度条的心理模型一致,不需要额外传旋转参数
3. 要放进表格或卡片角落就用 size: 56 + showText: false 的小环,文字由附近的主体数字承担
4. 换色在父级设 color:进度弧读 currentColor,底环固定描边色(--ua-color-border),不引入第二个色源
5. 这是个「环形进度条」,不是仪表盘:只表达 0-100 单一进度,多段占比请用饼图类组件
现场演示:apps/docs/demo.html#sec-ring
API 速览: API 速览:
- button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调 - button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调
@@ -2516,6 +2542,7 @@ API 速览:
- relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值 - relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值
- sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互 - sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互
- heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细 - heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细
- progressRing(props):环形进度,SVG 双圆靠 dasharray 画弧 + 中心百分比,value 可传信号自动重绘
一行用法: 一行用法:
+1
View File
@@ -134,6 +134,7 @@
- relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值 - relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值
- sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互 - sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互
- heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细 - heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细
- progressRing(props):环形进度,SVG 双圆靠 dasharray 画弧 + 中心百分比,value 可传信号自动重绘
- 用法: `const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')` - 用法: `const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')`
- 约定: 皮肤不持有业务状态,一律委托 headless 内核或调用方信号 - 约定: 皮肤不持有业务状态,一律委托 headless 内核或调用方信号
- 约定: 表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调 - 约定: 表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调
+1
View File
@@ -85,3 +85,4 @@ export { loading } from './loading.js';
export { relativeTime } from './relativeTime.js'; export { relativeTime } from './relativeTime.js';
export { sparkline } from './sparkline.js'; export { sparkline } from './sparkline.js';
export { heatmap } from './heatmap.js'; export { heatmap } from './heatmap.js';
export { progressRing } from './progressRing.js';
+56
View File
@@ -0,0 +1,56 @@
import { effect, h } from '@ui-arch/frame';
import type { ProgressRingProps } from './types.js';
const NS = 'http://www.w3.org/2000/svg';
// 缺省尺寸与环宽:96px 装得下百分比数字,8px 环宽在小尺寸下也不显笨
const SIZE = 96;
const THICK = 8;
/*** 建 SVG 元素并写属性:svg 必须 createElementNS,属性只能 setAttribute ***/
function svgEl(tag: string, attrs: Record<string, string | number>): SVGElement {
const el = document.createElementNS(NS, tag);
for (const [k, v] of Object.entries(attrs)) el.setAttribute(k, String(v));
return el;
}
/*** 环形进度:SVG 双圆(底环 + 进度弧)靠 dasharray 画弧,value 变化时弧长与文字同步 ***/
export function progressRing(props: ProgressRingProps): HTMLElement {
const size = props.size ?? SIZE;
const thick = props.thickness ?? THICK;
const mid = size / 2;
const r = (size - thick) / 2; // 半径要扣掉环宽,否则弧会超出画布
const c = 2 * Math.PI * r; // 周长:dasharray 的分母
const read = (): number => (typeof props.value === 'function' ? props.value() : props.value); // 数值 / 信号同一口径
const svg = svgEl('svg', { viewBox: `0 0 ${size} ${size}`, width: size, height: size, 'aria-hidden': 'true' });
const track = svgEl('circle', { cx: mid, cy: mid, r, fill: 'none', 'stroke-width': thick, class: 'ua-ring-track' });
// 弧从 12 点方向顺时针长:整圆旋转 -90°,否则默认从 3 点位置起步
const arc = svgEl('circle', {
cx: mid, cy: mid, r, fill: 'none', 'stroke-width': thick,
class: 'ua-ring-arc', 'stroke-dasharray': `${0} ${c}`, 'stroke-linecap': 'round',
transform: `rotate(-90 ${mid} ${mid})`,
});
const text = h('span', { class: 'ua-ring-text' });
const wrap = h(
'div',
{
class: 'ua-ring',
role: 'progressbar',
'aria-valuemin': '0',
'aria-valuemax': '100',
style: `width:${size}px;height:${size}px`,
},
svg,
text,
);
svg.append(track, arc); // 底环先画,进度弧盖在上面
/*** 重绘:把百分比夹到 0-100,弧长按比例裁,文字与 aria-valuenow 同步 ***/
const paint = (): void => {
const pct = Math.min(100, Math.max(0, Math.round(read())));
arc.setAttribute('stroke-dasharray', `${(c * pct) / 100} ${c}`); // 只画这一段,剩下留空
if (props.showText !== false) text.textContent = props.label ?? `${pct}%`;
wrap.setAttribute('aria-valuenow', String(pct));
};
effect(paint);
return wrap;
}
+9
View File
@@ -1110,3 +1110,12 @@ export interface HeatmapProps {
ariaLabel?: string; // 可访问名;缺省「最近 N 周活跃度」 ariaLabel?: string; // 可访问名;缺省「最近 N 周活跃度」
formatValue?: (count: number, date: string) => string; // 悬停提示文案;缺省「日期 · 数量」 formatValue?: (count: number, date: string) => string; // 悬停提示文案;缺省「日期 · 数量」
} }
/*** 环形进度入参 ***/
export interface ProgressRingProps {
value: number | Signal<number>; // 当前进度 0-100;超出范围自动夹取,信号变化时自动重绘
size?: number; // 外径(px);缺省 96
thickness?: number; // 环宽(px);缺省 8
showText?: boolean; // 是否显示中心文字;缺省 true(关掉时请自行保证 aria 可读)
label?: string; // 中心文字;缺省「N%」
}
+42 -1
View File
@@ -99,7 +99,8 @@
"loading(props, ...children):区域加载遮罩,内容原地降透明度 + 转圈文案,带延迟出场避免快请求闪烁", "loading(props, ...children):区域加载遮罩,内容原地降透明度 + 转圈文案,带延迟出场避免快请求闪烁",
"relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值", "relativeTime(props):把时间戳渲染成「3 分钟前」并自动刷新,超阈值改显示绝对日期,title 恒给精确值",
"sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互", "sparkline(props):迷你趋势线,把数值序列压成折线(可填充 + 末点标记),无坐标轴无交互",
"heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细" "heatmap(props):日历热力图,按周列 × 星期行铺格子、四档浓度表示当天数量,悬停看明细",
"progressRing(props):环形进度,SVG 双圆靠 dasharray 画弧 + 中心百分比,value 可传信号自动重绘"
], ],
"keyTypes": [ "keyTypes": [
"ButtonProps", "ButtonProps",
@@ -4410,6 +4411,46 @@
"格子颜色是相对深浅:按序列最大值归一成四档——所以它说的是「哪天更密」,不是绝对值高低", "格子颜色是相对深浅:按序列最大值归一成四档——所以它说的是「哪天更密」,不是绝对值高低",
"默认 12 周、11px 格子;嵌进窄卡片就调小 weeks,看不出格子边界就调大 cellSize" "默认 12 周、11px 格子;嵌进窄卡片就调小 weeks,看不出格子边界就调大 cellSize"
] ]
},
{
"id": "progressRing",
"title": "环形进度 ProgressRing",
"demo": "sec-ring",
"props": [
{
"n": "value",
"t": "number | Signal<number>",
"d": "当前进度 0-100;超出范围自动夹取,信号变化时自动重绘"
},
{
"n": "size",
"t": "number",
"d": "外径(px);缺省 96"
},
{
"n": "thickness",
"t": "number",
"d": "环宽(px);缺省 8"
},
{
"n": "showText",
"t": "boolean",
"d": "是否显示中心文字;缺省 true(关掉时请自行保证 aria 可读)"
},
{
"n": "label",
"t": "string",
"d": "中心文字;缺省「N%」"
}
],
"example": "progressRing({ value: pct, size: 96 })",
"steps": [
"value 给数字就是静态环,给信号就是活环:不用自己算弧长,组件按 0-100 换算 dasharray",
"0 点固定在 12 点方向顺时针走,和进度条的心理模型一致,不需要额外传旋转参数",
"要放进表格或卡片角落就用 size: 56 + showText: false 的小环,文字由附近的主体数字承担",
"换色在父级设 color:进度弧读 currentColor,底环固定描边色(--ua-color-border),不引入第二个色源",
"这是个「环形进度条」,不是仪表盘:只表达 0-100 单一进度,多段占比请用饼图类组件"
]
} }
] ]
} }
+29
View File
@@ -5872,6 +5872,35 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); }
word-break: break-word; word-break: break-word;
} }
/* ---- 环形进度:底环走描边色,进度弧跟随 currentColor,中心文字用等宽数字 ---- */
.ua-ring {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--ua-color-accent); /* 弧色跟随文字色:父级改 color 即可换色,不引入第二个色源 */
}
.ua-ring svg {
display: block;
}
.ua-ring-track {
stroke: var(--ua-color-border);
}
.ua-ring-arc {
stroke: currentColor;
transition: stroke-dasharray var(--ua-duration-slower) var(--ua-ease); /* 只动 dasharray:不产生空间位移,减少动效规则下无副作用 */
}
.ua-ring-text {
position: absolute;
color: var(--ua-color-text);
font-size: var(--ua-font-size-sm);
font-variant-numeric: tabular-nums; /* 等宽数字:进度跳到 100% 时文字不会左右晃 */
}
/* ---- 减少动效:旋转 / 缩放一律退化为瞬时 ---- /* ---- 减少动效:旋转 / 缩放一律退化为瞬时 ----
前两类(无限动画、悬停位移)已有专门兜底,但 rotate / scale 过渡属于第三类空间动效: 前两类(无限动画、悬停位移)已有专门兜底,但 rotate / scale 过渡属于第三类空间动效:
折叠箭头旋转、卡片按压缩放都靠它提供手感。减少动效下把过渡属性收窄成「只留颜色类」, 折叠箭头旋转、卡片按压缩放都靠它提供手感。减少动效下把过渡属性收窄成「只留颜色类」,