import { useState } from "react"; import Modal from "../../ui/Modal"; import Button from "../../ui/Button"; /** * Viewport presets. These are the *page's* resolution, not the window's — the * pane is a screencast, so a bigger window shows the same pixels drawn larger * while this is what actually reflows the layout. */ const PRESETS: { label: string; width: number; height: number }[] = [ { label: "1280 × 720", width: 1280, height: 720 }, { label: "1920 × 1080", width: 1920, height: 1080 }, { label: "1440 × 900", width: 1440, height: 900 }, { label: "390 × 844 (phone)", width: 390, height: 844 }, ]; interface Props { /** Prefilled URL — an auth URL from the terminal, or the last one used. */ initialUrl?: string; initialWidth?: number; initialHeight?: number; busy?: boolean; onOpen: (url: string, width: number, height: number) => void; onClose: () => void; } /** * Ask for a URL and a viewport, then open it in the container's browser. * * Deliberately modal and short-lived — the convention for a task with one * question and one button. The URL is not opened here; the caller runs the * command so failures land in its toast. */ export default function OpenPageDialog({ initialUrl = "", initialWidth = 1280, initialHeight = 720, busy = false, onOpen, onClose, }: Props) { const [url, setUrl] = useState(initialUrl); const [width, setWidth] = useState(initialWidth); const [height, setHeight] = useState(initialHeight); const trimmed = url.trim(); // Mirrors the backend's allow-list, so the error arrives before the click // rather than after a round trip. const valid = /^https?:\/\/\S+$/i.test(trimmed); return ( } >

Launches a browser inside this container and publishes it to the Browser tab. Use it for a sign-in page — the callback listener is in the container too, so the login completes without involving your host browser — or for a dev server on container loopback.

Viewport
{PRESETS.map((p) => { const active = p.width === width && p.height === height; return ( ); })}
setWidth(Number(e.target.value))} className="w-24 px-2 py-1 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded-[var(--radius-control)] text-xs text-[var(--text-primary)]" /> setHeight(Number(e.target.value))} className="w-24 px-2 py-1 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded-[var(--radius-control)] text-xs text-[var(--text-primary)]" /> CSS pixels
); }