feat(preview): add tablet device mode with scaled frame styling

This commit is contained in:
2026-06-12 11:54:47 -07:00
parent 2e8d9ddecc
commit c1a43d18a6
3 changed files with 74 additions and 9 deletions

View File

@@ -255,11 +255,22 @@ export default function PreviewTab() {
>
<div
style={{
...(deviceMode === "desktop" ? desktopFrame : mobileFrame),
...(deviceMode === "desktop"
? desktopFrame
: deviceMode === "tablet"
? tabletFrame
: mobileFrame),
transition: "all 0.3s ease",
transform:
deviceMode === "tablet"
? "scale(0.85)"
: deviceMode === "mobile"
? "scale(0.95)"
: "none",
transformOrigin: "center center",
}}
>
{deviceMode === "mobile" && <MobileChrome />}
{deviceMode !== "desktop" && <MobileChrome />}
{iframeSrc ? (
<iframe
@@ -273,7 +284,12 @@ export default function PreviewTab() {
onLoad={() => bridge?.notifyPreviewIframeLoaded()}
style={{
...iframeStyle,
borderRadius: deviceMode === "mobile" ? 44 : 0,
borderRadius:
deviceMode === "mobile"
? 44
: deviceMode === "tablet"
? 28
: 0,
}}
{...(sandboxIframe(iframeSrc, origin)
? { sandbox: SAME_ORIGIN_SANDBOX }
@@ -283,7 +299,9 @@ export default function PreviewTab() {
<div style={loaderWrap}>{emptyContent}</div>
)}
{deviceMode === "mobile" && <div style={homeIndicator} aria-hidden />}
{deviceMode !== "desktop" && (
<div style={homeIndicator} aria-hidden />
)}
</div>
</div>
</div>
@@ -566,6 +584,21 @@ const desktopFrame: React.CSSProperties = {
"0 1px 2px rgba(26, 26, 26, 0.04), 0 12px 40px rgba(26, 26, 26, 0.07), inset 0 1px 0 rgba(255, 255, 255, 0.85)",
};
const tabletFrame: React.CSSProperties = {
position: "relative",
width: 768,
height: 1024,
flexShrink: 0,
borderRadius: 40,
overflow: "hidden",
background: "#000",
border: "14px solid #1a1a1a",
boxShadow:
"0 0 0 1px rgba(255,255,255,0.1) inset, 0 24px 60px rgba(26, 26, 26, 0.15)",
display: "flex",
flexDirection: "column",
};
const mobileFrame: React.CSSProperties = {
position: "relative",
width: 390,

View File

@@ -1,8 +1,8 @@
import { create } from "zustand";
interface PreviewToolbarState {
deviceMode: "desktop" | "mobile";
setDeviceMode: (mode: "desktop" | "mobile") => void;
deviceMode: "desktop" | "tablet" | "mobile";
setDeviceMode: (mode: "desktop" | "tablet" | "mobile") => void;
refreshKey: number;
triggerRefresh: () => void;
}

View File

@@ -2,7 +2,13 @@
import Link from "next/link";
import { usePathname, useParams } from "next/navigation";
import { Monitor, Smartphone, RotateCw, ExternalLink } from "lucide-react";
import {
Monitor,
Tablet,
Smartphone,
RotateCw,
ExternalLink,
} from "lucide-react";
import { usePreviewToolbarStore } from "./preview-toolbar/preview-toolbar-state";
import { useAnatomy } from "@/components/project/use-anatomy";
@@ -182,7 +188,12 @@ function PreviewDeviceToggles() {
{/* Device Toggles Inside the Address Bar */}
<div
style={{ display: "flex", gap: 2, alignItems: "center", flexShrink: 0 }}
style={{
display: "flex",
gap: 2,
alignItems: "center",
marginRight: 4,
}}
>
<button
onClick={() => setDeviceMode("desktop")}
@@ -203,6 +214,25 @@ function PreviewDeviceToggles() {
>
<Monitor size={12} />
</button>
<button
onClick={() => setDeviceMode("tablet")}
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
width: 24,
height: 24,
borderRadius: 4,
border: "none",
cursor: "pointer",
transition: "all 0.15s",
background: deviceMode === "tablet" ? "#e4e4e7" : "transparent",
color: deviceMode === "tablet" ? "#18181b" : "#71717a",
}}
title="Tablet view"
>
<Tablet size={12} />
</button>
<button
onClick={() => setDeviceMode("mobile")}
style={{
@@ -259,10 +289,12 @@ function PreviewDeviceToggles() {
}
const bar: React.CSSProperties = {
display: "flex",
flexDirection: "row",
alignItems: "center",
flex: 1,
minWidth: 0,
height: "100%",
height: "56px", // Explicitly set height
padding: "0 16px",
gap: 12,
boxSizing: "border-box",