diff --git a/frontend/index.html b/frontend/index.html
index 1d1565b3..c2219aac 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -5,6 +5,18 @@
frontend
+
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 22ccc167..1e944ede 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -39,7 +39,7 @@ function App() {
return (
-
+
);
}
diff --git a/frontend/src/components/EditorLayout.tsx b/frontend/src/components/EditorLayout.tsx
index d9712c38..ee7b1480 100644
--- a/frontend/src/components/EditorLayout.tsx
+++ b/frontend/src/components/EditorLayout.tsx
@@ -47,7 +47,13 @@ export default function EditorLayout() {
const [isLoading, setIsLoading] = useState(false);
const [isActionLoading, setIsActionLoading] = useState(false);
const [isFileLoading, setIsFileLoading] = useState(false);
- const [isDarkMode, setIsDarkMode] = useState(true);
+ const [isDarkMode, setIsDarkMode] = useState(() => {
+ const saved = localStorage.getItem('sencho-theme');
+ if (saved !== null) {
+ return saved === 'dark';
+ }
+ return true; // Default to dark mode
+ });
const [showConsole, setShowConsole] = useState(true);
const [isEditing, setIsEditing] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
@@ -65,8 +71,10 @@ export default function EditorLayout() {
const html = document.documentElement;
if (isDarkMode) {
html.classList.add('dark');
+ localStorage.setItem('sencho-theme', 'dark');
} else {
html.classList.remove('dark');
+ localStorage.setItem('sencho-theme', 'light');
}
}, [isDarkMode]);
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 73c21b3d..3157c4fe 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,117 +1,180 @@
-@import 'tailwindcss';
+@import "tailwindcss";
@plugin 'tailwindcss-animate';
@custom-variant dark (&:is(.dark *));
-@theme {
- --color-border: hsl(var(--border));
- --color-input: hsl(var(--input));
- --color-ring: hsl(var(--ring));
- --color-background: hsl(var(--background));
- --color-foreground: hsl(var(--foreground));
+:root {
+ --background: oklch(1 0 0);
+ --foreground: oklch(0 0 0);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0 0 0);
+ --popover: oklch(0.9900 0 0);
+ --popover-foreground: oklch(0 0 0);
+ --primary: oklch(0 0 0);
+ --primary-foreground: oklch(1 0 0);
+ --secondary: oklch(0.9400 0 0);
+ --secondary-foreground: oklch(0 0 0);
+ --muted: oklch(0.9700 0 0);
+ --muted-foreground: oklch(0.4400 0 0);
+ --accent: oklch(0.9400 0 0);
+ --accent-foreground: oklch(0 0 0);
+ --destructive: oklch(0.6300 0.1900 23.0300);
+ --destructive-foreground: oklch(1 0 0);
+ --border: oklch(0.9200 0 0);
+ --input: oklch(0.9400 0 0);
+ --ring: oklch(0 0 0);
+ --chart-1: oklch(0.8100 0.1700 75.3500);
+ --chart-2: oklch(0.5500 0.2200 264.5300);
+ --chart-3: oklch(0.7200 0 0);
+ --chart-4: oklch(0.9200 0 0);
+ --chart-5: oklch(0.5600 0 0);
+ --sidebar: oklch(0.9900 0 0);
+ --sidebar-foreground: oklch(0 0 0);
+ --sidebar-primary: oklch(0 0 0);
+ --sidebar-primary-foreground: oklch(1 0 0);
+ --sidebar-accent: oklch(0.9400 0 0);
+ --sidebar-accent-foreground: oklch(0 0 0);
+ --sidebar-border: oklch(0.9400 0 0);
+ --sidebar-ring: oklch(0 0 0);
+ --font-sans: Geist, sans-serif;
+ --font-serif: Georgia, serif;
+ --font-mono: Geist Mono, monospace;
+ --radius: 0.5rem;
+ --shadow-x: 0px;
+ --shadow-y: 1px;
+ --shadow-blur: 2px;
+ --shadow-spread: 0px;
+ --shadow-opacity: 0.18;
+ --shadow-color: hsl(0 0% 0%);
+ --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
+ --shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
+ --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
+ --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
+ --shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
+ --shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
+ --shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
+ --shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
+ --tracking-normal: 0em;
+ --spacing: 0.25rem;
+}
- --color-primary: hsl(var(--primary));
- --color-primary-foreground: hsl(var(--primary-foreground));
+.dark {
+ --background: oklch(0.1400 0 0);
+ --foreground: oklch(1 0 0);
+ --card: oklch(0.1400 0 0);
+ --card-foreground: oklch(1 0 0);
+ --popover: oklch(0.1800 0 0);
+ --popover-foreground: oklch(1 0 0);
+ --primary: oklch(1 0 0);
+ --primary-foreground: oklch(0 0 0);
+ --secondary: oklch(0.2500 0 0);
+ --secondary-foreground: oklch(1 0 0);
+ --muted: oklch(0.2300 0 0);
+ --muted-foreground: oklch(0.7200 0 0);
+ --accent: oklch(0.3200 0 0);
+ --accent-foreground: oklch(1 0 0);
+ --destructive: oklch(0.6900 0.2000 23.9100);
+ --destructive-foreground: oklch(0 0 0);
+ --border: oklch(0.2600 0 0);
+ --input: oklch(0.3200 0 0);
+ --ring: oklch(0.7200 0 0);
+ --chart-1: oklch(0.8100 0.1700 75.3500);
+ --chart-2: oklch(0.5800 0.2100 260.8400);
+ --chart-3: oklch(0.5600 0 0);
+ --chart-4: oklch(0.4400 0 0);
+ --chart-5: oklch(0.9200 0 0);
+ --sidebar: oklch(0.1800 0 0);
+ --sidebar-foreground: oklch(1 0 0);
+ --sidebar-primary: oklch(1 0 0);
+ --sidebar-primary-foreground: oklch(0 0 0);
+ --sidebar-accent: oklch(0.3200 0 0);
+ --sidebar-accent-foreground: oklch(1 0 0);
+ --sidebar-border: oklch(0.3200 0 0);
+ --sidebar-ring: oklch(0.7200 0 0);
+ --font-sans: Geist, sans-serif;
+ --font-serif: Georgia, serif;
+ --font-mono: Geist Mono, monospace;
+ --radius: 0.5rem;
+ --shadow-x: 0px;
+ --shadow-y: 1px;
+ --shadow-blur: 2px;
+ --shadow-spread: 0px;
+ --shadow-opacity: 0.18;
+ --shadow-color: hsl(0 0% 0%);
+ --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
+ --shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
+ --shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
+ --shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
+ --shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
+ --shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
+ --shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
+ --shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
+}
- --color-secondary: hsl(var(--secondary));
- --color-secondary-foreground: hsl(var(--secondary-foreground));
+@theme inline {
+ --color-background: var(--background);
+ --color-foreground: var(--foreground);
+ --color-card: var(--card);
+ --color-card-foreground: var(--card-foreground);
+ --color-popover: var(--popover);
+ --color-popover-foreground: var(--popover-foreground);
+ --color-primary: var(--primary);
+ --color-primary-foreground: var(--primary-foreground);
+ --color-secondary: var(--secondary);
+ --color-secondary-foreground: var(--secondary-foreground);
+ --color-muted: var(--muted);
+ --color-muted-foreground: var(--muted-foreground);
+ --color-accent: var(--accent);
+ --color-accent-foreground: var(--accent-foreground);
+ --color-destructive: var(--destructive);
+ --color-destructive-foreground: var(--destructive-foreground);
+ --color-border: var(--border);
+ --color-input: var(--input);
+ --color-ring: var(--ring);
+ --color-chart-1: var(--chart-1);
+ --color-chart-2: var(--chart-2);
+ --color-chart-3: var(--chart-3);
+ --color-chart-4: var(--chart-4);
+ --color-chart-5: var(--chart-5);
+ --color-sidebar: var(--sidebar);
+ --color-sidebar-foreground: var(--sidebar-foreground);
+ --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: hsl(var(--destructive));
- --color-destructive-foreground: hsl(var(--destructive-foreground));
+ --font-sans: var(--font-sans);
+ --font-mono: var(--font-mono);
+ --font-serif: var(--font-serif);
- --color-muted: hsl(var(--muted));
- --color-muted-foreground: hsl(var(--muted-foreground));
-
- --color-accent: hsl(var(--accent));
- --color-accent-foreground: hsl(var(--accent-foreground));
-
- --color-popover: hsl(var(--popover));
- --color-popover-foreground: hsl(var(--popover-foreground));
-
- --color-card: hsl(var(--card));
- --color-card-foreground: hsl(var(--card-foreground));
-
- --radius-lg: var(--radius);
- --radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
- --color-chart-1: hsl(var(--chart-1));
- --color-chart-2: hsl(var(--chart-2));
- --color-chart-3: hsl(var(--chart-3));
- --color-chart-4: hsl(var(--chart-4));
- --color-chart-5: hsl(var(--chart-5));
+ --shadow-2xs: var(--shadow-2xs);
+ --shadow-xs: var(--shadow-xs);
+ --shadow-sm: var(--shadow-sm);
+ --shadow: var(--shadow);
+ --shadow-md: var(--shadow-md);
+ --shadow-lg: var(--shadow-lg);
+ --shadow-xl: var(--shadow-xl);
+ --shadow-2xl: var(--shadow-2xl);
}
@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
- *,
- ::after,
- ::before,
- ::backdrop,
- ::file-selector-button {
- border-color: var(--color-border, currentColor);
+ body {
+ @apply bg-background text-foreground;
}
}
-@layer base {
- :root {
- --background: 0 0% 100%;
- --foreground: 0 0% 3.9%;
- --card: 0 0% 100%;
- --card-foreground: 0 0% 3.9%;
- --popover: 0 0% 100%;
- --popover-foreground: 0 0% 3.9%;
- --primary: 0 0% 9%;
- --primary-foreground: 0 0% 98%;
- --secondary: 0 0% 96.1%;
- --secondary-foreground: 0 0% 9%;
- --muted: 0 0% 96.1%;
- --muted-foreground: 0 0% 45.1%;
- --accent: 0 0% 96.1%;
- --accent-foreground: 0 0% 9%;
- --destructive: 0 84.2% 60.2%;
- --destructive-foreground: 0 0% 98%;
- --border: 0 0% 89.8%;
- --input: 0 0% 89.8%;
- --ring: 0 0% 3.9%;
- --radius: 0.5rem;
- --chart-1: 12 76% 61%;
- --chart-2: 173 58% 39%;
- --chart-3: 197 37% 24%;
- --chart-4: 43 74% 66%;
- --chart-5: 27 87% 67%;
- }
-
- .dark {
- --background: 0 0% 3.9%;
- --foreground: 0 0% 98%;
- --card: 0 0% 3.9%;
- --card-foreground: 0 0% 98%;
- --popover: 0 0% 3.9%;
- --popover-foreground: 0 0% 98%;
- --primary: 0 0% 98%;
- --primary-foreground: 0 0% 9%;
- --secondary: 0 0% 14.9%;
- --secondary-foreground: 0 0% 98%;
- --muted: 0 0% 14.9%;
- --muted-foreground: 0 0% 63.9%;
- --accent: 0 0% 14.9%;
- --accent-foreground: 0 0% 98%;
- --destructive: 0 62.8% 30.6%;
- --destructive-foreground: 0 0% 98%;
- --border: 0 0% 14.9%;
- --input: 0 0% 14.9%;
- --ring: 0 0% 83.1%;
- --chart-1: 220 70% 50%;
- --chart-2: 160 60% 45%;
- --chart-3: 30 80% 55%;
- --chart-4: 280 65% 60%;
- --chart-5: 340 75% 55%;
- }
-}
-
-
html,
body,
#root {
@@ -121,7 +184,7 @@ body,
}
body {
- font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ font-family: var(--font-sans), system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.5;
font-weight: 400;
font-synthesis: none;