iter(g240): 按钮 loading 态,转圈禁点支持布尔与信号动态同步
This commit is contained in:
+9
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "ui-arch-registry-index/0.1",
|
||||
"generatedAt": "2026-10-26T13:32:36.756Z",
|
||||
"generatedAt": "2026-10-26T13:40:30.157Z",
|
||||
"repoRoot": ".",
|
||||
"packages": [
|
||||
{
|
||||
@@ -142,7 +142,7 @@
|
||||
"api": {
|
||||
"entry": "src/index.ts",
|
||||
"exports": [
|
||||
"button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用;type 缺省 button(表单内不隐式提交)",
|
||||
"button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调",
|
||||
"textField(props):文本输入,value 信号双向绑定,disabled 支持布尔或信号,onInput 输入回调;prefix/suffix 可选渲染为输入框内侧附加块,clearable 开启后有值即显一键清空按钮,maxCount 设原生上限并实时显示字数",
|
||||
"inputNumber(props):数字输入,−/+ 按钮与键盘 ↑↓ 调节(长按连发步进),min/max/step 夹取,precision 小数位归一;prefix/suffix 可选渲染为整组前后附加块",
|
||||
"textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号,rows 控行数;prefix/suffix 可选渲染为上下附加块,maxCount 显示实时字数并设原生上限",
|
||||
@@ -355,13 +355,19 @@
|
||||
"n": "size",
|
||||
"t": "'sm' | 'md' | 'lg'",
|
||||
"d": "高度档位:sm 紧凑 / md 默认 / lg 大触控目标,走 --ua-control-h-* 三档;缺省 md"
|
||||
},
|
||||
{
|
||||
"n": "loading",
|
||||
"t": "boolean | Signal<boolean>",
|
||||
"df": "false",
|
||||
"d": "加载态:转圈并禁点(aria-busy 播报忙碌);布尔直接置位,传信号则动态同步"
|
||||
}
|
||||
],
|
||||
"example": "button({ label: '提交', variant: 'primary', onClick: () => console.log('clicked') })",
|
||||
"steps": [
|
||||
"确定语义强度:主操作用 primary(默认),次要操作用 ghost,危险操作用 danger",
|
||||
"绑定 onClick 回调处理点击逻辑",
|
||||
"需要禁用态时自行在回调首行卫语句判断,或外层包条件渲染",
|
||||
"需要禁用态时传 disabled(布尔或信号);异步提交用 loading:开始时置 true,完成后置 false,按钮转圈并自动禁点",
|
||||
"放进 <form> 里需要提交时显式传 type: \"submit\";缺省 button 不会触发原生提交"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -159,6 +159,7 @@ const calDay = signal(dayKey(0));
|
||||
|
||||
// —— 响应式状态演示 ——
|
||||
const count = signal(0);
|
||||
const saving = signal(false); // 按钮 loading 态演示(模拟异步保存)
|
||||
|
||||
// —— 双向绑定演示 ——
|
||||
const name = signal('');
|
||||
@@ -326,6 +327,7 @@ const content = h(
|
||||
'signal 驱动:按钮修改信号,文本自动更新,无虚拟 DOM。',
|
||||
button({ label: 'count +1', onClick: () => count(count() + 1) }),
|
||||
button({ label: '重置', variant: 'ghost', onClick: () => count(0) }),
|
||||
button({ label: '保存(模拟请求)', loading: saving, onClick: () => { saving(true); setTimeout(() => saving(false), 1500); } }),
|
||||
h('span', { class: 'out' }, () => `count = ${count()}`),
|
||||
),
|
||||
section(
|
||||
|
||||
+4
-3
@@ -1,6 +1,6 @@
|
||||
# @ui-arch 组件库 Agent 文档(无图形版)
|
||||
|
||||
> 自动生成于 2026-10-26T13:32:36.756Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 自动生成于 2026-10-26T13:40:30.157Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
|
||||
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
|
||||
|
||||
## 快速上手
|
||||
@@ -90,6 +90,7 @@ image({ src: '/a.png', alt: '架构图', width: 160 })
|
||||
- disabled:boolean | Signal<boolean> —— 禁用态:布尔直接置位,传信号则动态同步
|
||||
- onClick(回调):() => void —— 点击回调
|
||||
- size:'sm' | 'md' | 'lg' —— 高度档位:sm 紧凑 / md 默认 / lg 大触控目标,走 --ua-control-h-* 三档;缺省 md
|
||||
- loading(默认 false):boolean | Signal<boolean> —— 加载态:转圈并禁点(aria-busy 播报忙碌);布尔直接置位,传信号则动态同步
|
||||
|
||||
示例:
|
||||
|
||||
@@ -101,7 +102,7 @@ button({ label: '提交', variant: 'primary', onClick: () => console.log('clicke
|
||||
|
||||
1. 确定语义强度:主操作用 primary(默认),次要操作用 ghost,危险操作用 danger
|
||||
2. 绑定 onClick 回调处理点击逻辑
|
||||
3. 需要禁用态时自行在回调首行卫语句判断,或外层包条件渲染
|
||||
3. 需要禁用态时传 disabled(布尔或信号);异步提交用 loading:开始时置 true,完成后置 false,按钮转圈并自动禁点
|
||||
4. 放进 <form> 里需要提交时显式传 type: "submit";缺省 button 不会触发原生提交
|
||||
|
||||
现场演示:apps/docs/demo.html#sec-counter
|
||||
@@ -2140,7 +2141,7 @@ highlight({ text: 'Alpha Beta', keyword: 'beta' })
|
||||
|
||||
API 速览:
|
||||
|
||||
- button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用;type 缺省 button(表单内不隐式提交)
|
||||
- button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调
|
||||
- textField(props):文本输入,value 信号双向绑定,disabled 支持布尔或信号,onInput 输入回调;prefix/suffix 可选渲染为输入框内侧附加块,clearable 开启后有值即显一键清空按钮,maxCount 设原生上限并实时显示字数
|
||||
- inputNumber(props):数字输入,−/+ 按钮与键盘 ↑↓ 调节(长按连发步进),min/max/step 夹取,precision 小数位归一;prefix/suffix 可选渲染为整组前后附加块
|
||||
- textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号,rows 控行数;prefix/suffix 可选渲染为上下附加块,maxCount 显示实时字数并设原生上限
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
- 类型: skin-dom · 目录: packages/skin/ui
|
||||
- 描述: DOM 皮肤组件库:表单 / 反馈 / 浮层 / 导航 / 数据展示,构建在 @ui-arch/frame 与 @ui-arch/table-core 之上,样式只消费 --ua-* 令牌(组件全量见 api.exports 或刚体清单)
|
||||
- API:
|
||||
- button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用;type 缺省 button(表单内不隐式提交)
|
||||
- button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调
|
||||
- textField(props):文本输入,value 信号双向绑定,disabled 支持布尔或信号,onInput 输入回调;prefix/suffix 可选渲染为输入框内侧附加块,clearable 开启后有值即显一键清空按钮,maxCount 设原生上限并实时显示字数
|
||||
- inputNumber(props):数字输入,−/+ 按钮与键盘 ↑↓ 调节(长按连发步进),min/max/step 夹取,precision 小数位归一;prefix/suffix 可选渲染为整组前后附加块
|
||||
- textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号,rows 控行数;prefix/suffix 可选渲染为上下附加块,maxCount 显示实时字数并设原生上限
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import { h } from '@ui-arch/frame';
|
||||
import { effect, h, signal } from '@ui-arch/frame';
|
||||
import type { ButtonProps } from './types.js';
|
||||
|
||||
/*** 按钮:variant 控制视觉强度,disabled 支持布尔或信号禁用,onClick 为点击回调 ***/
|
||||
/*** 按钮:variant 控制视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 为点击回调 ***/
|
||||
export function button(props: ButtonProps): HTMLElement {
|
||||
return h(
|
||||
const loading = typeof props.loading === 'function' ? props.loading : signal(!!props.loading); // 归一成信号:布尔也走同一响应式路径
|
||||
const spin = h('span', { class: 'ua-spinner ua-btn-spin', 'aria-hidden': 'true' }); // 转圈指示:CSS 默认 display:none,加载态才显形
|
||||
const el = h(
|
||||
'button',
|
||||
{ class: `ua-btn ua-btn-${props.variant ?? 'primary'}${props.size && props.size !== 'md' ? ` is-${props.size}` : ''}`, type: props.type ?? 'button', disabled: props.disabled, onClick: props.onClick }, // 缺省 button:表单内不隐式提交
|
||||
{
|
||||
class: `ua-btn ua-btn-${props.variant ?? 'primary'}${props.size && props.size !== 'md' ? ` is-${props.size}` : ''}`,
|
||||
type: props.type ?? 'button',
|
||||
disabled: () => (typeof props.disabled === 'function' ? props.disabled() : !!props.disabled) || loading(), // 禁点口径:显式禁用或加载中
|
||||
'aria-busy': () => (loading() ? 'true' : null), // 读屏播报忙碌态(null 移除属性)
|
||||
onClick: props.onClick,
|
||||
}, // 缺省 button:表单内不隐式提交
|
||||
spin,
|
||||
props.label,
|
||||
);
|
||||
effect(() => el.classList.toggle('is-loading', loading())); // 加载态只切类名,不整棵重渲染(保住焦点与子节点)
|
||||
return el;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface ButtonProps {
|
||||
variant?: 'primary' | 'ghost' | 'danger'; // 视觉强度;缺省 primary
|
||||
type?: 'button' | 'submit' | 'reset'; // 原生类型;缺省 button(表单内不会意外触发提交)
|
||||
disabled?: boolean | Signal<boolean>; // 禁用态:布尔直接置位,传信号则动态同步
|
||||
loading?: boolean | Signal<boolean>; // 加载态:转圈并禁点(aria-busy);布尔直接置位,传信号则动态同步
|
||||
onClick?: () => void; // 点击回调
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"api": {
|
||||
"entry": "src/index.ts",
|
||||
"exports": [
|
||||
"button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用;type 缺省 button(表单内不隐式提交)",
|
||||
"button(props):按钮,variant 三档视觉强度,disabled / loading 支持布尔或信号动态同步(loading 转圈并禁点),onClick 点击回调",
|
||||
"textField(props):文本输入,value 信号双向绑定,disabled 支持布尔或信号,onInput 输入回调;prefix/suffix 可选渲染为输入框内侧附加块,clearable 开启后有值即显一键清空按钮,maxCount 设原生上限并实时显示字数",
|
||||
"inputNumber(props):数字输入,−/+ 按钮与键盘 ↑↓ 调节(长按连发步进),min/max/step 夹取,precision 小数位归一;prefix/suffix 可选渲染为整组前后附加块",
|
||||
"textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号,rows 控行数;prefix/suffix 可选渲染为上下附加块,maxCount 显示实时字数并设原生上限",
|
||||
@@ -226,13 +226,19 @@
|
||||
"n": "size",
|
||||
"t": "'sm' | 'md' | 'lg'",
|
||||
"d": "高度档位:sm 紧凑 / md 默认 / lg 大触控目标,走 --ua-control-h-* 三档;缺省 md"
|
||||
},
|
||||
{
|
||||
"n": "loading",
|
||||
"t": "boolean | Signal<boolean>",
|
||||
"df": "false",
|
||||
"d": "加载态:转圈并禁点(aria-busy 播报忙碌);布尔直接置位,传信号则动态同步"
|
||||
}
|
||||
],
|
||||
"example": "button({ label: '提交', variant: 'primary', onClick: () => console.log('clicked') })",
|
||||
"steps": [
|
||||
"确定语义强度:主操作用 primary(默认),次要操作用 ghost,危险操作用 danger",
|
||||
"绑定 onClick 回调处理点击逻辑",
|
||||
"需要禁用态时自行在回调首行卫语句判断,或外层包条件渲染",
|
||||
"需要禁用态时传 disabled(布尔或信号);异步提交用 loading:开始时置 true,完成后置 false,按钮转圈并自动禁点",
|
||||
"放进 <form> 里需要提交时显式传 type: \"submit\";缺省 button 不会触发原生提交"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -5238,3 +5238,24 @@ h5.ua-type-title { font-size: var(--ua-font-size-md); }
|
||||
color: inherit;
|
||||
font-weight: var(--ua-weight-medium);
|
||||
}
|
||||
|
||||
/* ---- 按钮 loading 态:转圈 + 禁点 ---- */
|
||||
.ua-btn-spin {
|
||||
display: none; /* 非加载态不占位:文案位置不漂移 */
|
||||
border-width: 2px;
|
||||
}
|
||||
.ua-btn.is-loading {
|
||||
cursor: progress; /* 光标改忙碌:点了也不会有下一步 */
|
||||
}
|
||||
.ua-btn.is-loading .ua-btn-spin {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
margin-right: var(--ua-space-05);
|
||||
vertical-align: -0.125em; /* 随文字基线微沉:转圈与文案居中对齐 */
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.ua-btn.is-loading .ua-btn-spin {
|
||||
animation: none; /* 降动效:转圈静态化为实色环 */
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user