fix: harden app sidebar popover

This commit is contained in:
Jesse_Chen
2026-07-17 18:03:10 +08:00
parent 626524b186
commit c6467d8604
3 changed files with 10 additions and 5 deletions
+3 -3
View File
@@ -73,12 +73,12 @@ export function AppSidebar({
onOpenRedeem,
onOpenLogout,
}: AppSidebarProps) {
const { isMobile, setOpen, setOpenMobile, state } = useSidebar();
const { isMobile, setOpen, setOpenMobile, state, viewport } = useSidebar();
const firstSessionRef = useRef<HTMLButtonElement>(null);
const historyHeadingRef = useRef<HTMLHeadingElement>(null);
const isCollapsedDesktop = state === "collapsed" && !isMobile;
const showExpandedContent = !isCollapsedDesktop;
const popoverPlacement = `${isMobile}:${state}`;
const popoverPlacement = `${viewport}:${state}`;
const previousPopoverPlacement = useRef(popoverPlacement);
useEffect(() => {
@@ -192,7 +192,7 @@ export function AppSidebar({
sideOffset={8}
collisionPadding={12}
>
<Popover.Popup className="account-menu" role="menu" aria-label="账户菜单">
<Popover.Popup className="account-menu-popup" role="menu" aria-label="账户菜单">
<div className="account-menu-identity">
<span className="account-menu-avatar" aria-hidden="true">{account.initial}</span>
<span><b>{account.name}</b><small>{account.email}</small></span>
+5 -1
View File
@@ -114,10 +114,14 @@ test("uses a portaled Base UI account popover with safe collision padding", () =
assert.match(appSidebar, /import \{ Popover \} from "@base-ui\/react\/popover"/);
assert.match(appSidebar, /<Popover\.Portal>/);
assert.match(appSidebar, /collisionPadding=\{12\}/);
assert.match(appSidebar, /<Popover\.Popup className="account-menu-popup"/);
assert.doesNotMatch(appSidebar, /<Popover\.Popup className="account-menu"/);
});
test("closes an open account menu only when its sidebar placement changes", () => {
test("closes an open account menu when the sidebar viewport or state changes", () => {
const appSidebar = readProjectFile("src/components/app-sidebar.tsx");
assert.match(appSidebar, /const \{[^}]*\bviewport\b[^}]*\} = useSidebar\(\)/);
assert.match(appSidebar, /const popoverPlacement = `\$\{viewport\}:\$\{state\}`/);
assert.match(appSidebar, /previousPopoverPlacement/);
assert.match(appSidebar, /previousPopoverPlacement\.current !== popoverPlacement && accountMenuOpen/);
});
+2 -1
View File
@@ -83,7 +83,8 @@ test("routes account actions through a popover and focused dialogs", () => {
assert.match(pageSource, /openAccountDialog\("profile"/);
assert.match(pageSource, /openAccountDialog\("redeem"/);
assert.match(pageSource, /openAccountDialog\("logout"/);
assert.match(appSidebarSource, /className="account-menu"/);
assert.match(appSidebarSource, /<Popover\.Popup className="account-menu-popup"/);
assert.doesNotMatch(appSidebarSource, /<Popover\.Popup className="account-menu"/);
assert.match(appSidebarSource, /<Popover\.Root open=\{accountMenuOpen\} onOpenChange=\{onAccountMenuOpenChange\}>/);
});