feat(files): an HTML page opens in a modal over the screen

- Changes panel: Preview beside Whole file opens the page in a modal
  (HtmlViewerModal, shared with the File Explorer) instead of inside the
  panel; Changes and Whole file stay as they were.
- Chat: an HTML file's card, Outputs row or a path in a reply (in the
  workspace or not) opens FilePreview as a modal — Preview | Code, versions,
  Save to Artifacts kept — rather than the side panel or the Changes panel.
- Esc closes both modals: they stop every key from reaching the view below,
  which also kept useDialog's document listener from seeing it.
This commit is contained in:
2026-10-29 11:20:54 +07:00
parent 4a82790734
commit 97c39d5e15
8 changed files with 292 additions and 150 deletions
@@ -217,6 +217,17 @@ describe("the artifact view", () => {
cleanup();
});
it("shows a page as a modal over the screen, closed by Esc", async () => {
const onClose = vi.fn();
render(<FilePreview path="/w/page.html" scope={scope} onClose={onClose} modal />);
const dialog = await screen.findByRole("dialog", { name: "page.html" });
expect(dialog.parentElement?.parentElement).toBe(document.body);
expect(await screen.findByTestId("artifact-frame")).toBeInTheDocument();
expect(screen.queryByTestId("artifact-expand")).toBeNull();
fireEvent.keyDown(screen.getByTestId("artifact-tab-code"), { key: "Escape" });
expect(onClose).toHaveBeenCalled();
});
it("steps back to an older version the conversation wrote", async () => {
html(["<p>two</p>"]);
const tool = (id: string, input: Record<string, unknown>, name = "Write") => ({