fix(ui): compact context menus + viewport-clamped submenu flip
减重:全部右键菜单(FileTree 行菜单 / TabBar tab 菜单 / GitLens 文件与 历史菜单 / FreeWindow 标题菜单)与「+」菜单切到宿主 Menu 原语的 compact 密度(26px 行高 / 12px 字 / 164px 卡片),图标随槽位 16→14,「打开方式」 子菜单图钉 20→16,还原工具型右键菜单的趁手感。 越界:宿主子菜单纯 CSS 定位(从父行向上、向右生长)不受视口钳制——树顶 部右键时「打开方式 ▸」子菜单伸出视口上沿,窄面板(280–400px)时伸出右 沿。新增 menu-flip.ts:菜单打开期间在 <body> 发布 data-dsh-sidebar-submenu ="down|left" 方向 token(y < vh/2 → down;x + 400 > vw → left),layout.css 据此翻转子菜单生长方向与 ::before 悬停桥;属性存续期即作用域,宿主自有 菜单不受影响。刻意不做 max-height 滚动钳制——overflow 裁剪会切断悬停桥。 测试:menu-flip.spec.tsx(token 纯函数 + hook 生命周期 + CSS 契约跨文件 一致性);tab-bar / file-tree 两个 spec 追加翻转向量断言;mount.e2e 追加 compact 行高(≤30px)布局级证据。设计偏差记录同步至 docs/plans/2026-08-22-open-with-menu-design.md。
This commit is contained in:
@@ -111,3 +111,40 @@ body[data-dsh-sidebar-dragging] #root [data-dsh-center-col],
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Context-menu submenu flip (viewport clamping for the portaled menus).
|
||||
*
|
||||
* The ui-primitives Menu clamps its main portal list into the viewport but
|
||||
* positions nested submenus with static CSS only — anchored at the parent
|
||||
* row's bottom, growing UP and to the RIGHT — with no clamp whatsoever.
|
||||
* Docked on the window's right edge, both defaults are the worst case for
|
||||
* this panel: a tall "open with" submenu escapes past the viewport top when
|
||||
* the row menu opens near the top, and past the right edge on narrow panels
|
||||
* (PANEL_MIN 280 < card 218 + gap + submenu 165).
|
||||
*
|
||||
* menu-flip.ts publishes `data-dsh-sidebar-submenu` on <body> — with the
|
||||
* words "down" and/or "left" — for exactly the lifetime of one of OUR
|
||||
* submenu-bearing menus (FileTree row menu, TabBar tab menu). The tokens
|
||||
* flip the growth direction; the attribute's absence restores the
|
||||
* primitive's own geometry untouched, and host-owned menus are never
|
||||
* affected because they never open while the attribute exists (each side
|
||||
* closes on the other's outside pointerdown).
|
||||
*
|
||||
* No max-height/overflow scroll cap here on purpose: overflow clipping
|
||||
* would cut the submenu's ::before hover bridge (the 10px corridor that
|
||||
* keeps itemWrap's mouseleave from closing the card mid-crossing). */
|
||||
body[data-dsh-sidebar-submenu~="down"] div[role="menu"] div[role="menu"] {
|
||||
top: -4px;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
body[data-dsh-sidebar-submenu~="left"] div[role="menu"] div[role="menu"] {
|
||||
left: auto;
|
||||
right: calc(100% + 10px);
|
||||
}
|
||||
|
||||
/* The hover bridge follows the card to the left side of the parent row. */
|
||||
body[data-dsh-sidebar-submenu~="left"] div[role="menu"] div[role="menu"]::before {
|
||||
left: auto;
|
||||
right: -10px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user