iter: c01 button/checkbox/switch 补 disabled 禁用态(布尔或信号绑定)

This commit is contained in:
HIsheR
2026-10-23 16:08:19 +08:00
parent 83bc1e241c
commit 2a5892a88c
12 changed files with 87 additions and 21 deletions
+9 -1
View File
@@ -40,6 +40,14 @@
"acceptance": "ua CLI 新增 docs-gen 逻辑:读取各组件 ua.manifest.json 中的 components 参数表,自动生成 props 表 HTML 片段注入文档站模板;生成结果与现有手写版信息量对齐(props 名/类型/默认值/说明);npm run check 全绿且文档站可正常打开", "acceptance": "ua CLI 新增 docs-gen 逻辑:读取各组件 ua.manifest.json 中的 components 参数表,自动生成 props 表 HTML 片段注入文档站模板;生成结果与现有手写版信息量对齐(props 名/类型/默认值/说明);npm run check 全绿且文档站可正常打开",
"status": "done", "status": "done",
"notes": "核查确认 props 表/示例/步骤/演示 iframe 早已由 ua docs 从 manifest docs.components 单一来源驱动;真正的缺口是信息量不含默认值——本轮 CLI propsTable 新增「默认值」列(props 条目可选 df 字段,缺省渲染 —),llms-full.txt 参数行同步追加「默认 x」标注;16 处可机读默认值从描述文案提取进 df;check 全绿 + 文档站结构完整性校验通过" "notes": "核查确认 props 表/示例/步骤/演示 iframe 早已由 ua docs 从 manifest docs.components 单一来源驱动;真正的缺口是信息量不含默认值——本轮 CLI propsTable 新增「默认值」列(props 条目可选 df 字段,缺省渲染 —),llms-full.txt 参数行同步追加「默认 x」标注;16 处可机读默认值从描述文案提取进 df;check 全绿 + 文档站结构完整性校验通过"
},
{
"id": "c01",
"title": "button / checkbox / switch 补 disabled 禁用态",
"motivation": "三个基础交互组件缺禁用能力,表单只读/权限控制场景刚需",
"acceptance": "ButtonProps / CheckboxProps / SwitchProps 新增可选 disabled(boolean | Signal<boolean>):静态布尔与信号绑定都支持,禁用时事件不触发、置灰 + not-allowed 光标;demo 表单区加静态禁用与信号联动示例;manifest/文档/llms-full.txt 同步;npm run check 全绿",
"status": "done",
"notes": "零新增辅助代码:复用 frame h() 对 false/undefined 移除属性、Signal 函数走响应式绑定的既有语义,disabled 透传即可;CSS 补通用禁用态(opacity 0.45 + not-allowed,开关轨道同级置灰);demo 用同一 locked 信号绑定 switch 的 checked 与 checkbox 的 disabled 展示联动"
} }
] ]
} }
+19 -4
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "ui-arch-registry-index/0.1", "$schema": "ui-arch-registry-index/0.1",
"generatedAt": "2026-10-23T08:03:18.018Z", "generatedAt": "2026-10-23T08:07:27.570Z",
"repoRoot": ".", "repoRoot": ".",
"packages": [ "packages": [
{ {
@@ -142,11 +142,11 @@
"api": { "api": {
"entry": "src/index.ts", "entry": "src/index.ts",
"exports": [ "exports": [
"button(props):按钮,variant = primary | ghost | danger", "button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用",
"textField(props):文本输入,value 信号双向绑定", "textField(props):文本输入,value 信号双向绑定",
"textarea(props):多行输入,value 信号双向绑定", "textarea(props):多行输入,value 信号双向绑定",
"checkbox(props):复选框,checked 信号双向绑定", "checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"switchButton(props):开关,checked 信号双向绑定", "switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画", "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画",
"radioGroup(props):单选组,options + value 信号双向绑定", "radioGroup(props):单选组,options + value 信号双向绑定",
"card(props, ...children):卡片容器", "card(props, ...children):卡片容器",
@@ -224,6 +224,11 @@
"d": "视觉强度;缺省 primary", "d": "视觉强度;缺省 primary",
"df": "primary" "df": "primary"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onClick", "n": "onClick",
"t": "() => void", "t": "() => void",
@@ -317,6 +322,11 @@
"t": "string", "t": "string",
"d": "右侧文案;缺省只渲染勾选框" "d": "右侧文案;缺省只渲染勾选框"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onChange", "n": "onChange",
"t": "(checked: boolean) => void", "t": "(checked: boolean) => void",
@@ -346,6 +356,11 @@
"t": "string", "t": "string",
"d": "左侧文案" "d": "左侧文案"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onChange", "n": "onChange",
"t": "(checked: boolean) => void", "t": "(checked: boolean) => void",
+1
View File
@@ -3,3 +3,4 @@
{"time":"2026-10-23T15:53:33+08:00","id":"b03","result":"done","summary":"新增 skeleton 骨架屏组件:text/rect/circle 三形状 + 扫光微动画 + reduced-motion 静态化;manifest/docs/llms/demo 同步,check 全绿"} {"time":"2026-10-23T15:53:33+08:00","id":"b03","result":"done","summary":"新增 skeleton 骨架屏组件:text/rect/circle 三形状 + 扫光微动画 + reduced-motion 静态化;manifest/docs/llms/demo 同步,check 全绿"}
{"time":"2026-10-23T16:00:11+08:00","id":"b04","result":"done","summary":"新增独立 pagination 分页器(page 信号双向绑定 + 省略号折叠 + 键盘可达),dataTable 新增 page 受控桥接实现联动;demo 联动卡片,check 全绿"} {"time":"2026-10-23T16:00:11+08:00","id":"b04","result":"done","summary":"新增独立 pagination 分页器(page 信号双向绑定 + 省略号折叠 + 键盘可达),dataTable 新增 page 受控桥接实现联动;demo 联动卡片,check 全绿"}
{"time":"2026-10-23T16:03:46+08:00","id":"b05","result":"done","summary":"文档站核查确认已 manifest 驱动;补齐默认值信息量缺口:CLI propsTable 新增默认值列(df 字段)+ llms-full 默认标注,16 处默认值提取;check 全绿"} {"time":"2026-10-23T16:03:46+08:00","id":"b05","result":"done","summary":"文档站核查确认已 manifest 驱动;补齐默认值信息量缺口:CLI propsTable 新增默认值列(df 字段)+ llms-full 默认标注,16 处默认值提取;check 全绿"}
{"time":"2026-10-23T16:08:17+08:00","id":"c01","result":"done","summary":"button/checkbox/switchButton 补 disabled(boolean|Signal),复用 h() 布尔/信号既有语义零辅助代码;CSS 通用禁用态 + demo 信号联动示例;check 全绿"}
+10
View File
@@ -71,6 +71,9 @@ const formResult = signal('');
// —— 分页联动状态:dataTable 与独立 pagination 共用同一页码信号 —— // —— 分页联动状态:dataTable 与独立 pagination 共用同一页码信号 ——
const tablePage = signal(1); const tablePage = signal(1);
// —— 禁用态演示:开关信号同时绑定 switch 的 checked 与 checkbox 的 disabled ——
const locked = signal(true);
const app = h( const app = h(
'div', 'div',
{ class: 'page' }, { class: 'page' },
@@ -105,6 +108,13 @@ const app = h(
h('div', { class: 'row' }, radioGroup({ options: [{ value: 's', label: '小' }, { value: 'm', label: '中' }, { value: 'l', label: '大' }], value: size })), h('div', { class: 'row' }, radioGroup({ options: [{ value: 's', label: '小' }, { value: 'm', label: '中' }, { value: 'l', label: '大' }], value: size })),
textarea({ placeholder: '一句话介绍…', value: bio, rows: 2 }), textarea({ placeholder: '一句话介绍…', value: bio, rows: 2 }),
h('span', { class: 'out' }, () => `简介 ${bio().length} 字`), h('span', { class: 'out' }, () => `简介 ${bio().length} 字`),
h(
'div',
{ class: 'row' },
button({ label: '禁用按钮', variant: 'ghost', disabled: true }),
checkbox({ label: '信号禁用的勾选', disabled: locked }),
switchButton({ label: '锁定', checked: locked }), // 关掉开关即解锁上面的勾选框
),
), ),
section( section(
'sec-feedback', 'sec-feedback',
+7 -4
View File
@@ -1,6 +1,6 @@
# @ui-arch 组件库 Agent 文档(无图形版) # @ui-arch 组件库 Agent 文档(无图形版)
> 自动生成于 2026-10-23T08:02:39.002Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 自动生成于 2026-10-23T08:07:27.570Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
## 快速上手 ## 快速上手
@@ -48,6 +48,7 @@
- label(必填):string —— 按钮文案 - label(必填):string —— 按钮文案
- variant(默认 primary):'primary' | 'ghost' | 'danger' —— 视觉强度;缺省 primary - variant(默认 primary):'primary' | 'ghost' | 'danger' —— 视觉强度;缺省 primary
- disabled:boolean | Signal<boolean> —— 禁用态:布尔直接置位,传信号则动态同步
- onClick(回调):() => void —— 点击回调 - onClick(回调):() => void —— 点击回调
示例: 示例:
@@ -115,6 +116,7 @@ const bio = signal(''); textarea({ value: bio, rows: 4, placeholder: '一句话
- checked:Signal<boolean> —— 勾选状态信号,双向绑定 - checked:Signal<boolean> —— 勾选状态信号,双向绑定
- label:string —— 右侧文案;缺省只渲染勾选框 - label:string —— 右侧文案;缺省只渲染勾选框
- disabled:boolean | Signal<boolean> —— 禁用态:布尔直接置位,传信号则动态同步
- onChange(回调):(checked: boolean) => void —— 变更回调 - onChange(回调):(checked: boolean) => void —— 变更回调
示例: 示例:
@@ -137,6 +139,7 @@ const agreed = signal(false); checkbox({ label: '同意条款', checked: agreed,
- checked:Signal<boolean> —— 开关状态信号,双向绑定 - checked:Signal<boolean> —— 开关状态信号,双向绑定
- label:string —— 左侧文案 - label:string —— 左侧文案
- disabled:boolean | Signal<boolean> —— 禁用态:布尔直接置位,传信号则动态同步
- onChange(回调):(checked: boolean) => void —— 变更回调 - onChange(回调):(checked: boolean) => void —— 变更回调
示例: 示例:
@@ -506,11 +509,11 @@ dataTable({ data: users, selectable: true, columns: [{ key: 'name', header: '姓
API 速览: API 速览:
- button(props):按钮,variant = primary | ghost | danger - button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用
- textField(props):文本输入,value 信号双向绑定 - textField(props):文本输入,value 信号双向绑定
- textarea(props):多行输入,value 信号双向绑定 - textarea(props):多行输入,value 信号双向绑定
- checkbox(props):复选框,checked 信号双向绑定 - checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用
- switchButton(props):开关,checked 信号双向绑定 - switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用
- select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画 - select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画
- radioGroup(props):单选组,options + value 信号双向绑定 - radioGroup(props):单选组,options + value 信号双向绑定
- card(props, ...children):卡片容器 - card(props, ...children):卡片容器
+3 -3
View File
@@ -47,11 +47,11 @@
- 类型: skin-dom · 目录: packages/skin/ui - 类型: skin-dom · 目录: packages/skin/ui
- 描述: DOM 皮肤组件库:button / textField / textarea / checkbox / switch / select / radioGroup / card / badge / alert / toast / tooltip / skeleton / spinner / progress / tabs / pagination / modal / form / formItem / dataTable,构建在 @ui-arch/frame 与 @ui-arch/table-core 之上,样式只消费 --ua-* 令牌。 - 描述: DOM 皮肤组件库:button / textField / textarea / checkbox / switch / select / radioGroup / card / badge / alert / toast / tooltip / skeleton / spinner / progress / tabs / pagination / modal / form / formItem / dataTable,构建在 @ui-arch/frame 与 @ui-arch/table-core 之上,样式只消费 --ua-* 令牌。
- API: - API:
- button(props):按钮,variant = primary | ghost | danger - button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用
- textField(props):文本输入,value 信号双向绑定 - textField(props):文本输入,value 信号双向绑定
- textarea(props):多行输入,value 信号双向绑定 - textarea(props):多行输入,value 信号双向绑定
- checkbox(props):复选框,checked 信号双向绑定 - checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用
- switchButton(props):开关,checked 信号双向绑定 - switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用
- select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画 - select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画
- radioGroup(props):单选组,options + value 信号双向绑定 - radioGroup(props):单选组,options + value 信号双向绑定
- card(props, ...children):卡片容器 - card(props, ...children):卡片容器
+2 -2
View File
@@ -1,11 +1,11 @@
import { h } from '@ui-arch/frame'; import { h } from '@ui-arch/frame';
import type { ButtonProps } from './types.js'; import type { ButtonProps } from './types.js';
/*** 按钮:variant 控制视觉强度,onClick 为点击回调 ***/ /*** 按钮:variant 控制视觉强度,disabled 支持布尔或信号禁用,onClick 为点击回调 ***/
export function button(props: ButtonProps): HTMLElement { export function button(props: ButtonProps): HTMLElement {
return h( return h(
'button', 'button',
{ class: `ua-btn ua-btn-${props.variant ?? 'primary'}`, onClick: props.onClick }, { class: `ua-btn ua-btn-${props.variant ?? 'primary'}`, disabled: props.disabled, onClick: props.onClick }, // false/undefined 移除属性,Signal 走响应式
props.label, props.label,
); );
} }
+2 -2
View File
@@ -1,9 +1,9 @@
import { effect, h } from '@ui-arch/frame'; import { effect, h } from '@ui-arch/frame';
import type { CheckboxProps } from './types.js'; import type { CheckboxProps } from './types.js';
/*** 复选框:checked 信号双向绑定,onChange 为变更回调 ***/ /*** 复选框:checked 信号双向绑定,disabled 支持布尔或信号禁用,onChange 为变更回调 ***/
export function checkbox(props: CheckboxProps): HTMLElement { export function checkbox(props: CheckboxProps): HTMLElement {
const el = h('input', { type: 'checkbox', class: 'ua-checkbox' }) as HTMLInputElement; const el = h('input', { type: 'checkbox', class: 'ua-checkbox', disabled: props.disabled }) as HTMLInputElement; // false/undefined 移除属性,Signal 走响应式
if (props.checked) { if (props.checked) {
const checked = props.checked; const checked = props.checked;
el.addEventListener('change', () => checked(el.checked)); // 用户勾选写回信号 el.addEventListener('change', () => checked(el.checked)); // 用户勾选写回信号
+2 -2
View File
@@ -1,9 +1,9 @@
import { effect, h } from '@ui-arch/frame'; import { effect, h } from '@ui-arch/frame';
import type { SwitchProps } from './types.js'; import type { SwitchProps } from './types.js';
/*** 开关:checked 信号双向绑定,轨道 + 滑块的纯 CSS 实现 ***/ /*** 开关:checked 信号双向绑定,disabled 支持布尔或信号禁用,轨道 + 滑块的纯 CSS 实现 ***/
export function switchButton(props: SwitchProps): HTMLElement { export function switchButton(props: SwitchProps): HTMLElement {
const input = h('input', { type: 'checkbox', class: 'ua-switch-input' }) as HTMLInputElement; const input = h('input', { type: 'checkbox', class: 'ua-switch-input', disabled: props.disabled }) as HTMLInputElement; // false/undefined 移除属性,Signal 走响应式
if (props.checked) { if (props.checked) {
const checked = props.checked; const checked = props.checked;
input.addEventListener('change', () => checked(input.checked)); // 用户切换写回信号 input.addEventListener('change', () => checked(input.checked)); // 用户切换写回信号
+3
View File
@@ -12,6 +12,7 @@ export interface TooltipProps {
export interface ButtonProps { export interface ButtonProps {
label: string; // 按钮文案 label: string; // 按钮文案
variant?: 'primary' | 'ghost' | 'danger'; // 视觉强度;缺省 primary variant?: 'primary' | 'ghost' | 'danger'; // 视觉强度;缺省 primary
disabled?: boolean | Signal<boolean>; // 禁用态:布尔直接置位,传信号则动态同步
onClick?: () => void; // 点击回调 onClick?: () => void; // 点击回调
} }
@@ -48,6 +49,7 @@ export interface OptionItem {
export interface CheckboxProps { export interface CheckboxProps {
label?: string; // 右侧文案;缺省不渲染 label?: string; // 右侧文案;缺省不渲染
checked?: Signal<boolean>; // 勾选状态信号,双向绑定 checked?: Signal<boolean>; // 勾选状态信号,双向绑定
disabled?: boolean | Signal<boolean>; // 禁用态:布尔直接置位,传信号则动态同步
onChange?: (checked: boolean) => void; // 变更回调 onChange?: (checked: boolean) => void; // 变更回调
} }
@@ -55,6 +57,7 @@ export interface CheckboxProps {
export interface SwitchProps { export interface SwitchProps {
label?: string; // 左侧文案;缺省不渲染 label?: string; // 左侧文案;缺省不渲染
checked?: Signal<boolean>; // 开关状态信号,双向绑定 checked?: Signal<boolean>; // 开关状态信号,双向绑定
disabled?: boolean | Signal<boolean>; // 禁用态:布尔直接置位,传信号则动态同步
onChange?: (checked: boolean) => void; // 变更回调 onChange?: (checked: boolean) => void; // 变更回调
} }
+18 -3
View File
@@ -13,11 +13,11 @@
"api": { "api": {
"entry": "src/index.ts", "entry": "src/index.ts",
"exports": [ "exports": [
"button(props):按钮,variant = primary | ghost | danger", "button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用",
"textField(props):文本输入,value 信号双向绑定", "textField(props):文本输入,value 信号双向绑定",
"textarea(props):多行输入,value 信号双向绑定", "textarea(props):多行输入,value 信号双向绑定",
"checkbox(props):复选框,checked 信号双向绑定", "checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"switchButton(props):开关,checked 信号双向绑定", "switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画", "select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画",
"radioGroup(props):单选组,options + value 信号双向绑定", "radioGroup(props):单选组,options + value 信号双向绑定",
"card(props, ...children):卡片容器", "card(props, ...children):卡片容器",
@@ -95,6 +95,11 @@
"d": "视觉强度;缺省 primary", "d": "视觉强度;缺省 primary",
"df": "primary" "df": "primary"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onClick", "n": "onClick",
"t": "() => void", "t": "() => void",
@@ -188,6 +193,11 @@
"t": "string", "t": "string",
"d": "右侧文案;缺省只渲染勾选框" "d": "右侧文案;缺省只渲染勾选框"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onChange", "n": "onChange",
"t": "(checked: boolean) => void", "t": "(checked: boolean) => void",
@@ -217,6 +227,11 @@
"t": "string", "t": "string",
"d": "左侧文案" "d": "左侧文案"
}, },
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步"
},
{ {
"n": "onChange", "n": "onChange",
"t": "(checked: boolean) => void", "t": "(checked: boolean) => void",
+11
View File
@@ -773,6 +773,17 @@
transform: translateX(-50%) translateY(0); transform: translateX(-50%) translateY(0);
} }
/* —— 通用禁用态:置灰 + 禁用光标 —— */
.ua-btn:disabled,
.ua-checkbox:disabled,
.ua-switch-input:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.ua-switch-input:disabled + .ua-switch-track {
opacity: 0.45;
}
/* —— 无障碍:用户偏好减少动效时关闭全部动画 —— */ /* —— 无障碍:用户偏好减少动效时关闭全部动画 —— */
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.ua-btn, .ua-btn,