tailwind config support in the frontend

This commit is contained in:
Naman Dhingra 2024-06-06 08:51:46 +05:30
parent 392b9849a2
commit 7542ee448d
3 changed files with 67 additions and 27 deletions

View File

@ -71,6 +71,7 @@ function App() {
codeGenerationModel: CodeGenerationModel.GPT_4O_2024_05_13,
// Only relevant for hosted version
isTermOfServiceAccepted: false,
tailwindConfig: null,
},
"setting"
);
@ -403,7 +404,7 @@ function App() {
/>
)}
<div className="lg:fixed lg:inset-y-0 lg:z-40 lg:flex lg:w-96 lg:flex-col">
<div className="flex grow flex-col gap-y-2 overflow-y-auto border-r border-gray-200 bg-white px-6 dark:bg-zinc-950 dark:text-white">
<div className="flex flex-col px-6 overflow-y-auto bg-white border-r border-gray-200 grow gap-y-2 dark:bg-zinc-950 dark:text-white">
<div className="flex items-center justify-between mt-10 mb-2">
<h1 className="text-2xl ">Screenshot to Code</h1>
<SettingsDialog settings={settings} setSettings={setSettings} />
@ -426,15 +427,15 @@ function App() {
/>
{showReactWarning && (
<div className="text-sm bg-yellow-200 rounded p-2">
<div className="p-2 text-sm bg-yellow-200 rounded">
Sorry - React is not currently working with GPT-4 Turbo. Please
use GPT-4 Vision or Claude Sonnet. We are working on a fix.
</div>
)}
{showGpt4OMessage && (
<div className="rounded-lg p-2 bg-fuchsia-200">
<p className="text-gray-800 text-sm">
<div className="p-2 rounded-lg bg-fuchsia-200">
<p className="text-sm text-gray-800">
Now supporting GPT-4o. Higher quality and 2x faster. Give it a
try!
</p>
@ -446,7 +447,7 @@ function App() {
{IS_RUNNING_ON_CLOUD && !settings.openAiApiKey && <OnboardingNote />}
{IS_OPENAI_DOWN && (
<div className="bg-black text-white dark:bg-white dark:text-black p-3 rounded">
<div className="p-3 text-white bg-black rounded dark:bg-white dark:text-black">
OpenAI API is currently down. Try back in 30 minutes or later. We
apologize for the inconvenience.
</div>
@ -461,8 +462,7 @@ function App() {
{/* Speed disclaimer for video mode */}
{inputMode === "video" && (
<div
className="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700
p-2 text-xs mb-4 mt-1"
className="p-2 mt-1 mb-4 text-xs text-yellow-700 bg-yellow-100 border-l-4 border-yellow-500"
>
Code generation from videos can take 3-4 minutes. We do
multiple passes to get the best result. Please be patient.
@ -495,8 +495,8 @@ function App() {
onChange={(e) => setUpdateInstruction(e.target.value)}
value={updateInstruction}
/>
<div className="flex justify-between items-center gap-x-2">
<div className="font-500 text-xs text-slate-700 dark:text-white">
<div className="flex items-center justify-between gap-x-2">
<div className="text-xs font-500 text-slate-700 dark:text-white">
Include screenshot of current version?
</div>
<Switch
@ -512,7 +512,7 @@ function App() {
Update
</Button>
</div>
<div className="flex items-center justify-end gap-x-2 mt-2">
<div className="flex items-center justify-end mt-2 gap-x-2">
<Button
onClick={regenerate}
className="flex items-center gap-x-2 dark:text-white dark:bg-gray-700 regenerate-btn"
@ -523,14 +523,14 @@ function App() {
<SelectAndEditModeToggleButton />
)}
</div>
<div className="flex justify-end items-center mt-2">
<div className="flex items-center justify-end mt-2">
<TipLink />
</div>
</div>
)}
{/* Reference image display */}
<div className="flex gap-x-2 mt-2">
<div className="flex mt-2 gap-x-2">
{referenceImages.length > 0 && (
<div className="flex flex-col">
<div
@ -555,21 +555,21 @@ function App() {
/>
)}
</div>
<div className="text-gray-400 uppercase text-sm text-center mt-1">
<div className="mt-1 text-sm text-center text-gray-400 uppercase">
{inputMode === "video"
? "Original Video"
: "Original Screenshot"}
</div>
</div>
)}
<div className="bg-gray-400 px-4 py-2 rounded text-sm hidden">
<h2 className="text-lg mb-4 border-b border-gray-800">
<div className="hidden px-4 py-2 text-sm bg-gray-400 rounded">
<h2 className="mb-4 text-lg border-b border-gray-800">
Console
</h2>
{executionConsole.map((line, index) => (
<div
key={index}
className="border-b border-gray-400 mb-2 text-gray-600 font-mono"
className="mb-2 font-mono text-gray-600 border-b border-gray-400"
>
{line}
</div>
@ -600,7 +600,7 @@ function App() {
<main className="py-2 lg:pl-96">
{appState === AppState.INITIAL && (
<div className="flex flex-col justify-center items-center gap-y-10">
<div className="flex flex-col items-center justify-center gap-y-10">
<ImageUpload setReferenceImages={doCreate} />
<UrlInputSection
doCreate={doCreate}
@ -613,7 +613,7 @@ function App() {
{(appState === AppState.CODING || appState === AppState.CODE_READY) && (
<div className="ml-4">
<Tabs defaultValue="desktop">
<div className="flex justify-between mr-8 mb-4">
<div className="flex justify-between mb-4 mr-8">
<div className="flex items-center gap-x-2">
{appState === AppState.CODE_READY && (
<>
@ -627,7 +627,7 @@ function App() {
<Button
onClick={downloadCode}
variant="secondary"
className="flex items-center gap-x-2 mr-4 dark:text-white dark:bg-gray-700 download-btn"
className="flex items-center mr-4 gap-x-2 dark:text-white dark:bg-gray-700 download-btn"
>
<FaDownload /> Download
</Button>

View File

@ -30,12 +30,30 @@ interface Props {
function SettingsDialog({ settings, setSettings }: Props) {
const handleThemeChange = (theme: EditorTheme) => {
setSettings((s) => ({
setSettings((s: Settings) => ({
...s,
editorTheme: theme,
}));
};
const handleFileChange = (event: Event) => {
const target= event.target as HTMLInputElement;
const file: File = (target.files as FileList)[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const content = e!.target!.result;
// Here you can set the file content to the settings
console.log(content);
setSettings((s: any) => ({
...s,
tailwindConfig: content,
}));
};
reader.readAsText(file);
}
};
return (
<Dialog>
<DialogTrigger>
@ -49,7 +67,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
<div className="flex items-center space-x-2">
<Label htmlFor="image-generation">
<div>DALL-E Placeholder Image Generation</div>
<div className="font-light mt-2 text-xs">
<div className="mt-2 text-xs font-light">
More fun with it but if you want to save money, turn it off.
</div>
</Label>
@ -68,7 +86,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
<div>
<Label htmlFor="openai-api-key">
<div>OpenAI API key</div>
<div className="font-light mt-1 mb-2 text-xs leading-relaxed">
<div className="mt-1 mb-2 text-xs font-light leading-relaxed">
Only stored in your browser. Never stored on servers. Overrides
your .env config.
</div>
@ -91,7 +109,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
<div>
<Label htmlFor="openai-api-key">
<div>OpenAI Base URL (optional)</div>
<div className="font-light mt-2 leading-relaxed">
<div className="mt-2 font-light leading-relaxed">
Replace with a proxy URL if you don't want to use the default.
</div>
</Label>
@ -113,7 +131,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
<div>
<Label htmlFor="anthropic-api-key">
<div>Anthropic API key</div>
<div className="font-light mt-1 text-xs leading-relaxed">
<div className="mt-1 text-xs font-light leading-relaxed">
Only stored in your browser. Never stored on servers. Overrides
your .env config.
</div>
@ -137,7 +155,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
<AccordionContent>
<Label htmlFor="screenshot-one-api-key">
<div className="leading-normal font-normal text-xs">
<div className="text-xs font-normal leading-normal">
If you want to use URLs directly instead of taking the
screenshot yourself, add a ScreenshotOne API key.{" "}
<a
@ -169,14 +187,14 @@ function SettingsDialog({ settings, setSettings }: Props) {
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>Theme Settings</AccordionTrigger>
<AccordionContent className="space-y-4 flex flex-col">
<AccordionContent className="flex flex-col space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="app-theme">
<div>App Theme</div>
</Label>
<div>
<button
className="flex rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50t"
className="flex px-3 py-1 text-sm transition-colors bg-transparent border rounded-md shadow-sm border-input file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50t"
onClick={() => {
document
.querySelector("div.mt-2")
@ -218,6 +236,27 @@ function SettingsDialog({ settings, setSettings }: Props) {
</AccordionContent>
</AccordionItem>
</Accordion>
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>Tailwind Configuration</AccordionTrigger>
<AccordionContent className="flex flex-col space-y-4">
<div className="flex items-center justify-between">
<Label htmlFor="app-theme">
<div>Upload config file</div>
</Label>
<div>
<Input
id="config-file"
type="file"
accept=".js,.ts"
onChange={handleFileChange}
/>
</div>
</div>
</AccordionContent>
</AccordionItem>
</Accordion>
</div>
<DialogFooter>

View File

@ -17,6 +17,7 @@ export interface Settings {
// Only relevant for hosted version
isTermOfServiceAccepted: boolean;
anthropicApiKey: string | null; // Added property for anthropic API key
tailwindConfig: string | null; // Added property for tailwind config
}
export enum AppState {