Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 33 additions & 27 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
--muted-foreground: oklch(0.55 0.02 264.41);
--accent: oklch(0.95 0.03 233.56);
--accent-foreground: oklch(0.38 0.14 265.59);
--brand-claude: #d97757;
--destructive: oklch(0.64 0.21 25.39);
--border: oklch(0.93 0.01 261.82);
--input: oklch(0.93 0.01 261.82);
Expand All @@ -32,12 +33,8 @@
--sidebar-foreground: oklch(0.14 0 0);
--sidebar-background: oklch(1.0 0 0);
--sidebar-project-background: oklch(1.0 0 0);
--sidebar-primary: oklch(0.20 0 0);
--sidebar-primary-foreground: oklch(0.98 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.20 0 0);
--sidebar-border: oklch(0.92 0 0);
--sidebar-ring: oklch(0.71 0 0);
--destructive-foreground: oklch(1.0000 0 0);
--content-background: oklch(1.00 0 0);
--font-serif: Source Serif 4, serif;
Expand Down Expand Up @@ -93,12 +90,8 @@
--sidebar-foreground: oklch(0.99 0 0);
--sidebar-background: #333333;
--sidebar-project-background: #242426;
--sidebar-primary: oklch(0.49 0.24 264.40);
--sidebar-primary-foreground: oklch(0.99 0 0);
--sidebar-accent: #2B2D2E;
--sidebar-accent-foreground: oklch(0.99 0 0);
--sidebar-border: oklch(1.00 0 0 / 10%);
--sidebar-ring: oklch(0.55 0.02 285.93);
--content-background: #1E1E1E;
--tabs-background: #252526;
--tab-background: #292929;
Expand All @@ -121,43 +114,57 @@
}

.stealth {
/* === Base Colors === */
--background: #1e1e1e;
--foreground: #cccccc;

/* === UI Components === */
--card: #252526;
--card-foreground: #cccccc;
--popover: #2d2d30;
--popover-foreground: #cccccc;

/* === Brand Colors === */
--primary: #007acc;
--primary-foreground: #ffffff;
--primary-hover: #0062a3;

--secondary: #2d2d30;
--secondary-foreground: #dcdcdc;

--accent: #2d2d30;
--accent-foreground: #ffffff;

--muted: #2d2d30;
--muted-foreground: #858585;
--accent: #264f78;
--accent-foreground: #ffffff;
--destructive: #7f1d1d;
--destructive-foreground: #ffffff;

--destructive: #F14C4C;
--destructive-foreground: #F14C4C;

/* === Borders & Inputs === */
--border: #3e3e42;
--input: #3e3e42;
--ring: #007fd4;
--chart-1: #007acc;
--chart-2: #57a64a;
--chart-3: #d69d85;
--chart-4: #569cd6;
--chart-5: #b5cea8;

/* === Sidebar (VS Code Style) === */
--sidebar: #2d2d30;
--sidebar-foreground: #dcdcdc;
--sidebar-background: #2d2d30;
--sidebar-project-background: #1e1e1e;
--sidebar-primary: #007acc;
--sidebar-primary-foreground: #ffffff;
--sidebar-project-background: #252526;
--sidebar-accent: #2d2d30;
--sidebar-accent-foreground: #ffffff;
--sidebar-border: #1e1e1e;
--sidebar-ring: #007fd4;
--destructive-foreground: #ffffff;

/* === Charts === */
--chart-1: #007acc;
--chart-2: #57a64a;
--chart-3: #d69d85;
--chart-4: #569cd6;
--chart-5: #b5cea8;

/* === Custom/Specific Overrides === */
--content-background: #1e1e1e;

/* Tabs */
--tabs-background: #2d2d30;
--tab-background: #2d2d30;
--tab-foreground: #969696;
Expand All @@ -182,6 +189,7 @@
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-brand-claude: var(--brand-claude);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
Expand All @@ -195,12 +203,10 @@
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-background: var(--sidebar-background);
--color-sidebar-project-background: var(--sidebar-project-background);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);

--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);

--color-destructive-foreground: var(--destructive-foreground);
--color-content-background: var(--content-background);
--color-tabs-background: var(--tabs-background);
Expand Down
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function RootLayout({
<body className={`${geist.className} bg-background antialiased`}>
<Providers>{children}</Providers>
<Toaster
position="top-right"
position="bottom-right"
theme="dark"
toastOptions={{
classNames: {
Expand Down
2 changes: 1 addition & 1 deletion components/features/projectList/ProjectCardDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export default function ProjectCardDropdown({ project }: ProjectCardDropdownProp
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
onClick={handleDeleteConfirm}
className="bg-destructive hover:bg-destructive/90 text-white"
className="bg-destructive hover:bg-destructive/90"
>
Delete
</AlertDialogAction>
Expand Down
47 changes: 11 additions & 36 deletions components/features/projectList/ProjectListHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,53 +6,26 @@

'use client';

import { memo, useState } from 'react';
import { useState } from 'react';
import { Plus, User } from 'lucide-react';
import { useSession } from 'next-auth/react';

import CreateProjectDialog from '@/components/dialog/create-project-dialog';
import SettingsDialog from '@/components/dialog/settings-dialog';
import { Button } from '@/components/ui/button';

interface ProjectListHeaderProps {

className?: string;
}

const ProjectListHeader = memo(({ className }: ProjectListHeaderProps) => {
const { data: session } = useSession();
const ProjectListHeader = () => {
const [showSettings, setShowSettings] = useState(false);
const [showCreateProject, setShowCreateProject] = useState(false);

// Get user initials for avatar fallback
// const getUserInitials = () => {
// if (!session?.user?.name) return 'U';
// const names = session.user.name.split(' ');
// if (names.length >= 2) {
// return `${names[0][0]}${names[1][0]}`.toUpperCase();
// }
// return session.user.name[0].toUpperCase();
// };

return (
<>
<div className={`flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-8 ${className || ''}`}>
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-8">
<div>
<h2 className="text-2xl font-bold text-foreground">Projects</h2>
<p className="text-muted-foreground/70 mt-1">Manage your full-stack applications</p>
<h2 className="text-2xl font-bold">Projects</h2>
<p className="text-muted-foreground mt-1">Manage your full-stack applications</p>
</div>
<div className="flex gap-3 w-full sm:w-auto items-center">
{/* TODO: to be implemented */}
{/* <div className="relative flex-1 sm:w-64">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground/50" size={16} />
<input
type="text"
placeholder="Search projects..."
className="w-full bg-secondary/50 border border-border rounded-md pl-9 pr-4 py-2 text-sm text-foreground focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary placeholder:text-muted-foreground/40"
/>
</div> */}
<Button
variant="default"
onClick={() => setShowCreateProject(true)}
className="whitespace-nowrap px-4 py-2 text-sm"
>
Expand All @@ -61,13 +34,15 @@ const ProjectListHeader = memo(({ className }: ProjectListHeaderProps) => {
</Button>

{/* Avatar / Settings Button */}
<button
<Button
variant="secondary"
size="icon"
onClick={() => setShowSettings(true)}
className="w-9 h-9 ml-1 rounded-full bg-secondary/50 border border-border flex items-center justify-center text-muted-foreground hover:text-foreground hover:border-primary transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-background shadow-sm"
className="ml-1 rounded-full border-border text-muted-foreground hover:text-foreground hover:border-primary shadow-sm"
aria-label="User Settings"
>
<User size={18} />
</button>
</Button>
</div>
</div>

Expand All @@ -78,7 +53,7 @@ const ProjectListHeader = memo(({ className }: ProjectListHeaderProps) => {
<SettingsDialog open={showSettings} onOpenChange={setShowSettings} />
</>
);
});
};

ProjectListHeader.displayName = 'ProjectListHeader';

Expand Down
6 changes: 3 additions & 3 deletions components/home-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function HomePage() {
return (
<>
{/* Base marketing page - always visible */}
<div className="min-h-screen flex flex-col items-center justify-start pt-32">
<div className="min-h-screen flex flex-col items-center justify-start pt-28">
{/* Matrix Background Effect */}
<MatrixRain />

Expand All @@ -99,7 +99,7 @@ export function HomePage() {
height={80}
className="w-16 h-16 md:w-20 md:h-20"
/>
<h1 className="md:text-6xl lg:text-8xl font-bold bg-gradient-to-r from-foreground to-muted-foreground bg-clip-text leading-normal text-transparent">
<h1 className="md:text-6xl lg:text-8xl font-bold bg-linear-to-r from-foreground to-muted-foreground bg-clip-text leading-normal text-transparent">
Fulling
</h1>
</div>
Expand All @@ -108,7 +108,7 @@ export function HomePage() {
<p className="text-xl text-primary mb-12">AI-Powered Full-Stack Development Platform</p>
<p className="text-lg text-foreground/80 mb-8 max-w-2xl mx-auto">
Create, develop, and deploy production-ready web applications using natural language.
Powered by <span className="text-[#d97757] bg-[#d97757]/10 px-1 py-0.5 rounded-md font-mono">Claude Code</span> in isolated sandbox environments.
Powered by <span className="text-brand-claude bg-brand-claude/10 px-1 py-0.5 rounded-md font-mono">Claude Code</span> in isolated sandbox environments.
</p>
</div>

Expand Down
6 changes: 3 additions & 3 deletions components/layout/status-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ export function StatusBar({ project }: StatusBarProps) {
</div>

<div className="flex items-center gap-4">
<div className="flex items-center gap-1 hover:bg-card-foreground/10 px-1 rounded cursor-pointer transition-colors">
<div className="flex items-center gap-1 px-1 rounded cursor-pointer transition-colors">
<Box className={`w-3 h-3 ${getStatusIconColor(sbStatus)}`} />
<span>Sandbox: {sbStatus}</span>
</div>
<div className="w-px h-3 bg-card-foreground/20 mx-1" />
<div className="flex items-center gap-1 hover:bg-card-foreground/10 px-1 rounded cursor-pointer transition-colors">
<div className="w-px h-3 bg-card-foreground/60 mx-1" />
<div className="flex items-center gap-1 px-1 rounded cursor-pointer transition-colors">
<Database className={`w-3 h-3 ${getStatusIconColor(dbStatus)}`} />
<span>Database: {dbStatus}</span>
</div>
Expand Down
6 changes: 3 additions & 3 deletions components/ui/alert-dialog-vscode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ function AlertDialogContent({
<AlertDialogPrimitive.Content
data-slot="alert-dialog-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:max-w-lg",
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:max-w-lg rounded-lg",
className
)}
onClick={(e) => e.stopPropagation()}
Expand Down Expand Up @@ -139,7 +139,7 @@ function AlertDialogAction({
}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
return (
<AlertDialogPrimitive.Action
className={cn(buttonVariants(), "rounded-none", className)}
className={cn(buttonVariants(), className)}
{...props}
/>
)
Expand All @@ -151,7 +151,7 @@ function AlertDialogCancel({
}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
return (
<AlertDialogPrimitive.Cancel
className={cn(buttonVariants({ variant: "outline" }), "rounded-none", className)}
className={cn(buttonVariants({ variant: "outline" }), className)}
{...props}
/>
)
Expand Down
2 changes: 1 addition & 1 deletion components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const buttonVariants = cva(
secondary:
"bg-secondary text-secondary-foreground border border-border hover:bg-border",
ghost:
"text-secondary-foreground hover:bg-border",
"text-muted-foreground hover:bg-border hover:text-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
Expand Down
14 changes: 7 additions & 7 deletions components/ui/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
)}
{...props}
Expand Down Expand Up @@ -74,7 +74,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-muted focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive! [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-inset:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
Expand All @@ -92,7 +92,7 @@ function DropdownMenuCheckboxItem({
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-muted focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
checked={checked}
Expand Down Expand Up @@ -128,7 +128,7 @@ function DropdownMenuRadioItem({
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-md py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
Expand All @@ -155,7 +155,7 @@ function DropdownMenuLabel({
data-slot="dropdown-menu-label"
data-inset={inset}
className={cn(
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
"px-2 py-1.5 text-sm font-medium data-inset:pl-8",
className
)}
{...props}
Expand Down Expand Up @@ -211,7 +211,7 @@ function DropdownMenuSubTrigger({
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-hidden select-none data-inset:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
Expand All @@ -230,7 +230,7 @@ function DropdownMenuSubContent({
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-32 origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
className
)}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion lib/util/status-colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function getStatusIconColor(status: Status): string {
case 'STOPPED':
case 'TERMINATED':
default:
return 'text-[#858585]'
return ''
}
}

Expand Down