diff --git a/e2e-tests/toggle_screen_sizes.spec.ts b/e2e-tests/toggle_screen_sizes.spec.ts new file mode 100644 index 0000000..44e2218 --- /dev/null +++ b/e2e-tests/toggle_screen_sizes.spec.ts @@ -0,0 +1,79 @@ +import { test, testSkipIfWindows, Timeout } from "./helpers/test_helper"; +import { expect } from "@playwright/test"; + +test.describe("Toggle Screen Size Tests", () => { + async function setupApp(po: any) { + await po.setUp({ autoApprove: true }); + await po.sendPrompt("tc=write-index"); + + const iframe = po.getPreviewIframeElement(); + const frame = await iframe.contentFrame(); + + await expect(frame.getByText("Testing:write-index!")).toBeVisible({ + timeout: Timeout.EXTRA_LONG, + }); + } + + testSkipIfWindows( + "should open and close device mode popover", + async ({ po }) => { + test.setTimeout(Timeout.EXTRA_LONG * 1.5); + await setupApp(po); + + // Click the device mode button to open popover + const deviceModeButton = po.page.locator( + '[data-testid="device-mode-button"]', + ); + await deviceModeButton.click(); + + // Verify popover is visible with device options + const originalButton = po.page.locator('[aria-label="Desktop view"]'); + await expect(originalButton).toBeVisible(); + + // Close popover by clicking the button again + await deviceModeButton.click(); + + // Verify popover is closed + await expect(originalButton).toBeHidden(); + }, + ); + + testSkipIfWindows("should switch between device modes", async ({ po }) => { + test.setTimeout(Timeout.EXTRA_LONG * 1.5); + await setupApp(po); + + const deviceModeButton = po.page.locator( + '[data-testid="device-mode-button"]', + ); + + const previewIframe = po.page.locator( + '[data-testid="preview-iframe-element"]', + ); + + // Switch to tablet mode + await deviceModeButton.click(); + await po.page.locator('[aria-label="Tablet view"]').click(); + + // Wait for the iframe width to change to tablet size (768px) + await expect(previewIframe).toHaveAttribute("style", /width:\s*768px/); + + // Verify iframe has tablet dimensions + const tabletWidth = await previewIframe.evaluate((el: HTMLIFrameElement) => + el.style.width.replace("px", ""), + ); + expect(tabletWidth).toBe("768"); + + // Switch to mobile mode + await deviceModeButton.click(); + await po.page.locator('[aria-label="Mobile view"]').click(); + + // Wait for the iframe width to change to mobile size (375px) + await expect(previewIframe).toHaveAttribute("style", /width:\s*375px/); + + // Verify iframe has mobile dimensions + const mobileWidth = await previewIframe.evaluate((el: HTMLIFrameElement) => + el.style.width.replace("px", ""), + ); + expect(mobileWidth).toBe("375"); + }); +}); diff --git a/src/components/preview_panel/PreviewIframe.tsx b/src/components/preview_panel/PreviewIframe.tsx index 37bb350..6d019f8 100644 --- a/src/components/preview_panel/PreviewIframe.tsx +++ b/src/components/preview_panel/PreviewIframe.tsx @@ -19,6 +19,10 @@ import { ChevronRight, MousePointerClick, Power, + MonitorSmartphone, + Monitor, + Tablet, + Smartphone, } from "lucide-react"; import { selectedChatIdAtom } from "@/atoms/chatAtoms"; import { IpcClient } from "@/ipc/ipc_client"; @@ -39,6 +43,12 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { useRunApp } from "@/hooks/useRunApp"; import { useShortcut } from "@/hooks/useShortcut"; import { cn } from "@/lib/utils"; @@ -165,6 +175,17 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => { const iframeRef = useRef(null); const [isPicking, setIsPicking] = useState(false); + // Device mode state + type DeviceMode = "desktop" | "tablet" | "mobile"; + const [deviceMode, setDeviceMode] = useState("desktop"); + const [isDevicePopoverOpen, setIsDevicePopoverOpen] = useState(false); + + // Device configurations + const deviceWidthConfig = { + tablet: 768, + mobile: 375, + }; + //detect if the user is using Mac const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0; @@ -547,6 +568,85 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => { > + + {/* Device Mode Button */} + + + + + e.preventDefault()} + onInteractOutside={(e) => e.preventDefault()} + > + + { + if (value) { + setDeviceMode(value as DeviceMode); + setIsDevicePopoverOpen(false); + } + }} + variant="outline" + > + {/* Tooltips placed inside items instead of wrapping + to avoid asChild prop merging that breaks highlighting */} + + + + + + + + +

Desktop

+
+
+
+ + + + + + + + +

Tablet

+
+
+
+ + + + + + + + +

Mobile

+
+
+
+
+
+
+
@@ -572,19 +672,31 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => {

) : ( -