From ca55e1b0efd8709a470df1281a2b5d4682eb635d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Tue, 4 Aug 2026 10:29:26 +0100 Subject: [PATCH] feat: add quick chat elevation (#2251) --- .../quick-chat/quick-chat-modal.tsx | 2 +- apps/web/e2e/tests/chat/quick-chat.spec.ts | 18 ++++ docs/plans/quick-chat-elevation/plan.md | 83 +++++++++++++++++++ .../task-01-quick-chat-elevation.md | 80 ++++++++++++++++++ docs/specs/INDEX.md | 1 + docs/specs/ui/quick-chat-elevation.md | 45 ++++++++++ 6 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 docs/plans/quick-chat-elevation/plan.md create mode 100644 docs/plans/quick-chat-elevation/task-01-quick-chat-elevation.md create mode 100644 docs/specs/ui/quick-chat-elevation.md diff --git a/apps/web/components/quick-chat/quick-chat-modal.tsx b/apps/web/components/quick-chat/quick-chat-modal.tsx index a57ad053d6..95466035ed 100644 --- a/apps/web/components/quick-chat/quick-chat-modal.tsx +++ b/apps/web/components/quick-chat/quick-chat-modal.tsx @@ -148,7 +148,7 @@ export const QuickChatModal = memo(function QuickChatModal({ workspaceId }: Quic className="!left-0 !top-0 !h-dvh !max-h-dvh !w-screen !max-w-none !translate-x-0 !translate-y-0 flex flex-col gap-0 p-0 shadow-2xl sm:!left-1/2 sm:!top-1/2 sm:!h-[85vh] sm:!max-h-[85vh] sm:!w-[var(--quick-chat-width)] sm:!max-w-[calc(100vw-2rem)] sm:!-translate-x-1/2 sm:!-translate-y-1/2" style={{ "--quick-chat-width": `${width}px` } as CSSProperties} showCloseButton={false} - overlayClassName="bg-transparent" + overlayClassName="bg-black/20" > Quick Chat diff --git a/apps/web/e2e/tests/chat/quick-chat.spec.ts b/apps/web/e2e/tests/chat/quick-chat.spec.ts index cfb5079b82..1959d40066 100644 --- a/apps/web/e2e/tests/chat/quick-chat.spec.ts +++ b/apps/web/e2e/tests/chat/quick-chat.spec.ts @@ -29,6 +29,24 @@ async function waitForQuickChatWidth(dialog: Locator) { } test.describe("Quick Chat", () => { + test("adds elevation when opened over the page", async ({ testPage }) => { + const dialog = await openQuickChatSetup(testPage); + const overlay = testPage.locator('[data-slot="dialog-overlay"]'); + + await expect(overlay).toBeVisible(); + const styles = await Promise.all([ + overlay.evaluate((element) => getComputedStyle(element).backgroundColor), + dialog.evaluate((element) => getComputedStyle(element).boxShadow), + ]); + expect(styles[0]).not.toBe("rgba(0, 0, 0, 0)"); + expect(styles[0]).not.toBe("transparent"); + expect(styles[1]).not.toBe("none"); + + await testPage.keyboard.press("Escape"); + await expect(dialog).not.toBeVisible(); + await expect(overlay).not.toBeVisible(); + }); + test("clarification shortcuts work after clicking the message surface", async ({ testPage }) => { const dialog = await openQuickChatWithAgent(testPage); await sendQuickChatMessage(dialog, testPage, "/e2e:clarification-multi"); diff --git a/docs/plans/quick-chat-elevation/plan.md b/docs/plans/quick-chat-elevation/plan.md new file mode 100644 index 0000000000..c6ad091cb5 --- /dev/null +++ b/docs/plans/quick-chat-elevation/plan.md @@ -0,0 +1,83 @@ +--- +spec: docs/specs/ui/quick-chat-elevation.md +created: 2026-08-04 +status: done +--- + +# Implementation Plan: Quick Chat elevation + +## Overview + +Reuse the existing Radix dialog overlay and Quick Chat panel shadow. Change only the Quick Chat +overlay from transparent to the established subtle backdrop treatment, then add focused desktop +rendered coverage and retain the existing mobile entry/containment coverage. The change is a single +frontend vertical slice with no backend, state, API, or persistence work. + +## Backend + +No backend changes. Quick Chat state and session behavior are unchanged. + +## Frontend + +### Quick Chat dialog surface + +- Update `apps/web/components/quick-chat/quick-chat-modal.tsx` so the `DialogContent` overlay uses + the existing subtle backdrop treatment (`bg-black/20`) instead of `bg-transparent`. +- Keep the existing `shadow-2xl` panel class, responsive dimensions, full-screen phone layout, + focus behavior, and close controls unchanged. + +## Tests + +- **What:** Opening Quick Chat on a tablet/desktop viewport renders a non-transparent backdrop and + leaves the dialog panel elevated with a non-empty box shadow; closing it removes the backdrop. + **File:** `apps/web/e2e/tests/chat/quick-chat.spec.ts`. + **How:** Open the existing Quick Chat setup with the shared helper, inspect the portaled + `[data-slot="dialog-overlay"]` and dialog computed styles, then close and assert both are no + longer visible. The new test must fail before the overlay class change because the backdrop is + currently transparent. +- **What:** The mobile Quick Chat path still opens from a touch entry point, stays viewport + contained, and closes through its explicit control. + **File:** existing `apps/web/e2e/tests/chat/mobile-quick-chat-entry.spec.ts` coverage. + **How:** Run the existing mobile scenario; no alternate mobile composition or new test file is + needed because this visual change does not alter the full-screen phone surface. + +## E2E Tests + +- **Scenario:** GIVEN Quick Chat is closed on a tablet or desktop viewport, WHEN the user opens it, + THEN the dialog is visibly elevated above a non-transparent backdrop. + **File:** `apps/web/e2e/tests/chat/quick-chat.spec.ts`. + **What to verify:** The dialog is visible, the portaled overlay has a non-transparent computed + background, and the panel's computed `box-shadow` is not `none`. +- **Scenario:** GIVEN a phone viewport, WHEN the user opens Quick Chat from the Home header, THEN + the existing full-screen dialog and close control remain usable without document horizontal + overflow. + **File:** `apps/web/e2e/tests/chat/mobile-quick-chat-entry.spec.ts`. + **What to verify:** Existing mobile entry, containment, close, and overflow assertions continue + to pass. + +## Implementation Waves + +- [x] [Task 01: Add Quick Chat elevation](task-01-quick-chat-elevation.md) + +## Verification Results + +Completed implementation and focused verification: + +- `pnpm install --frozen-lockfile` — passed. +- `pnpm --filter @kandev/web run typecheck` — passed. +- RED proof: the new desktop E2E failed before the class change because the overlay computed to + `rgba(0, 0, 0, 0)`. +- `pnpm --dir web e2e:run --project chromium tests/chat/quick-chat.spec.ts -- --grep "elevation"` — + passed, 1 test. +- `pnpm --dir web e2e:run --project mobile-chrome tests/chat/mobile-quick-chat-entry.spec.ts` — + passed, 4 tests. +- Managed PR capture — passed, with desktop and mobile Quick Chat screenshots in + `apps/web/.pr-assets/`. + +## Risks + +- The backdrop is visible around the panel on tablet/desktop but naturally hidden behind the + full-screen phone composition; the mobile check must verify usability rather than expect visible + page dimming. +- The overlay remains a Radix dialog overlay, so changing only its color must preserve focus + trapping, Escape dismissal, and page interaction blocking. diff --git a/docs/plans/quick-chat-elevation/task-01-quick-chat-elevation.md b/docs/plans/quick-chat-elevation/task-01-quick-chat-elevation.md new file mode 100644 index 0000000000..1e3dde625a --- /dev/null +++ b/docs/plans/quick-chat-elevation/task-01-quick-chat-elevation.md @@ -0,0 +1,80 @@ +--- +id: "01-quick-chat-elevation" +title: "Add Quick Chat elevation" +status: done +wave: 1 +depends_on: [] +plan: "plan.md" +spec: "../../specs/ui/quick-chat-elevation.md" +--- + +# Task 01: Add Quick Chat elevation + +## Acceptance + +1. Tablet and desktop Quick Chat opens above a subtle non-transparent backdrop while retaining its + existing panel shadow, size, position, content, and close behavior. +2. Closing Quick Chat removes the backdrop and restores the page; the existing mobile Quick Chat + entry, full-screen composition, close control, and no-overflow behavior remain intact. + +## Verification + +```bash +cd apps && pnpm install --frozen-lockfile +pnpm --filter @kandev/web run typecheck +pnpm --dir web e2e:run --project chromium tests/chat/quick-chat.spec.ts -- --grep "elevation" +pnpm --dir web e2e:run --project mobile-chrome tests/chat/mobile-quick-chat-entry.spec.ts +``` + +The E2E test is written and run RED before changing the overlay class, then rerun GREEN after the +minimal frontend change. The final E2E commands use the managed runner so the production Vite build +is refreshed before browser verification. + +## Files likely touched + +- `apps/web/components/quick-chat/quick-chat-modal.tsx` +- `apps/web/e2e/tests/chat/quick-chat.spec.ts` + +Existing mobile coverage used as evidence: + +- `apps/web/e2e/tests/chat/mobile-quick-chat-entry.spec.ts` + +## Dependencies + +None. Reuse the existing `DialogOverlay`, Quick Chat modal, helpers, and mobile entry coverage. + +## Parallelism + +Sequential. The test and the one-line overlay change describe the same rendered contract and must +be verified together. + +## Inputs + +- `docs/specs/ui/quick-chat-elevation.md` +- `docs/plans/quick-chat-elevation/plan.md` +- `apps/web/AGENTS.md` +- `.agents/skills/tdd/SKILL.md` +- `.agents/skills/e2e/SKILL.md` +- `.agents/skills/mobile-parity/SKILL.md` + +## Risks + +- Do not replace the transparent overlay globally; the change is scoped to Quick Chat and should + not alter other dialogs or the separate new-chat picker. +- Avoid changing phone geometry: the full-screen panel covers the backdrop by design. + +## Results + +- Added the desktop rendered contract test in `apps/web/e2e/tests/chat/quick-chat.spec.ts`. +- Confirmed RED before the production change: the overlay computed to `rgba(0, 0, 0, 0)`. +- Changed only the Quick Chat overlay class from `bg-transparent` to `bg-black/20`; the existing + `shadow-2xl` panel and mobile full-screen layout remain unchanged. +- Typecheck passed. +- Focused desktop E2E passed (1 test) and existing mobile entry E2E passed (4 tests). +- Managed desktop/mobile PR screenshot capture passed; generated assets remain ignored in + `apps/web/.pr-assets/` for PR publication. + +## Output contract + +Report the RED and GREEN E2E evidence, changed files, exact verification results, blockers or +residual risks, and update this task plus `plan.md` to `done` when implementation is complete. diff --git a/docs/specs/INDEX.md b/docs/specs/INDEX.md index 7a4ded93ee..5838e47072 100644 --- a/docs/specs/INDEX.md +++ b/docs/specs/INDEX.md @@ -151,6 +151,7 @@ Subscription quota tracking and per-agent cheap-model profile routing. | [message-queue-merge](ui/message-queue-merge.md) | shipped | | [settings-manual-save](ui/settings-manual-save.md) | shipped | | [executor-settings-card-spacing](ui/executor-settings-card-spacing.md) | shipped | +| [quick-chat-elevation](ui/quick-chat-elevation.md) | building | | [transcript-navigation-settings](ui/transcript-navigation-settings.md) | shipped | | [app-status-bar](ui/app-status-bar.md) | shipped | | [mobile-task-navigation](ui/mobile-task-navigation.md) | shipped | diff --git a/docs/specs/ui/quick-chat-elevation.md b/docs/specs/ui/quick-chat-elevation.md new file mode 100644 index 0000000000..a65d31da0e --- /dev/null +++ b/docs/specs/ui/quick-chat-elevation.md @@ -0,0 +1,45 @@ +--- +status: building +created: 2026-08-04 +owner: kandev +--- + +# Quick Chat elevation + +## Why + +Quick Chat opens over the current page with a transparent backdrop, so the floating panel can +blend into the page and its opened state is not immediately clear. Users need a restrained visual +separation that makes the panel feel elevated while preserving the surrounding page as context. + +## What + +- When Quick Chat opens at tablet or desktop widths, the page behind it is visually de-emphasized by + a subtle semitransparent backdrop. +- The Quick Chat panel remains above the backdrop with its existing elevation shadow, dimensions, + position, content, and interaction behavior unchanged. +- Closing Quick Chat removes the backdrop and restores the page's normal appearance and interaction. +- On phone widths, Quick Chat keeps its existing full-screen composition, explicit close control, + and viewport containment. The backdrop does not need to be visible because the panel covers the + viewport. + +## Scenarios + +- **GIVEN** Quick Chat is closed on a tablet or desktop viewport, **WHEN** the user opens Quick Chat, + **THEN** the Quick Chat dialog is visible above a non-transparent backdrop and its computed panel + shadow is not `none`. +- **GIVEN** Quick Chat is open on a tablet or desktop viewport, **WHEN** the user closes it, + **THEN** the dialog and backdrop are removed so the page is fully visible again. +- **GIVEN** a phone viewport, **WHEN** the user opens Quick Chat from an existing mobile entry + point, **THEN** the full-screen dialog remains usable, the explicit close control remains + reachable, and the document has no horizontal overflow. + +## Out of scope + +- Changing Quick Chat size, position, responsive composition, content, sessions, or persistence. +- Adding a new backdrop component, user setting, animation, or navigation behavior. +- Changing the separate new-Quick-Chat picker dialog or configuration-chat popover. + +## Implementation plan + +[Quick Chat elevation implementation](../../plans/quick-chat-elevation/plan.md)