diff --git a/src/styles.css b/src/styles.css index e8aecbd..da13e90 100644 --- a/src/styles.css +++ b/src/styles.css @@ -2097,6 +2097,21 @@ details[open] > summary > .disclosure-accordion-indicator { background-image: none; backdrop-filter: none; -webkit-backdrop-filter: none; + transition: transform 160ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 160ms ease; +} +/* Keep the border neutral and express focus as a small elevation change. */ +.agent-panel-shell[data-agent-presentation] .agent-panel-input-form:focus-within { + border-color: #e4e4e7; + box-shadow: 0 4px 10px rgb(15 23 42 / 0.08), 0 18px 36px -14px rgb(15 23 42 / 0.22); + transform: translateY(-2px); +} +@media (prefers-reduced-motion: reduce) { + .agent-panel-shell[data-agent-presentation] .agent-panel-input-form { + transition: none; + } + .agent-panel-shell[data-agent-presentation] .agent-panel-input-form:focus-within { + transform: none; + } } .agent-panel-shell[data-agent-presentation] .agent-panel-input-body { display: block; diff --git a/tests/browser/form-focus.e2e.ts b/tests/browser/form-focus.e2e.ts index 525808c..2323aeb 100644 --- a/tests/browser/form-focus.e2e.ts +++ b/tests/browser/form-focus.e2e.ts @@ -10,22 +10,29 @@ test.beforeEach(async ({ page }) => { await page.goto("/", { waitUntil: "domcontentloaded" }); }); -test("Agent composer keeps one thin focus boundary without an outer blue ring", async ({ page }) => { +test("Agent composer uses a neutral shadow instead of a blue focus border", async ({ page }) => { + await page.emulateMedia({ reducedMotion: "no-preference" }); await page.getByRole("button", { name: /展开 Agent 助手面板/ }).click(); const form = page.locator("form.agent-panel-control"); - const textarea = page.getByPlaceholder(/输入调度问题/); + const textarea = page.getByRole("textbox", { name: "询问供水问题,或描述需要处理的任务" }); const restingShadow = await form.evaluate((element) => getComputedStyle(element).boxShadow); + const restingBorder = await form.evaluate((element) => getComputedStyle(element).borderColor); expect(restingShadow).not.toBe("none"); const restingBox = await form.boundingBox(); await textarea.click(); - await expectThemeColor(form, "border-color", "--action-blue-hover"); + await expect(form).toHaveCSS("border-color", restingBorder); await expect(form).toHaveCSS("border-width", "1px"); - await expect(form).toHaveCSS("box-shadow", restingShadow); + await expect(form).not.toHaveCSS("box-shadow", restingShadow); + await expect(form).toHaveCSS("transform", "matrix(1, 0, 0, 1, 0, -2)"); await expect(textarea).toHaveCSS("outline-style", "none"); - expect(await form.boundingBox()).toEqual(restingBox); + const liftedBox = await form.boundingBox(); + expect(liftedBox?.x).toBeCloseTo(restingBox!.x, 1); + expect(liftedBox?.y).toBeCloseTo(restingBox!.y - 2, 1); + expect(liftedBox?.width).toBeCloseTo(restingBox!.width, 1); + expect(liftedBox?.height).toBeCloseTo(restingBox!.height, 1); await page.keyboard.press("Tab"); await textarea.focus(); - await expectThemeColor(form, "border-color", "--action-blue-hover"); + await expect(form).toHaveCSS("border-color", restingBorder); const focusedBox = await form.boundingBox(); await page.screenshot({ path: "test-results/form-focus/agent-focused.png", @@ -89,16 +96,20 @@ test("borderless selects and choice controls keep one theme keyboard focus indic }); for (const width of [320, 375]) { - test(`mobile composer owns a single inset focus stroke at ${width}px`, async ({ page }) => { + test(`mobile composer keeps a neutral focus treatment at ${width}px`, async ({ page }) => { await page.setViewportSize({ width, height: 844 }); await page.getByRole("button", { name: "打开 Agent 面板" }).click(); - const textarea = page.getByPlaceholder(/输入调度问题/); + const textarea = page.getByRole("textbox", { name: "询问供水问题,或描述需要处理的任务" }); + const material = page.locator("form.agent-panel-input-form"); + const restingBorder = await material.evaluate((element) => getComputedStyle(element).borderColor); + const restingShadow = await material.evaluate((element) => getComputedStyle(element).boxShadow); + const restingBox = await material.boundingBox(); await textarea.click(); - const material = page.locator(".agent-panel-composer"); - await expect(material).toHaveCSS("outline-width", "1px"); - await expect(material).toHaveCSS("outline-offset", "-1px"); - await expectThemeColor(material, "outline-color", "--action-blue-hover"); + await expect(material).toHaveCSS("border-width", "1px"); + await expect(material).toHaveCSS("border-color", restingBorder); + await expect(material).not.toHaveCSS("box-shadow", restingShadow); await expect(textarea).toHaveCSS("outline-style", "none"); + expect(await material.boundingBox()).toEqual(restingBox); await page.screenshot({ path: `test-results/form-focus/mobile-${width}.png` }); }); }