From 68964c2c8f2497b5793aab3fcb38abcb908093a6 Mon Sep 17 00:00:00 2001
From: Hamzat Victor
Date: Wed, 23 Oct 2024 10:51:16 +0100
Subject: [PATCH 1/6] feat: add css syntax highlight
---
frontend/lib/file-extension-to-language.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/frontend/lib/file-extension-to-language.json b/frontend/lib/file-extension-to-language.json
index a959737..7aff12b 100644
--- a/frontend/lib/file-extension-to-language.json
+++ b/frontend/lib/file-extension-to-language.json
@@ -38,6 +38,7 @@
"csl": "xml",
"cson": "coffeescript",
"csproj": "xml",
+ "css":"css",
"ct": "xml",
"ctp": "php",
"cxx": "cpp",
From eb4e34cf103fad7ad6aa576ff064da8be467195c Mon Sep 17 00:00:00 2001
From: Hamzat Victor
Date: Wed, 23 Oct 2024 10:51:50 +0100
Subject: [PATCH 2/6] feat: add light theme WIP
---
.prettierignore | 2 +-
frontend/app/globals.css | 23 ++
frontend/app/layout.tsx | 19 +-
frontend/components/dashboard/newProject.tsx | 30 +--
frontend/components/editor/index.tsx | 243 ++++++++++--------
frontend/components/editor/navbar/index.tsx | 61 +++--
.../components/editor/terminals/terminal.tsx | 22 +-
frontend/components/landing/index.tsx | 35 ++-
frontend/components/ui/customButton.tsx | 5 +-
.../theme-provider.tsx} | 2 +-
frontend/components/ui/theme-switcher.tsx | 39 +++
11 files changed, 302 insertions(+), 179 deletions(-)
rename frontend/components/{layout/themeProvider.tsx => ui/theme-provider.tsx} (90%)
create mode 100644 frontend/components/ui/theme-switcher.tsx
diff --git a/.prettierignore b/.prettierignore
index 4314ec3..df26bac 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,4 @@
-frontend/**
+# frontend/**
backend/ai/**
backend/database/**
backend/storage/**
\ No newline at end of file
diff --git a/frontend/app/globals.css b/frontend/app/globals.css
index 762a30d..15f1ccf 100644
--- a/frontend/app/globals.css
+++ b/frontend/app/globals.css
@@ -99,6 +99,29 @@
); /* violet 900 -> bg */
}
+.light .gradient-button-bg {
+ background: radial-gradient(
+ circle at top,
+ #262626 0%,
+ #f5f5f5 50%
+ ); /* Dark gray -> Light gray */
+}
+
+.light .gradient-button {
+ background: radial-gradient(
+ circle at bottom,
+ hsl(0, 10%, 25%) -10%,
+ #9d9d9d 50%
+ ); /* Light gray -> Almost white */
+}
+
+.light .gradient-button-bg > div:hover {
+ background: radial-gradient(
+ circle at bottom,
+ hsl(0, 10%, 25%) -10%,
+ #9d9d9d 80%
+ ); /* Light gray -> Almost white */
+}
.inline-decoration::before {
content: "Generate";
color: #525252;
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 70f5791..c93b647 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -1,13 +1,13 @@
-import type { Metadata } from "next"
-import { GeistSans } from "geist/font/sans"
-import { GeistMono } from "geist/font/mono"
-import "./globals.css"
-import { ThemeProvider } from "@/components/layout/themeProvider"
-import { ClerkProvider } from "@clerk/nextjs"
import { Toaster } from "@/components/ui/sonner"
-import { Analytics } from "@vercel/analytics/react"
-import { PreviewProvider } from "@/context/PreviewContext";
+import { ThemeProvider } from "@/components/ui/theme-provider"
+import { PreviewProvider } from "@/context/PreviewContext"
import { SocketProvider } from '@/context/SocketContext'
+import { ClerkProvider } from "@clerk/nextjs"
+import { Analytics } from "@vercel/analytics/react"
+import { GeistMono } from "geist/font/mono"
+import { GeistSans } from "geist/font/sans"
+import type { Metadata } from "next"
+import "./globals.css"
export const metadata: Metadata = {
title: "Sandbox",
@@ -25,8 +25,7 @@ export default function RootLayout({
diff --git a/frontend/components/dashboard/newProject.tsx b/frontend/components/dashboard/newProject.tsx
index b793fc2..012d385 100644
--- a/frontend/components/dashboard/newProject.tsx
+++ b/frontend/components/dashboard/newProject.tsx
@@ -3,16 +3,14 @@
import {
Dialog,
DialogContent,
- DialogDescription,
DialogHeader,
DialogTitle,
- DialogTrigger,
} from "@/components/ui/dialog"
-import Image from "next/image"
-import { useState, useCallback, useEffect, useMemo } from "react"
-import { set, z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
+import Image from "next/image"
+import { useCallback, useEffect, useMemo, useState } from "react"
import { useForm } from "react-hook-form"
+import { z } from "zod"
import {
Form,
@@ -31,23 +29,17 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
-import { useUser } from "@clerk/nextjs"
import { createSandbox } from "@/lib/actions"
-import { useRouter } from "next/navigation"
-import {
- Loader2,
- ChevronRight,
- ChevronLeft,
- Search,
- SlashSquare,
-} from "lucide-react"
-import { Button } from "../ui/button"
import { projectTemplates } from "@/lib/data"
+import { useUser } from "@clerk/nextjs"
+import { ChevronLeft, ChevronRight, Loader2, Search } from "lucide-react"
+import { useRouter } from "next/navigation"
+import { Button } from "../ui/button"
-import useEmblaCarousel from "embla-carousel-react"
-import type { EmblaCarouselType } from "embla-carousel"
-import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures"
import { cn } from "@/lib/utils"
+import type { EmblaCarouselType } from "embla-carousel"
+import useEmblaCarousel from "embla-carousel-react"
+import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures"
const formSchema = z.object({
name: z
.string()
@@ -296,7 +288,7 @@ function SearchInput({
-
+
Go To App
-
+
{children}
diff --git a/frontend/components/layout/themeProvider.tsx b/frontend/components/ui/theme-provider.tsx
similarity index 90%
rename from frontend/components/layout/themeProvider.tsx
rename to frontend/components/ui/theme-provider.tsx
index 8c90fbc..5135dd0 100644
--- a/frontend/components/layout/themeProvider.tsx
+++ b/frontend/components/ui/theme-provider.tsx
@@ -1,9 +1,9 @@
"use client"
-import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return
{children}
}
+
\ No newline at end of file
diff --git a/frontend/components/ui/theme-switcher.tsx b/frontend/components/ui/theme-switcher.tsx
new file mode 100644
index 0000000..9e0bc40
--- /dev/null
+++ b/frontend/components/ui/theme-switcher.tsx
@@ -0,0 +1,39 @@
+"use client"
+
+import { Moon, Sun } from "lucide-react"
+import { useTheme } from "next-themes"
+
+import { Button } from "@/components/ui/button"
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu"
+
+export function ThemeSwitcher() {
+ const { setTheme } = useTheme()
+
+ return (
+
+
+
+
+
+ setTheme("light")}>
+ Light
+
+ setTheme("dark")}>
+ Dark
+
+ setTheme("system")}>
+ System
+
+
+
+ )
+}
From e2d237fe0976b7b066752099ed5a55c37ca60c31 Mon Sep 17 00:00:00 2001
From: Hamzat Victor
Date: Wed, 23 Oct 2024 11:55:38 +0100
Subject: [PATCH 3/6] feat: add theme to terminal
---
backend/server/src/index.ts | 9 +-
.../components/editor/terminals/terminal.tsx | 106 ++++++++++++------
frontend/components/ui/tab.tsx | 2 +-
3 files changed, 81 insertions(+), 36 deletions(-)
diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts
index 293f802..788c329 100644
--- a/backend/server/src/index.ts
+++ b/backend/server/src/index.ts
@@ -224,10 +224,11 @@ io.on("connection", async (socket) => {
containers[data.sandboxId],
sendLoadedEvent
)
- await fileManagers[data.sandboxId].initialize()
terminalManagers[data.sandboxId] = new TerminalManager(
containers[data.sandboxId]
)
+ console.log(`terminal manager set up for ${data.sandboxId}`)
+ await fileManagers[data.sandboxId].initialize()
}
const fileManager = fileManagers[data.sandboxId]
@@ -415,6 +416,12 @@ io.on("connection", async (socket) => {
socket.on("createTerminal", async (id: string, callback) => {
try {
await lockManager.acquireLock(data.sandboxId, async () => {
+ let terminalManager = terminalManagers[data.sandboxId]
+ if (!terminalManager) {
+ terminalManager = terminalManagers[data.sandboxId] =
+ new TerminalManager(containers[data.sandboxId])
+ }
+
await terminalManager.createTerminal(id, (responseString: string) => {
socket.emit("terminalResponse", { id, data: responseString })
const port = extractPortNumber(responseString)
diff --git a/frontend/components/editor/terminals/terminal.tsx b/frontend/components/editor/terminals/terminal.tsx
index 47ce47a..4790a44 100644
--- a/frontend/components/editor/terminals/terminal.tsx
+++ b/frontend/components/editor/terminals/terminal.tsx
@@ -6,9 +6,9 @@ import "./xterm.css"
import { debounce } from "@/lib/utils"
import { Loader2 } from "lucide-react"
+import { useTheme } from "next-themes"
import { ElementRef, useEffect, useRef } from "react"
import { Socket } from "socket.io-client"
-
export default function EditorTerminal({
socket,
id,
@@ -22,38 +22,17 @@ export default function EditorTerminal({
setTerm: (term: Terminal) => void
visible: boolean
}) {
- const terminalRef = useRef>(null)
+ const { theme } = useTheme()
+ const terminalContainerRef = useRef>(null)
const fitAddonRef = useRef(null)
useEffect(() => {
- if (!terminalRef.current) return
+ if (!terminalContainerRef.current) return
// console.log("new terminal", id, term ? "reusing" : "creating");
const terminal = new Terminal({
cursorBlink: true,
- theme: {
- foreground: "#2e3436",
- background: "#ffffff",
- black: "#2e3436",
- brightBlack: "#555753",
- red: "#cc0000",
- brightRed: "#ef2929",
- green: "#4e9a06",
- brightGreen: "#8ae234",
- yellow: "#c4a000",
- brightYellow: "#fce94f",
- blue: "#3465a4",
- brightBlue: "#729fcf",
- magenta: "#75507b",
- brightMagenta: "#ad7fa8",
- cyan: "#06989a",
- brightCyan: "#34e2e2",
- white: "#d3d7cf",
- brightWhite: "#eeeeec",
- cursor: "#2e3436",
- cursorAccent: "#ffffff",
- selection: "rgba(52, 101, 164, 0.3)",
- },
+ theme: theme === "light" ? lightTheme : darkTheme,
fontFamily: "var(--font-geist-mono)",
fontSize: 14,
lineHeight: 1.5,
@@ -67,14 +46,20 @@ export default function EditorTerminal({
return dispose
}, [])
+ useEffect(() => {
+ if (term) {
+ term.options.theme = theme === "light" ? lightTheme : darkTheme
+ }
+ }, [theme])
+
useEffect(() => {
if (!term) return
- if (!terminalRef.current) return
+ if (!terminalContainerRef.current) return
if (!fitAddonRef.current) {
const fitAddon = new FitAddon()
term.loadAddon(fitAddon)
- term.open(terminalRef.current)
+ term.open(terminalContainerRef.current)
fitAddon.fit()
fitAddonRef.current = fitAddon
}
@@ -89,7 +74,7 @@ export default function EditorTerminal({
})
const resizeObserver = new ResizeObserver(
debounce((entries) => {
- if (!fitAddonRef.current || !terminalRef.current) return
+ if (!fitAddonRef.current || !terminalContainerRef.current) return
const entry = entries[0]
if (!entry) return
@@ -98,8 +83,8 @@ export default function EditorTerminal({
// Only call fit if the size has actually changed
if (
- width !== terminalRef.current.offsetWidth ||
- height !== terminalRef.current.offsetHeight
+ width !== terminalContainerRef.current.offsetWidth ||
+ height !== terminalContainerRef.current.offsetHeight
) {
try {
fitAddonRef.current.fit()
@@ -111,13 +96,13 @@ export default function EditorTerminal({
)
// start observing for resize
- resizeObserver.observe(terminalRef.current)
+ resizeObserver.observe(terminalContainerRef.current)
return () => {
disposableOnData.dispose()
disposableOnResize.dispose()
resizeObserver.disconnect()
}
- }, [term, terminalRef.current])
+ }, [term, terminalContainerRef.current])
useEffect(() => {
if (!term) return
@@ -136,7 +121,7 @@ export default function EditorTerminal({
return (
<>
@@ -150,3 +135,56 @@ export default function EditorTerminal({
>
)
}
+
+const lightTheme = {
+ foreground: "#2e3436",
+ background: "#ffffff",
+ black: "#2e3436",
+ brightBlack: "#555753",
+ red: "#cc0000",
+ brightRed: "#ef2929",
+ green: "#4e9a06",
+ brightGreen: "#8ae234",
+ yellow: "#c4a000",
+ brightYellow: "#fce94f",
+ blue: "#3465a4",
+ brightBlue: "#729fcf",
+ magenta: "#75507b",
+ brightMagenta: "#ad7fa8",
+ cyan: "#06989a",
+ brightCyan: "#34e2e2",
+ white: "#d3d7cf",
+ brightWhite: "#eeeeec",
+ cursor: "#2e3436",
+ cursorAccent: "#ffffff",
+ selectionBackground: "#3465a4",
+ selectionForeground: "#ffffff",
+ selectionInactiveBackground: "#264973",
+}
+
+// Dark Theme
+const darkTheme = {
+ foreground: "#f8f8f2",
+ background: "#0a0a0a",
+ black: "#21222c",
+ brightBlack: "#6272a4",
+ red: "#ff5555",
+ brightRed: "#ff6e6e",
+ green: "#50fa7b",
+ brightGreen: "#69ff94",
+ yellow: "#f1fa8c",
+ brightYellow: "#ffffa5",
+ blue: "#bd93f9",
+ brightBlue: "#d6acff",
+ magenta: "#ff79c6",
+ brightMagenta: "#ff92df",
+ cyan: "#8be9fd",
+ brightCyan: "#a4ffff",
+ white: "#f8f8f2",
+ brightWhite: "#ffffff",
+ cursor: "#f8f8f2",
+ cursorAccent: "#0a0a0a",
+ selectionBackground: "#264973",
+ selectionForeground: "#ffffff",
+ selectionInactiveBackground: "#1a3151",
+}
diff --git a/frontend/components/ui/tab.tsx b/frontend/components/ui/tab.tsx
index 0ef38e0..f5bac5c 100644
--- a/frontend/components/ui/tab.tsx
+++ b/frontend/components/ui/tab.tsx
@@ -28,7 +28,7 @@ export default function Tab({
variant={"secondary"}
className={`font-normal select-none ${
selected
- ? "bg-neutral-700 hover:bg-neutral-600 text-foreground"
+ ? "bg-muted-foreground/50 hover:bg-muted-foreground/40 text-foreground"
: "text-muted-foreground"
}`}
>
From 009d4d5164e4b285310c923075c974f59a1146dd Mon Sep 17 00:00:00 2001
From: Hamzat Victor
Date: Wed, 23 Oct 2024 12:05:43 +0100
Subject: [PATCH 4/6] feat: add theme swithcer to dashboard
---
frontend/components/dashboard/navbar/index.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/frontend/components/dashboard/navbar/index.tsx b/frontend/components/dashboard/navbar/index.tsx
index 2f983af..5409236 100644
--- a/frontend/components/dashboard/navbar/index.tsx
+++ b/frontend/components/dashboard/navbar/index.tsx
@@ -1,4 +1,5 @@
import Logo from "@/assets/logo.svg"
+import { ThemeSwitcher } from "@/components/ui/theme-switcher"
import { User } from "@/lib/types"
import Image from "next/image"
import Link from "next/link"
@@ -19,6 +20,7 @@ export default function DashboardNavbar({ userData }: { userData: User }) {
+
From 107cd3ddcca81133f20f95a091c83f09e030907f Mon Sep 17 00:00:00 2001
From: Hamzat Victor
Date: Wed, 23 Oct 2024 12:05:54 +0100
Subject: [PATCH 5/6] feat: improve accessibility
---
frontend/components/dashboard/newProject.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/components/dashboard/newProject.tsx b/frontend/components/dashboard/newProject.tsx
index 012d385..bf85d4b 100644
--- a/frontend/components/dashboard/newProject.tsx
+++ b/frontend/components/dashboard/newProject.tsx
@@ -288,7 +288,7 @@ function SearchInput({