Skip to content

Commit 4dd5448

Browse files
committed
Comment responsive preview (for now)
1 parent 2c9445d commit 4dd5448

2 files changed

Lines changed: 76 additions & 73 deletions

File tree

packages/plugin-ui/src/PluginUI.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ const frameworks: Framework[] = ["HTML", "Tailwind", "Flutter", "SwiftUI"];
4343
export const PluginUI = (props: PluginUIProps) => {
4444
const [showAbout, setShowAbout] = useState(false);
4545

46+
const [previewExpanded, setPreviewExpanded] = useState(false);
47+
const [previewViewMode, setPreviewViewMode] = useState<
48+
"desktop" | "mobile" | "precision"
49+
>("precision");
50+
const [previewBgColor, setPreviewBgColor] = useState<"white" | "black">(
51+
"white",
52+
);
53+
4654
if (props.isLoading) return <Loading />;
4755

4856
const isEmpty = props.code === "";
49-
5057
const warnings = props.warnings ?? [];
5158

5259
return (
@@ -95,7 +102,15 @@ export const PluginUI = (props: PluginUIProps) => {
95102
) : (
96103
<div className="flex flex-col items-center px-4 py-2 gap-2 dark:bg-transparent">
97104
{isEmpty === false && props.htmlPreview && (
98-
<Preview htmlPreview={props.htmlPreview} />
105+
<Preview
106+
htmlPreview={props.htmlPreview}
107+
expanded={previewExpanded}
108+
setExpanded={setPreviewExpanded}
109+
viewMode={previewViewMode}
110+
setViewMode={setPreviewViewMode}
111+
bgColor={previewBgColor}
112+
setBgColor={setPreviewBgColor}
113+
/>
99114
)}
100115

101116
{warnings.length > 0 && <WarningsPanel warnings={warnings} />}

packages/plugin-ui/src/components/Preview.tsx

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from "react";
1+
import React from "react";
22
import { HTMLPreview } from "types";
33
import {
44
Maximize2,
@@ -7,57 +7,49 @@ import {
77
Smartphone,
88
Circle,
99
Ruler,
10-
MonitorIcon,
10+
Monitor,
1111
} from "lucide-react";
12+
import { cn } from "../lib/utils";
1213

14+
// Update the component props to receive state from parent
1315
const Preview: React.FC<{
1416
htmlPreview: HTMLPreview;
17+
expanded: boolean;
18+
setExpanded: React.Dispatch<React.SetStateAction<boolean>>;
19+
viewMode: "desktop" | "mobile" | "precision";
20+
setViewMode: React.Dispatch<
21+
React.SetStateAction<"desktop" | "mobile" | "precision">
22+
>;
23+
bgColor: "white" | "black";
24+
setBgColor: React.Dispatch<React.SetStateAction<"white" | "black">>;
1525
}> = (props) => {
16-
const [expanded, setExpanded] = useState(false);
17-
const [viewMode, setViewMode] = useState<"desktop" | "mobile" | "precision">(
18-
"desktop",
19-
);
20-
const [animationClass, setAnimationClass] = useState<string>("");
21-
const [bgColor, setBgColor] = useState<"white" | "black">("white");
26+
const {
27+
htmlPreview,
28+
expanded,
29+
setExpanded,
30+
viewMode,
31+
setViewMode,
32+
bgColor,
33+
setBgColor,
34+
} = props;
2235

2336
// Define consistent dimensions regardless of mode
2437
const containerWidth = expanded ? 320 : 240;
2538
const containerHeight = expanded ? 180 : 120;
2639

40+
// Calculate scale factor first to use in content width calculation
41+
const scaleFactor = Math.min(
42+
containerWidth / htmlPreview.size.width,
43+
containerHeight / htmlPreview.size.height,
44+
);
45+
2746
// Calculate content dimensions based on view mode
2847
const contentWidth =
2948
viewMode === "desktop"
3049
? containerWidth
3150
: viewMode === "mobile"
3251
? Math.floor(containerWidth * 0.4) // Narrower for mobile
33-
: containerWidth; // For precision, use container width for the outer frame
34-
35-
const scaleFactor = Math.min(
36-
containerWidth / props.htmlPreview.size.width,
37-
containerHeight / props.htmlPreview.size.height,
38-
);
39-
40-
// Add animation when changing view mode
41-
useEffect(() => {
42-
if (viewMode === "desktop") {
43-
setAnimationClass("animate-slide-in-left");
44-
} else if (viewMode === "mobile") {
45-
setAnimationClass("animate-slide-in-right");
46-
} else {
47-
setAnimationClass("animate-fade-in");
48-
}
49-
const timer = setTimeout(() => setAnimationClass(""), 300); // Remove animation class after it completes
50-
return () => clearTimeout(timer);
51-
}, [viewMode]);
52-
53-
// Add animation when changing size
54-
useEffect(() => {
55-
const timer = setTimeout(() => setAnimationClass("animate-scale-in"), 50);
56-
return () => {
57-
clearTimeout(timer);
58-
setAnimationClass("");
59-
};
60-
}, [expanded]);
52+
: htmlPreview.size.width * scaleFactor; // For precision, use scaled original width
6153

6254
return (
6355
<div className="flex flex-col w-full bg-white dark:bg-neutral-800 rounded-lg shadow-sm border border-neutral-200 dark:border-neutral-700">
@@ -69,21 +61,18 @@ const Preview: React.FC<{
6961
</h3>
7062
<div className="flex items-center gap-1">
7163
{/* Background Color Toggle - Only show in desktop and mobile modes */}
72-
{viewMode !== "precision" && (
73-
<button
74-
onClick={() =>
75-
setBgColor(bgColor === "white" ? "black" : "white")
76-
}
77-
className="p-1.5 mr-1 rounded hover:bg-neutral-100 dark:hover:bg-neutral-700 text-neutral-500 dark:text-neutral-400 transition-colors"
78-
aria-label={`Switch the preview to ${bgColor === "white" ? "black" : "white"} background.\nUseful to avoid black text on black background.`}
79-
title={`Switch the preview to ${bgColor === "white" ? "black" : "white"} background.\nUseful to avoid black text on black background.`}
80-
>
81-
<Circle size={14} fill={bgColor} className="stroke-current" />
82-
</button>
83-
)}
64+
65+
<button
66+
onClick={() => setBgColor(bgColor === "white" ? "black" : "white")}
67+
className="p-1.5 mr-1 rounded hover:bg-neutral-100 dark:hover:bg-neutral-700 text-neutral-500 dark:text-neutral-400 transition-colors"
68+
aria-label={`Switch the preview to ${bgColor === "white" ? "black" : "white"} background.\nUseful to avoid black text on black background.`}
69+
title={`Switch the preview to ${bgColor === "white" ? "black" : "white"} background.\nUseful to avoid black text on black background.`}
70+
>
71+
<Circle size={14} fill={bgColor} className="stroke-current" />
72+
</button>
8473

8574
{/* View Mode Toggle */}
86-
<div className="mr-1 flex bg-neutral-100 dark:bg-neutral-700 rounded-md p-0.5">
75+
{/* <div className="mr-1 flex bg-neutral-100 dark:bg-neutral-700 rounded-md p-0.5">
8776
<button
8877
onClick={() => setViewMode("desktop")}
8978
className={`p-1 rounded text-xs ${
@@ -94,7 +83,7 @@ const Preview: React.FC<{
9483
aria-label="Desktop view"
9584
title="Desktop view"
9685
>
97-
<MonitorSmartphone size={14} />
86+
<Monitor size={14} />
9887
</button>
9988
<button
10089
onClick={() => setViewMode("mobile")}
@@ -120,7 +109,7 @@ const Preview: React.FC<{
120109
>
121110
<Ruler size={14} />
122111
</button>
123-
</div>
112+
</div> */}
124113

125114
{/* Expand/Collapse Button */}
126115
<button
@@ -147,31 +136,30 @@ const Preview: React.FC<{
147136
>
148137
{/* Inner content positioned based on view mode */}
149138
<div
150-
className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 ${animationClass}`}
139+
className={`absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2`}
151140
style={{
152141
width: contentWidth,
153142
height:
154143
viewMode === "mobile"
155144
? Math.min(containerHeight * 0.9, containerHeight)
156-
: containerHeight, // Use full container height for both desktop and precision
145+
: viewMode === "precision"
146+
? htmlPreview.size.height * scaleFactor // Use scaled height for precision
147+
: containerHeight,
157148
transition: "width 0.3s ease, height 0.3s ease",
158149
}}
159150
>
160151
{/* Device frame - no background for precision mode */}
161152
<div
162-
className={`w-full h-full flex justify-center items-center overflow-hidden ${
163-
viewMode === "precision"
164-
? "" // No background in precision mode
165-
: bgColor === "white"
166-
? "bg-white"
167-
: "bg-black"
168-
} ${
153+
className={cn(
154+
"w-full h-full flex justify-center items-center overflow-hidden",
155+
bgColor === "white" ? "bg-white" : "bg-black",
169156
viewMode === "desktop"
170157
? "border border-neutral-300 dark:border-neutral-600 rounded shadow-sm"
171158
: viewMode === "mobile"
172159
? "border-2 border-neutral-400 dark:border-neutral-500 rounded-xl shadow-sm"
173-
: "border border-indigo-400 dark:border-indigo-500 rounded shadow-sm" // Precision mode uses indigo border with rounded corners
174-
} transition-all duration-300 ease-in-out`}
160+
: "border border-indigo-400 dark:border-indigo-500 rounded shadow-sm",
161+
`transition-all duration-300 ease-in-out`,
162+
)}
175163
>
176164
{/* Content */}
177165
<div className="w-full h-full flex justify-center items-center">
@@ -180,23 +168,23 @@ const Preview: React.FC<{
180168
zoom: scaleFactor,
181169
width:
182170
viewMode === "precision"
183-
? props.htmlPreview.size.width
171+
? htmlPreview.size.width
184172
: "100%",
185173
height:
186174
viewMode === "precision"
187-
? props.htmlPreview.size.height
175+
? htmlPreview.size.height
188176
: "100%",
189177
transformOrigin: "center",
190178
maxWidth: "100%",
191179
maxHeight: "100%",
192180
aspectRatio:
193181
viewMode === "precision"
194-
? `${props.htmlPreview.size.width} / ${props.htmlPreview.size.height}`
182+
? `${htmlPreview.size.width} / ${htmlPreview.size.height}`
195183
: undefined,
196184
transition: "all 0.3s ease",
197185
}}
198186
dangerouslySetInnerHTML={{
199-
__html: props.htmlPreview.content,
187+
__html: htmlPreview.content,
200188
}}
201189
/>
202190
</div>
@@ -208,10 +196,10 @@ const Preview: React.FC<{
208196
{/* Footer with size info */}
209197
<div className="px-3 py-1.5 text-xs text-neutral-500 dark:text-neutral-400 flex items-center justify-between border-t border-neutral-200 dark:border-neutral-700">
210198
<span>
211-
{props.htmlPreview.size.width.toFixed(0)}×
212-
{props.htmlPreview.size.height.toFixed(0)}px
199+
{htmlPreview.size.width.toFixed(0)}×
200+
{htmlPreview.size.height.toFixed(0)}px
213201
</span>
214-
<div className="flex items-center gap-1.5">
202+
{/* <div className="flex items-center gap-1.5">
215203
{viewMode === "mobile" ? (
216204
<span className="flex items-center gap-1">
217205
<Smartphone size={10} />
@@ -224,11 +212,11 @@ const Preview: React.FC<{
224212
</span>
225213
) : (
226214
<span className="flex items-center gap-1">
227-
<MonitorIcon size={10} />
215+
<Monitor size={10} />
228216
<span>Desktop view</span>
229217
</span>
230218
)}
231-
</div>
219+
</div> */}
232220
</div>
233221
</div>
234222
);

0 commit comments

Comments
 (0)