From f873baf66a58f8eabe2ea03363473ab06daa3b64 Mon Sep 17 00:00:00 2001 From: HIsheR Date: Tue, 27 Oct 2026 00:43:55 +0800 Subject: [PATCH] =?UTF-8?q?iter(g313):=20sortableList=20=E7=A6=81=E7=94=A8?= =?UTF-8?q?=E6=80=81=E8=A1=A5=E8=A7=86=E8=A7=89=E7=BA=BF=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 9 +++++++++ .ua/index.json | 7 ++++--- apps/demo/main.ts | 2 ++ llms-full.txt | 5 +++-- packages/skin/ui/src/sortableList.ts | 6 ++++++ packages/skin/ui/ua.manifest.json | 5 +++-- packages/skin/ui/ui.css | 12 ++++++++++++ 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/.ua/backlog.json b/.ua/backlog.json index b14bbeb..3c87a40 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -3203,6 +3203,15 @@ "motivation": "emptyRow 只区分「筛掉了」与「真没数据」,但两种情况都只给文案——列表本来就空时没有「新建」这类下一步,用户只能自己找工具栏;而筛选没结果时又该引导清条件,两种语义不该共用一个按钮位。", "acceptance": "① DataTableProps 新增 emptyAction 插槽,只在「真没数据」时渲染在占位文案右侧;② 有筛选词时该位置仍是「清除筛选」,两者互斥;③ manifest 参数表与手把手、类型注释同步;④ npm run check 全绿。", "notes": "" + }, + { + "id": "g313", + "domain": "tune", + "status": "open", + "title": "sortableList 禁用态没有任何视觉线索", + "motivation": "disabled 只拦住了 dragstart 与键盘搬位,界面上一模一样:光标还是 grab、悬停照样变色,用户拖三次没反应只会以为组件坏了。", + "acceptance": "① 根节点按 disabled 切换 is-disabled 类与 aria-disabled(布尔与信号两种读法都响应);② 禁用时行光标回默认、文字退次级色、把手退到边框色、悬停与按下都不再给底色反馈;③ manifest 的 disabled 说明与手把手补一条,demo 增一个禁用实例;④ audit:visual / audit:contrast 全绿,npm run check 通过。", + "notes": "" } ] } diff --git a/.ua/index.json b/.ua/index.json index 56f287a..747a18e 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T16:42:26.169Z", + "generatedAt": "2026-10-26T16:43:41.739Z", "repoRoot": ".", "packages": [ { @@ -4693,7 +4693,7 @@ { "n": "disabled", "t": "boolean | Signal", - "d": "禁用拖拽与键盘搬位;缺省 false", + "d": "禁用拖拽与键盘搬位,同时整体置灰退到不可交互那一档(光标与悬停都不再给反馈);缺省 false", "df": "false" }, { @@ -4710,7 +4710,8 @@ "被拖的行以虚线边 + 抬升投影标示(不用整行降透明度:那会把正文对比压到 4.86,低于正文 7:1 口径),落点由指针位置决定,不会出现「拖了三格只动一格」的错觉", "外部要按代码调整顺序用句柄 move(from, to),下标越界或禁用时静默忽略;order() 以 DOM 为唯一真相回读当前顺序", "条目超过一屏也能拖:指针进入最近滚动祖先(overflow-y 为 auto/scroll 且内容确已溢出)上下 48px 感应带即按帧自动滚,松手或离开感应带立刻停;找不到滚动祖先(整页跟随滚动)时不接管滚动,交给浏览器", - "什么时候别用:需要严格的两级联动排序(树 / 表格分组)时它不够用,得自己在 onChange 里按父节点重排;跨列表搬运用两个实例各自持有顺序信号" + "什么时候别用:需要严格的两级联动排序(树 / 表格分组)时它不够用,得自己在 onChange 里按父节点重排;跨列表搬运用两个实例各自持有顺序信号", + "只看不改时传 disabled:光标回到默认、文字退到次级色、悬停与按下都不再变色,读屏播报 aria-disabled——禁用态最忌「看着能拖、拖了没反应」" ] }, { diff --git a/apps/demo/main.ts b/apps/demo/main.ts index 38f900e..2e6d6a4 100644 --- a/apps/demo/main.ts +++ b/apps/demo/main.ts @@ -1930,6 +1930,8 @@ content.append( { class: 'col' }, sortableDemo.el, h('p', { class: 'desc' }, () => `当前顺序:${sortableOrder().join(' → ')}`), + h('p', { class: 'desc' }, '禁用态:拖不动也不骗人——光标回默认、文字退次级色、悬停与按下都不再给反馈'), + sortableList({ items: ['已冻结:需求评审', '已冻结:接口联调'], disabled: true }).el, ), ), section( diff --git a/llms-full.txt b/llms-full.txt index 6364477..8dafa81 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T16:42:26.169Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T16:43:41.739Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -2508,7 +2508,7 @@ noticeBar({ text: '系统将于今晚 23:00 维护 10 分钟', scroll: true }) - items(必填):string[] —— 全部条目文案;文案即排序键,要求唯一(重名会让顺序回读撞车) - value:Signal —— 受控顺序信号;传了则内部改动写回,外部改动即重排(拖拽中跳过) - onChange(回调):(next: string[]) => void —— 顺序变化回调,拖放落定 / 键盘搬位 / move 调用后各触发一次 -- disabled(默认 false):boolean | Signal —— 禁用拖拽与键盘搬位;缺省 false +- disabled(默认 false):boolean | Signal —— 禁用拖拽与键盘搬位,同时整体置灰退到不可交互那一档(光标与悬停都不再给反馈);缺省 false - emptyText:string —— 无条目占位文案;缺省「暂无可排序项」 示例: @@ -2527,6 +2527,7 @@ container.append(sort.el); 5. 外部要按代码调整顺序用句柄 move(from, to),下标越界或禁用时静默忽略;order() 以 DOM 为唯一真相回读当前顺序 6. 条目超过一屏也能拖:指针进入最近滚动祖先(overflow-y 为 auto/scroll 且内容确已溢出)上下 48px 感应带即按帧自动滚,松手或离开感应带立刻停;找不到滚动祖先(整页跟随滚动)时不接管滚动,交给浏览器 7. 什么时候别用:需要严格的两级联动排序(树 / 表格分组)时它不够用,得自己在 onChange 里按父节点重排;跨列表搬运用两个实例各自持有顺序信号 +8. 只看不改时传 disabled:光标回到默认、文字退到次级色、悬停与按下都不再变色,读屏播报 aria-disabled——禁用态最忌「看着能拖、拖了没反应」 现场演示:apps/docs/demo.html#sec-sortable diff --git a/packages/skin/ui/src/sortableList.ts b/packages/skin/ui/src/sortableList.ts index 7179c49..362e9a5 100644 --- a/packages/skin/ui/src/sortableList.ts +++ b/packages/skin/ui/src/sortableList.ts @@ -46,6 +46,12 @@ export function sortableList(props: SortableListProps): SortableListHandle { ...(props.value ? props.value() : props.items).map((text) => rows.get(text)).filter((row): row is HTMLElement => !!row), ) as HTMLElement; syncAria(); + // 禁用态:拖不动就得看得出来——否则用户反复拖拽无反应,以为组件坏了 + effect(() => { + const off = disabled(); + root.classList.toggle('is-disabled', off); + root.setAttribute('aria-disabled', String(off)); // 读屏同样能播报「当前不可调整」 + }); // —— 鼠标 / 触摸拖放:dragstart 记源行,dragover 就地搬节点,dragend 落定提交 —— /*** 最近的纵向滚动祖先:拖到边缘要能自动滚,否则长列表根本拖不到视口外 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index f0849c0..81417a9 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -4564,7 +4564,7 @@ { "n": "disabled", "t": "boolean | Signal", - "d": "禁用拖拽与键盘搬位;缺省 false", + "d": "禁用拖拽与键盘搬位,同时整体置灰退到不可交互那一档(光标与悬停都不再给反馈);缺省 false", "df": "false" }, { @@ -4581,7 +4581,8 @@ "被拖的行以虚线边 + 抬升投影标示(不用整行降透明度:那会把正文对比压到 4.86,低于正文 7:1 口径),落点由指针位置决定,不会出现「拖了三格只动一格」的错觉", "外部要按代码调整顺序用句柄 move(from, to),下标越界或禁用时静默忽略;order() 以 DOM 为唯一真相回读当前顺序", "条目超过一屏也能拖:指针进入最近滚动祖先(overflow-y 为 auto/scroll 且内容确已溢出)上下 48px 感应带即按帧自动滚,松手或离开感应带立刻停;找不到滚动祖先(整页跟随滚动)时不接管滚动,交给浏览器", - "什么时候别用:需要严格的两级联动排序(树 / 表格分组)时它不够用,得自己在 onChange 里按父节点重排;跨列表搬运用两个实例各自持有顺序信号" + "什么时候别用:需要严格的两级联动排序(树 / 表格分组)时它不够用,得自己在 onChange 里按父节点重排;跨列表搬运用两个实例各自持有顺序信号", + "只看不改时传 disabled:光标回到默认、文字退到次级色、悬停与按下都不再变色,读屏播报 aria-disabled——禁用态最忌「看着能拖、拖了没反应」" ] }, { diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index 74628c0..1a7a24c 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -2748,6 +2748,18 @@ button.ua-step-dot:hover { line-height: var(--ua-leading-none); transition: color var(--ua-duration-fast) var(--ua-ease); } +/* 禁用态:光标不再承诺可拖,底色与文字一起退到不可交互那一档 */ +.ua-sortable.is-disabled .ua-sortable-item { + cursor: default; + color: var(--ua-color-text-muted); +} +.ua-sortable.is-disabled .ua-sortable-item:hover, +.ua-sortable.is-disabled .ua-sortable-item:active { + background: var(--ua-color-surface); /* 悬停与按下都不再给反馈:禁用态任何「动了」的暗示都是误导 */ +} +.ua-sortable.is-disabled .ua-sortable-grip { + color: var(--ua-color-border); +} /* —— 轮播 —— */ .ua-carousel {