fix(app): align compact menu sheet content
Route composer attachments through the shared compact menu sheet so headers and rows use the same alignment rails. Base the final-row padding on the device safe area to keep actions clear of system navigation.
This commit is contained in:
@@ -7,6 +7,7 @@ import { connectWorkspaceSetupClient } from "./workspace-setup";
|
||||
import { selectWorkspaceInSidebar } from "./sidebar";
|
||||
import { getServerId } from "./server-id";
|
||||
import { waitForTabBar } from "./launcher";
|
||||
import { waitForSettledPosition } from "./sheet-layout";
|
||||
|
||||
function composerInput(page: Page) {
|
||||
return page.getByRole("textbox", { name: "Message agent..." }).first();
|
||||
@@ -71,7 +72,28 @@ export async function pressInterruptShortcut(page: Page): Promise<void> {
|
||||
|
||||
export async function openAttachmentMenu(page: Page): Promise<void> {
|
||||
await page.getByTestId("message-input-attach-button").filter({ visible: true }).first().click();
|
||||
await expect(page.getByTestId("message-input-attachment-menu")).toBeVisible({ timeout: 5_000 });
|
||||
await expect(
|
||||
page
|
||||
.getByTestId("message-input-attachment-menu")
|
||||
.or(page.getByTestId("message-input-attachment-menu-content")),
|
||||
).toBeVisible({ timeout: 5_000 });
|
||||
}
|
||||
|
||||
export async function expectAttachmentSheetRowsOnTitleRail(page: Page): Promise<void> {
|
||||
const title = page.getByText("Add attachment", { exact: true });
|
||||
const firstItemGlyph = page
|
||||
.getByRole("button", { name: "Add image", exact: true })
|
||||
.locator("svg")
|
||||
.first();
|
||||
await waitForSettledPosition(title);
|
||||
const [titleBox, glyphBox] = await Promise.all([
|
||||
title.boundingBox(),
|
||||
firstItemGlyph.boundingBox(),
|
||||
]);
|
||||
if (!titleBox || !glyphBox) {
|
||||
throw new Error("Attachment sheet geometry could not be measured");
|
||||
}
|
||||
expect(Math.abs(glyphBox.x - titleBox.x)).toBeLessThanOrEqual(1);
|
||||
}
|
||||
|
||||
export async function expectAttachButtonDisabled(page: Page): Promise<void> {
|
||||
|
||||
@@ -235,6 +235,27 @@ export async function expectNewWorkspaceProjectSelected(
|
||||
await expect(projectPicker).toContainText(projectDisplayName);
|
||||
}
|
||||
|
||||
export async function expectNewWorkspaceTriggerLabelsAligned(
|
||||
page: Page,
|
||||
input: { projectLabel: string; hostLabel: string },
|
||||
): Promise<void> {
|
||||
const projectTrigger = page.getByRole("button", { name: "Workspace project" });
|
||||
const hostTrigger = page.getByRole("button", { name: "Host", exact: true });
|
||||
const [projectTriggerBox, projectLabelBox, hostTriggerBox, hostLabelBox] = await Promise.all([
|
||||
projectTrigger.boundingBox(),
|
||||
projectTrigger.getByText(input.projectLabel, { exact: true }).boundingBox(),
|
||||
hostTrigger.boundingBox(),
|
||||
hostTrigger.getByText(input.hostLabel, { exact: true }).boundingBox(),
|
||||
]);
|
||||
if (!projectTriggerBox || !projectLabelBox || !hostTriggerBox || !hostLabelBox) {
|
||||
throw new Error("New Workspace trigger geometry could not be measured");
|
||||
}
|
||||
|
||||
const projectLabelInset = projectLabelBox.x - projectTriggerBox.x;
|
||||
const hostLabelInset = hostLabelBox.x - hostTriggerBox.x;
|
||||
expect(hostLabelInset).toBeCloseTo(projectLabelInset, 0);
|
||||
}
|
||||
|
||||
export async function fillNewWorkspaceDraft(page: Page, draft: string): Promise<void> {
|
||||
const composer = page.getByRole("textbox", { name: "Message agent..." });
|
||||
await expect(composer).toBeVisible({ timeout: 30_000 });
|
||||
|
||||
Reference in New Issue
Block a user