iter: d02 select/radioGroup 补 disabled + 修复 select 箭头旋转

This commit is contained in:
ui-arch-bot
2026-10-23 16:47:03 +08:00
parent 84277a744e
commit 6b9fa95d1e
11 changed files with 75 additions and 15 deletions
+6 -1
View File
@@ -6,7 +6,12 @@ export function radioGroup(props: RadioGroupProps): HTMLElement {
const groupName = `ua-radio-${Math.random().toString(36).slice(2, 8)}`; // 组内唯一 name
const radios: HTMLInputElement[] = [];
for (const opt of props.options) {
const input = h('input', { type: 'radio', name: groupName, class: 'ua-radio' }) as HTMLInputElement;
const input = h('input', {
type: 'radio',
name: groupName,
class: 'ua-radio',
disabled: props.disabled, // 布尔或信号禁用,h() 直接透传
}) as HTMLInputElement;
input.value = opt.value;
radios.push(input);
input.addEventListener('change', () => {
+2 -1
View File
@@ -24,6 +24,7 @@ export function select(props: SelectProps): HTMLElement {
class: 'ua-select-trigger',
'aria-haspopup': 'listbox',
'aria-expanded': () => String(open()),
disabled: props.disabled, // 布尔或信号禁用,h() 直接透传(原生 button 拦截点击)
onClick: () => open(!open()),
},
h('span', { class: () => `ua-select-value${value() ? '' : ' is-empty'}` }, () => current() || props.placeholder || ''),
@@ -46,7 +47,7 @@ export function select(props: SelectProps): HTMLElement {
);
const pop = h('div', { class: () => `ua-select-pop${open() ? ' ua-open' : ''}`, role: 'listbox' }, ...options);
const root = h('div', { class: 'ua-select' }, trigger, pop);
const root = h('div', { class: () => `ua-select${open() ? ' ua-open' : ''}` }, trigger, pop); // 根带开合类,供箭头旋转
root.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape') open(false); // Esc 关闭弹层
+2
View File
@@ -67,6 +67,7 @@ export interface SelectProps {
options: OptionItem[]; // 选项列表
value?: Signal<string>; // 选中值信号,双向绑定
placeholder?: string; // 未选中时的占位项文案
disabled?: boolean | Signal<boolean>; // 禁用态:布尔直接置位,传信号则动态同步
onChange?: (value: string) => void; // 变更回调
}
@@ -74,6 +75,7 @@ export interface SelectProps {
export interface RadioGroupProps {
options: OptionItem[]; // 选项列表
value?: Signal<string>; // 选中值信号,双向绑定
disabled?: boolean | Signal<boolean>; // 禁用态:整组置灰且不可选
onChange?: (value: string) => void; // 变更回调
}
+14 -3
View File
@@ -18,9 +18,9 @@
"textarea(props):多行输入,value 信号双向绑定,disabled 支持布尔或信号禁用",
"checkbox(props):复选框,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"switchButton(props):开关,checked 信号双向绑定,disabled 支持布尔或信号禁用",
"select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画",
"select(props):自绘下拉选择(非原生 select),value 信号双向绑定,点外部 / Esc 关闭,选项弹层带微动画,disabled 支持布尔或信号禁用",
"menu(props):下拉菜单,触发器 + 自绘弹层,条目支持禁用 / 危险 / 分隔线,↑↓ 环形导航,点外部 / Esc 关闭",
"radioGroup(props):单选组,options + value 信号双向绑定",
"radioGroup(props):单选组,options + value 信号双向绑定,disabled 整组禁用",
"card(props, ...children):卡片容器",
"badge(props):徽标,variant = default | success | warning | danger",
"alert(props):提示条,variant = info | success | warning | danger",
@@ -280,6 +280,11 @@
"t": "string",
"d": "未选中时触发器显示的占位文案"
},
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "禁用态:布尔直接置位,传信号则动态同步;禁用时触发器置灰且不展开弹层"
},
{
"n": "onChange",
"t": "(value: string) => void",
@@ -356,6 +361,11 @@
"t": "Signal<string>",
"d": "选中值信号,双向绑定"
},
{
"n": "disabled",
"t": "boolean | Signal<boolean>",
"d": "整组禁用:全部选项与文案置灰且不可选"
},
{
"n": "onChange",
"t": "(value: string) => void",
@@ -367,7 +377,8 @@
"steps": [
"创建字符串信号,初值设为默认选项的 value",
"传入 options 与 value,组内自动互斥",
"读取 size() 获取当前选中值"
"读取 size() 获取当前选中值",
"需要整组禁用时传 disabled:布尔值静态禁用,也可传信号(如 locked)实现动态锁定"
]
},
{
+12 -1
View File
@@ -852,9 +852,20 @@
/* —— 通用禁用态:置灰 + 禁用光标 —— */
.ua-btn:disabled,
.ua-checkbox:disabled,
.ua-radio:disabled,
.ua-switch-input:disabled,
.ua-input:disabled,
.ua-textarea:disabled {
.ua-textarea:disabled,
.ua-select-trigger:disabled {
opacity: 0.45;
cursor: not-allowed;
}
/* 禁用时悬停不改边框色,避免误以为可交互 */
.ua-select-trigger:disabled:hover {
border-color: var(--ua-color-border);
}
/* 单选组禁用:整行文案同步弱化 */
.ua-check-row:has(.ua-radio:disabled) {
opacity: 0.45;
cursor: not-allowed;
}