Repository navigation
🐛 修复新建脚本按钮点击被 hover 菜单吞掉,改为直接新建用户脚本 - #1704
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist / 检查清单
背景
Fix #1699。报告人指出「不能直接點擊 Create Script」,并猜测「Create Script 的點擊跟 hover 撞了」——这个猜测是对的。
桌面工具栏的
+ Create Script按钮同时承担两个角色:DropdownMenuTrigger(asChild,pointerdown 会onOpenToggle);useHoverMenu()的 hover 触发目标(onMouseEnter→setIsOpen(true))。菜单
open由useHoverMenu受控。鼠标移上按钮 → hover 已把菜单打开;此时按下鼠标 → Radix 调onOpenChange(!open)=false→ 菜单被关掉。而鼠标并未离开按钮,不会再触发mouseEnter,所以要移开再移回、或者再点一次才能重新展开。复现(本地 vitest,改动前):
mouseEntertrigger → 菜单展开;原地pointerDown+click→ 菜单消失;再点一次 → 又展开。用户视角就是「鼠标移上去菜单弹出来,手一按菜单没了,点了没反应」。除此之外还有一层预期落差:按钮长得像主操作按钮(
+图标 +Create Script文案),但整块区域只是下拉触发器,没有任何直接新建脚本的行为;要新建必须再进菜单点Create User Script。该按钮自新 UI 重写(#1514)引入后一直是这个行为;现有单测只覆盖了 hover 展开与菜单项点击,没有覆盖「hover 之后点 trigger」这条路径。
本次改动
把「点击」的语义交给新建脚本,同时保证没有 hover 能力的设备仍能打开菜单。判据是
(hover: hover)媒体查询而非视口宽度:ArrowDown展开菜单,点击 /Enter/Space直接新建用户脚本。+图标按钮、以及触摸设备上的桌面工具栏):一律点击展开菜单,与原行为一致。Enter/SpaceArrowDown+图标新增
src/pages/components/use-can-hover.ts(useCanHover),与既有的use-is-mobile.ts同构:useSyncExternalStore订阅(hover: hover),接上/拔掉鼠标时会更新。菜单内容、导入分组、
LinkImportDialog均未改动;菜单里的Create User Script项改为复用同一个createUserScript函数。无视觉变化。实现考虑
为什么按 hover 能力而不是视口宽度分支。 桌面工具栏在视口 ≥768px 就渲染(
useIsMobile的断点),平板横屏、触屏笔记本都落在这个区间但没有 hover。若这些设备也走 hover 菜单,下拉里的「后台脚本 / 定时脚本 / 导入本地 / 链接导入 / 导入 Skill」五个入口将完全无法触达——这会是比原 issue 更严重的回归。因此触摸设备复用已有的点击菜单路径(isHoverMenu === false),该路径本身已有测试覆盖,且不套用useHoverMenu的 dismiss 拦截,Esc 与点击外部都能正常关闭。为什么用
preventDefault()拦 Radix 的 toggle。DropdownMenuTrigger用composeEventHandlers(props.onPointerDown, …)挂载 toggle,而composeEventHandlers在event.defaultPrevented时会跳过自己那一半;asChild走Slot,其mergeProps对on[A-Z]*属性的合成顺序是「先子元素 handler,后 slot handler」。因此在Button上挂onPointerDown={(e) => e.preventDefault()}可以稳定拦掉 toggle,同时不影响click照常派发(取消pointerdown只阻止兼容鼠标事件与聚焦,不阻止click)。这一依赖已写进代码注释。版本已核对:@radix-ui/react-slot@1.2.5、@radix-ui/react-dropdown-menu@2.1.17(radix-ui@1.5.0)。e2e 环境需要显式声明指针能力。 首次推送后 CI 的
Run E2E tests (2/4)失败:两条桌面用例挂掉、触摸用例通过——正是canHover === false的症状。原因是无头 Linux 检测不到任何输入设备,把(hover: hover)/(pointer: fine)报成false,而无头 macOS 报true,同一套用例在两个平台结果不同。因此在e2e/fixtures.ts的共享启动参数里加上--blink-settings=availableHoverTypes=2,primaryHoverType=2,availablePointerTypes=4,primaryPointerType=4,让默认环境稳定对应「有鼠标的桌面」;触摸用例自建上下文覆盖,不受影响。同时给 hover 用例加了一行前置断言(hover: hover) === true,以后环境再变能一眼区分「环境问题」与「功能回归」。键盘单独处理。 Radix 在
Enter/Space上除了 toggle 还会preventDefault()(顺带吃掉原生 click),所以这两个键在自己的onKeyDown里拦下并直接调用createUserScript();ArrowDown不拦,仍交给 Radix 展开菜单——即「带默认操作的菜单按钮」的常规键盘模型。已知限制
ChevronDown在可 hover 的设备上不再是「点这里展开」的可点击 affordance,而只是「还有更多选项」的提示。本 PR 未调整其样式。preventDefault()拦截 pointerdown 会同时抑制该按钮的鼠标聚焦。由于点击后即导航到编辑器,实际影响可忽略;键盘 Tab 聚焦不受影响。+按钮一致。Slot的 handler 合成顺序与composeEventHandlers的defaultPrevented短路,属于 Radix 的公开行为约定,但升级 Radix 大版本时值得回归这几条测试。(hover: hover)取决于浏览器检测到的主指针。若某些环境(远程桌面、部分 Linux 配置)在有鼠标时仍报hover: none,这些用户会退化为「点击展开菜单」,即本 PR 之前、且不含 [BUG] (UI UX)不能直接點擊"Create Script" #1699 碰撞的行为。降级方向是安全的:判据只会导致「少一个直达入口」,不会导致「菜单够不着」。建议审查重点
+图标是否仍为点击展开、Esc 可关(variant="icon"未改)。ArrowDown展开菜单、Enter/Space新建脚本。data-tour="install-entry"(src/pages/options/onboarding/steps.ts)仍指向同一按钮,未受影响。关联
Fix #1699
验证
两处行为改动均先写失败测试再改实现:
CreateScriptMenu.test.tsx先加 3 条(hover 后点击、无 hover 直接点击、键盘 Enter/ArrowDown)确认全红;触摸降级再加 2 条(点击展开菜单不导航、Esc 可关)确认全红。e2e 侧:把原来断言「点击展开菜单」的用例改为 hover 版,新增「点击应直接进入编辑器」,并新增一条触摸设备用例。Playwright 的
.click()会先把鼠标移到元素上(触发 hover 展开)再点击,因此那条用例正好在真实 Chromium 中覆盖 #1699 的原始路径。CI 上的 e2e 失败已定位并修复,过程留档:先用
--blink-settings=...HoverTypes=1...PointerTypes=1(强制「无指针」)在本地复现,两条桌面用例以与 CI 完全相同的报错失败、触摸用例通过,确认是环境的指针能力而非功能问题;再用探针验证该 flag 双向可控(默认hover:true→ 强制 none 得false→ 强制 hover 得true),据此在共享 fixture 中固定为「有鼠标的桌面」。因改动了共享 fixture,本地跑了全量 e2e:64 passed。触摸用例需要真实的无 hover 环境:CDP
Emulation.setEmulatedMedia的hover/pointer特性对chrome-extension://页面不生效(实测(hover: hover)仍为true),因此该用例自行以hasTouch: true+isMobile: true+viewport 1200×800启动持久化上下文(参照gm-api.spec.ts自建上下文的做法),并在断言前先探测确认(hover: hover) === false且innerWidth ≥ 768,再tap()断言菜单展开且 URL 未跳转。一处需要说明的观测:期间有两次
src/pages全量运行出现 1–3 条无关文件(SubscribeListMobile/GeneralSection/SettingsPane/StoragePane)的失败,每次失败集合不同,单独重跑均通过;随后在本分支与干净main上各连续跑 3 次全量,均 100% 通过(本分支 1358/1358,main1355/1355)。判断为vitest.config.ts中uiproject 已知的超时预算在机器满载时的偶发抖动(该文件注释已记录此问题),与本改动无关。Screenshots / 截图
无视觉变化——按钮外观、布局、菜单内容均未改动,本次仅改变点击/键盘的行为语义,详见上文行为对照表。