From 37f11911b117ed26033cbf804e389b90cb9a62de Mon Sep 17 00:00:00 2001 From: GouJ Date: Fri, 4 Sep 2026 10:29:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=AE=80=E5=8C=96=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E7=82=B9=E5=87=BB=E6=8F=8F=E8=BE=B9=E5=B9=B6=E4=BF=9D=E7=95=99?= =?UTF-8?q?=E9=94=AE=E7=9B=98=E7=84=A6=E7=82=B9=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ui/flatTheme.test.ts | 19 +++++++++++++++++++ src/composables/useTheme.ts | 4 +++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/components/ui/flatTheme.test.ts b/src/components/ui/flatTheme.test.ts index 1532a3b..95caafe 100644 --- a/src/components/ui/flatTheme.test.ts +++ b/src/components/ui/flatTheme.test.ts @@ -60,6 +60,8 @@ describe('全站平面主题', () => { expect(active.style.getPropertyValue(property)).toBe('#ffffff') } expect(active.style.getPropertyValue('--n-color')).toBe('#078640') + expect(active.style.getPropertyValue('--n-border-focus')).toBe('none') + expect(active.style.getPropertyValue('--n-wave-opacity')).toBe('0') expect(disabled.style.getPropertyValue('--n-color-disabled')).toBe(dark ? '#303030' : '#e4e4e4') expect(disabled.style.getPropertyValue('--n-text-color-disabled')).toBe(dark ? '#808080' : '#8c8c8c') expect(disabled.disabled).toBe(true) @@ -102,6 +104,12 @@ describe('全站平面主题', () => { } for (const selector of ['.n-button', '.normal-input', '.n-base-selection']) { expect(value(selector, '--n-border')).toBe('none') + } + // 普通按钮点击后不残留深绿描边,输入和选择控件仍保留聚焦边界。 + expect(value('.n-button', '--n-border-focus')).toBe('none') + expect(value('.n-button', '--n-wave-opacity')).toBe('0') + expect(wrapper.getComponent(NButton).props('focusable')).toBe(true) + for (const selector of ['.normal-input', '.n-base-selection']) { expect(value(selector, '--n-border-focus')).toContain(dark ? '#5cd693' : '#087c42') } expect(value('.n-button', '--n-color')).toBe(control) @@ -122,6 +130,17 @@ describe('全站平面主题', () => { expect(value('.n-tabs', '--n-tab-border-color')).toBe(dark ? '#333333' : '#dadada') }) + it('普通按钮只在键盘焦点可见时显示外框,不用失焦或禁止聚焦隐藏点击反馈', () => { + // DOM 环境不模拟真实鼠标/键盘焦点判定,保护共享 CSS 与触发器契约。 + const css = readFileSync('src/admin.css', 'utf8') + expect(css).toMatch( + /\.n-button:focus-visible\s*\{[^}]*outline:\s*2px solid var\(--app-accent-text\);[^}]*outline-offset:\s*2px;/ + ) + const tools = readFileSync('src/components/ui/WorkspaceTools.vue', 'utf8') + expect(tools).not.toContain('.blur(') + expect(tools).not.toContain(':focusable="false"') + }) + it('单图标按钮以当前控件高度为边长,尺寸与内容按钮互不影响', () => { // happy-dom 不计算几何尺寸,此项约束共用样式和调用方,实际布局仍需浏览器验收。 const css = readFileSync('src/admin.css', 'utf8') diff --git a/src/composables/useTheme.ts b/src/composables/useTheme.ts index a6090e4..d44538e 100644 --- a/src/composables/useTheme.ts +++ b/src/composables/useTheme.ts @@ -107,7 +107,9 @@ export function useTheme() { borderHover: 'none', borderPressed: 'none', borderDisabled: 'none', - borderFocus: focusBorder, + // 点击只通过底色反馈,避免残留绿框和向外扩散的粗波纹;键盘焦点由 :focus-visible 保留。 + borderFocus: 'none', + waveOpacity: '0', opacityDisabled: '1', colorDisabled: disabledColor, textColorDisabled: disabledText,