fix(workbench): restore focus on a second Alt and keep closed menus closed

Цей коміт міститься в:
l0ng-ai committed 2026-10-31 20:31:30 +08:00
1 джерело f566efb91a
коміт 2a2d1b636d
2 files changed
+51 -3

No files matched your search

+39
Переглянути файл
@@ -156,6 +156,45 @@ describe("main menu presentation", () => {
expect(editor).toHaveFocus();
});
it("returns focus on a second lone Alt", async () => {
setStyle("merged");
render(
<>
<button>Editor</button>
<MainMenu />
</>,
);
await screen.findByRole("menubar");
const editor = screen.getByRole("button", { name: "Editor" });
editor.focus();
alt();
expect(titles().getByRole("menuitem", { name: "File" })).toHaveFocus();
alt();
expect(editor).toHaveFocus();
alt();
fireEvent.keyDown(document.activeElement!, { key: "Escape" });
expect(editor).toHaveFocus();
});
it("does not reopen a title's menu after the titles collapse and return", async () => {
setStyle("merged");
render(<MainMenu />);
await screen.findByRole("menubar");
fireEvent.click(titles().getByRole("menuitem", { name: "Edit" }));
expect(await screen.findByRole("menu", { name: "Edit" })).toBeInTheDocument();
act(() => {
available = 100;
resize();
});
expect(screen.queryByRole("menu")).toBeNull();
act(() => {
available = 500;
resize();
});
expect(screen.getByRole("menubar")).toBeInTheDocument();
expect(screen.queryByRole("menu")).toBeNull();
});
it("falls back to a hamburger popup when narrow and restores titles when space returns", async () => {
available = 100;
setStyle("merged");
+12 -3
Переглянути файл
@@ -122,7 +122,13 @@ function MainMenuBar({ merged, onExpandedChange }: MainMenuProps & { merged: boo
// Measuring the allocated slot includes all neighbouring toolbar/caption controls.
useLayoutEffect(() => {
if (!merged || !slot.current || !measure.current) return;
const update = () => setFits(menus.length > 0 && slot.current!.clientWidth >= measure.current!.scrollWidth);
const update = () => {
const next = menus.length > 0 && slot.current!.clientWidth >= measure.current!.scrollWidth;
setFits(next);
// Each presentation's menu closes with it, and must not reopen when it returns.
if (next) setExpanded(false);
else setOpen(null);
};
const observer = new ResizeObserver(update);
observer.observe(slot.current);
observer.observe(measure.current);
@@ -161,8 +167,11 @@ function MainMenuBar({ merged, onExpandedChange }: MainMenuProps & { merged: boo
close();
if (persistent) focusTitle(focused);
} else if (persistent) {
previousFocus.current = document.activeElement as HTMLElement;
focusTitle(0);
if (bar?.contains(document.activeElement)) previousFocus.current?.focus();
else {
previousFocus.current = document.activeElement as HTMLElement;
focusTitle(0);
}
} else void expand();
}),
);