fix(frontend): keep mobile sidebar trigger clickable (#5149)

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
ChaseMoon 2026-09-03 09:24:49 +08:00 committed by GitHub
parent 27cb73659d
commit c139ba108f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 9 deletions

View File

@ -259,10 +259,10 @@ export default function AgentChatPage() {
<div className="relative flex size-full min-h-0 justify-between">
<header
className={cn(
"absolute top-0 right-0 left-0 z-30 flex h-12 shrink-0 items-center gap-2 px-2 sm:px-4",
"absolute top-0 right-0 left-0 flex h-12 shrink-0 items-center gap-2 px-2 sm:px-4",
isWelcomeMode
? "bg-background/0 backdrop-blur-none"
: "bg-background/80 shadow-xs backdrop-blur",
? "bg-background/0 z-40 backdrop-blur-none"
: "bg-background/80 z-30 shadow-xs backdrop-blur",
)}
>
<SidebarTrigger className="md:hidden" />

View File

@ -280,10 +280,10 @@ export default function ChatPage() {
<div className="relative flex size-full min-h-0 justify-between">
<header
className={cn(
"absolute top-0 right-0 left-0 z-30 flex h-12 shrink-0 items-center gap-2 px-2 sm:px-4",
"absolute top-0 right-0 left-0 flex h-12 shrink-0 items-center gap-2 px-2 sm:px-4",
isWelcomeMode
? "bg-background/0 backdrop-blur-none"
: "bg-background/80 shadow-xs backdrop-blur",
? "bg-background/0 z-40 backdrop-blur-none"
: "bg-background/80 z-30 shadow-xs backdrop-blur",
)}
>
{!isMock && <SidebarTrigger className="md:hidden" />}

View File

@ -47,6 +47,54 @@ test.describe("Agent chat", () => {
).toBeVisible();
});
test("mobile agent welcome keeps the sidebar trigger clickable", async ({
page,
}) => {
await page.setViewportSize({ width: 390, height: 664 });
mockLangGraphAPI(page, {
agents: [
{
...MOCK_AGENTS[0]!,
description: "这是一个用于验证移动端欢迎页布局的测试智能体。".repeat(
16,
),
},
],
});
await page.goto("/workspace/agents/test-agent/chats/new");
await page.evaluate(() => {
document.cookie = "locale=zh-CN; path=/; SameSite=Lax";
});
await page.reload();
const sidebarTrigger = page
.locator("[data-sidebar='trigger']:visible")
.first();
await expect(sidebarTrigger).toBeVisible({ timeout: 15_000 });
const triggerBox = await sidebarTrigger.boundingBox();
expect(triggerBox).not.toBeNull();
const triggerReceivesPointerEvents = await page.evaluate(
({ x, y }) => {
const trigger = document.elementFromPoint(x, y);
return trigger?.closest("[data-sidebar='trigger']") !== null;
},
{
x: triggerBox!.x + triggerBox!.width / 2,
y: triggerBox!.y + triggerBox!.height / 2,
},
);
expect(triggerReceivesPointerEvents).toBe(true);
await page.mouse.click(
triggerBox!.x + triggerBox!.width / 2,
triggerBox!.y + triggerBox!.height / 2,
);
await expect(
page.locator("[data-mobile='true'][data-sidebar='sidebar']"),
).toBeVisible();
});
test("keeps new-chat drafts isolated between agents", async ({ page }) => {
mockLangGraphAPI(page, { agents: MOCK_AGENTS });

View File

@ -77,10 +77,14 @@ test.describe("Sidebar navigation", () => {
test("mobile welcome layout stays within viewport and opens sidebar", async ({
page,
}) => {
await page.setViewportSize({ width: 390, height: 844 });
await page.setViewportSize({ width: 390, height: 664 });
mockLangGraphAPI(page);
await page.goto("/workspace/chats/new");
await page.evaluate(() => {
document.cookie = "locale=zh-CN; path=/; SameSite=Lax";
});
await page.reload();
const viewportWidth = page.viewportSize()?.width ?? 390;
const expectInsideViewport = async (
@ -93,7 +97,7 @@ test.describe("Sidebar navigation", () => {
expect(box!.x + box!.width).toBeLessThanOrEqual(viewportWidth + 1);
};
await expectInsideViewport(page.getByText(/Welcome to|欢迎使用/).first());
await expectInsideViewport(page.getByText(/欢迎使用 🦌 DeerFlow/).first());
await expectInsideViewport(page.getByRole("textbox").first());
await expectInsideViewport(page.locator("[data-slot='suggestions-list']"));
@ -101,7 +105,23 @@ test.describe("Sidebar navigation", () => {
.locator("[data-sidebar='trigger']:visible")
.first();
await expect(mobileSidebarTrigger).toBeVisible();
await mobileSidebarTrigger.click();
const triggerBox = await mobileSidebarTrigger.boundingBox();
expect(triggerBox).not.toBeNull();
const triggerReceivesPointerEvents = await page.evaluate(
({ x, y }) => {
const trigger = document.elementFromPoint(x, y);
return trigger?.closest("[data-sidebar='trigger']") !== null;
},
{
x: triggerBox!.x + triggerBox!.width / 2,
y: triggerBox!.y + triggerBox!.height / 2,
},
);
expect(triggerReceivesPointerEvents).toBe(true);
await page.mouse.click(
triggerBox!.x + triggerBox!.width / 2,
triggerBox!.y + triggerBox!.height / 2,
);
const mobileSidebar = page.locator(
"[data-mobile='true'][data-sidebar='sidebar']",