diff --git a/package-lock.json b/package-lock.json index 8ccedf3..43a7fe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2016,7 +2016,6 @@ "version": "19.2.9", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.9.tgz", "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==", - "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -2679,7 +2678,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, "license": "MIT" }, "node_modules/debug": { @@ -5253,7 +5251,6 @@ "version": "4.1.18", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", - "dev": true, "license": "MIT" }, "node_modules/tapable": { diff --git a/src/components/ThemeSwitcher.tsx b/src/components/ThemeSwitcher.tsx new file mode 100644 index 0000000..f9de3ef --- /dev/null +++ b/src/components/ThemeSwitcher.tsx @@ -0,0 +1,98 @@ +import { useState } from 'react'; +import { Palette, ChevronUp } from 'lucide-react'; + +const THEMES = [ + // Dark Themes + { name: 'Monokai', value: '' }, + { name: 'Dracula', value: 'theme-dracula' }, + { name: 'Nord', value: 'theme-nord' }, + { name: 'Solarized Dark', value: 'theme-solarized-dark' }, + { name: 'One Dark', value: 'theme-one-dark' }, + { name: 'Gruvbox Dark', value: 'theme-gruvbox-dark' }, + { name: 'Tokyo Night', value: 'theme-tokyo-night' }, + { name: 'Material Dark', value: 'theme-material-dark' }, + // Light Themes + { name: 'Light', value: 'theme-light' }, + { name: 'GitHub Light', value: 'theme-github-light' }, + { name: 'Solarized Light', value: 'theme-solarized-light' }, + { name: 'One Light', value: 'theme-one-light' }, +]; + +export function ThemeSwitcher() { + const [isOpen, setIsOpen] = useState(false); + const [currentTheme, setCurrentTheme] = useState(''); + + const handleThemeChange = (themeValue: string) => { + setCurrentTheme(themeValue); + + // Remove all theme classes + THEMES.forEach(theme => { + if (theme.value) { + document.documentElement.classList.remove(theme.value); + } + }); + + // Add selected theme class + if (themeValue) { + document.documentElement.classList.add(themeValue); + } + + setIsOpen(false); + }; + + // const currentThemeName = THEMES.find(t => t.value === currentTheme)?.name || 'Monokai'; + + return ( +
+ + + {isOpen && ( +
+ {THEMES.map((theme) => ( + + ))} +
+ )} +
+ ); +} diff --git a/src/components/layout/ActivityBar.tsx b/src/components/layout/ActivityBar.tsx index b88b1f6..fec44d4 100644 --- a/src/components/layout/ActivityBar.tsx +++ b/src/components/layout/ActivityBar.tsx @@ -1,17 +1,23 @@ -import { Files, Search, GitBranch, Settings, CircleUser } from 'lucide-react'; +import { Files, Search, GitBranch, CircleUser, Lock } from 'lucide-react'; import { ActivityBarItem } from './ActivityBarItem'; export function ActivityBar() { return ( -
+
+
-
); diff --git a/src/components/layout/ActivityBarItem.tsx b/src/components/layout/ActivityBarItem.tsx index 25ca5f3..55346ec 100644 --- a/src/components/layout/ActivityBarItem.tsx +++ b/src/components/layout/ActivityBarItem.tsx @@ -7,7 +7,24 @@ interface ActivityBarItemProps { export function ActivityBarItem({ icon: Icon, active = false }: ActivityBarItemProps) { return ( -
+
{ + if (!active) { + e.currentTarget.style.color = 'var(--activity-item-text-hover)'; + } + }} + onMouseLeave={(e) => { + if (!active) { + e.currentTarget.style.color = 'var(--activity-item-text-default)'; + } + }} + >
); diff --git a/src/components/layout/MainLayout.tsx b/src/components/layout/MainLayout.tsx index 16b4b97..c39e4b2 100644 --- a/src/components/layout/MainLayout.tsx +++ b/src/components/layout/MainLayout.tsx @@ -2,6 +2,8 @@ import type { ReactNode } from 'react'; import { Panel, Group, Separator } from 'react-resizable-panels'; import { ActivityBar } from './ActivityBar'; import { TitleBar } from './TitleBar'; +import { useAppStore } from '../../store/useAppStore'; +import { ChevronRight } from 'lucide-react'; interface MainLayoutProps { sidebarContent: ReactNode; @@ -9,8 +11,16 @@ interface MainLayoutProps { } export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) { + const { isExplorerCollapsed, toggleExplorerCollapsed } = useAppStore(); + return ( -
+
@@ -21,17 +31,57 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
{/* Sidebar Panel */} - -
- {sidebarContent} -
-
+ {!isExplorerCollapsed && ( + <> + +
+ {sidebarContent} +
+
- + + + )} + + {/* Collapsed Sidebar - VS Code Style */} + {isExplorerCollapsed && ( +
+ +
+ )} {/* Editor Panel */} - -
+ +
{editorContent}
diff --git a/src/components/layout/TitleBar.tsx b/src/components/layout/TitleBar.tsx index 0e2bf01..8858ff8 100644 --- a/src/components/layout/TitleBar.tsx +++ b/src/components/layout/TitleBar.tsx @@ -1,7 +1,18 @@ export function TitleBar() { return ( -
- Cinder Notes +
+ + Cinder Notes +
); } diff --git a/src/components/layout/editor/Editor.tsx b/src/components/layout/editor/Editor.tsx index 8440ceb..27e227d 100644 --- a/src/components/layout/editor/Editor.tsx +++ b/src/components/layout/editor/Editor.tsx @@ -1,59 +1,97 @@ -import { useState } from 'react'; import { useAppStore } from '../../../store/useAppStore'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; -import { Eye, Edit2 } from 'lucide-react'; +import { Eye, ChevronLeft, FileText, Save, Sparkles } from 'lucide-react'; -export function Editor() { +interface EditorProps { + isPreview: boolean; + onPreviewChange?: (isPreview: boolean) => void; +} + +export function Editor({ isPreview }: EditorProps) { const { activeFileId, activeFileContent, updateFileContent } = useAppStore(); - const [isPreview, setIsPreview] = useState(false); + + // Check if this is a blank tab + const isBlankTab = activeFileId?.startsWith('new-tab-'); // If no active file, just show empty state in main area // Tabs are now handled by EditorPane return ( -
+
- {!activeFileId ? ( -
+ {!activeFileId || isBlankTab ? ( +
-

No file selected

+
+ +
+

Cinder Notes

+
+
+ +

Select a file from the explorer to start editing

+
+
+ +

Create new notes in Markdown format

+
+
+ +

Toggle preview mode to see rendered content

+
+
+ +

Auto-saves as you type

+
+
) : (
- {/* Toolbar/Toggle */} - - {isPreview ? ( -
+
{activeFileContent}
) : ( -