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
3 changes: 0 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

98 changes: 98 additions & 0 deletions src/components/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="relative">
<button
onClick={() => setIsOpen(!isOpen)}
className="p-1.5 cursor-pointer rounded group transition-colors flex items-center gap-1"
style={{ color: 'var(--text-primary)' }}
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'var(--bg-tertiary)'}
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
title="Theme"
>
<Palette size={14} className="opacity-60 group-hover:opacity-100" />
{isOpen && <ChevronUp size={12} className="opacity-60" />}
</button>

{isOpen && (
<div
className="absolute bottom-full right-0 mb-1 rounded border shadow-lg z-50 min-w-[150px]"
style={{
backgroundColor: 'var(--bg-secondary)',
borderColor: 'var(--border-primary)',
boxShadow: '0 -4px 12px rgba(0, 0, 0, 0.3)',
}}
>
{THEMES.map((theme) => (
<button
key={theme.value}
onClick={() => handleThemeChange(theme.value)}
className={`w-full text-left px-3 py-1.5 text-[12px] transition-colors flex items-center justify-between ${
currentTheme === theme.value ? 'font-semibold' : ''
}`}
style={{
backgroundColor: currentTheme === theme.value ? 'var(--bg-tertiary)' : 'transparent',
color: currentTheme === theme.value ? 'var(--text-primary)' : 'var(--text-secondary)',
}}
onMouseEnter={(e) => {
if (currentTheme !== theme.value) {
e.currentTarget.style.backgroundColor = 'var(--bg-hover)';
}
}}
onMouseLeave={(e) => {
if (currentTheme !== theme.value) {
e.currentTarget.style.backgroundColor = 'transparent';
}
}}
>
{theme.name}
{currentTheme === theme.value && <span className="text-[10px]">✓</span>}
</button>
))}
</div>
)}
</div>
);
}
12 changes: 9 additions & 3 deletions src/components/layout/ActivityBar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="w-[50px] flex-shrink-0 flex flex-col bg-[#272822] border-l border-[#171717] items-center py-2 z-10">
<div
className="w-[50px] flex-shrink-0 flex flex-col items-center py-2 z-10"
style={{
backgroundColor: 'var(--activity-bar-bg)',
borderLeft: `1px solid var(--activity-bar-border)`
}}
>
<div className="flex-1 flex flex-col gap-2">
<ActivityBarItem icon={Files} active />
<ActivityBarItem icon={Search} />
<ActivityBarItem icon={GitBranch} />
<ActivityBarItem icon={Lock} />
</div>
<div className="flex flex-col gap-2 pb-2">
<ActivityBarItem icon={CircleUser} />
<ActivityBarItem icon={Settings} />
</div>
</div>
);
Expand Down
19 changes: 18 additions & 1 deletion src/components/layout/ActivityBarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,24 @@ interface ActivityBarItemProps {

export function ActivityBarItem({ icon: Icon, active = false }: ActivityBarItemProps) {
return (
<div className={`p-3 cursor-pointer hover:text-white transition-colors ${active ? 'text-white border-l-2 border-[#f92672]' : 'text-[#8f908a]'}`}>
<div
className={`p-3 cursor-pointer transition-colors ${active ? 'border-l-2' : ''}`}
style={{
color: active ? 'var(--activity-item-text-active)' : 'var(--activity-item-text-default)',
backgroundColor: active ? 'var(--activity-item-bg-active)' : 'transparent',
borderLeft: active ? `2px solid var(--activity-item-border-active)` : 'none',
}}
onMouseEnter={(e) => {
if (!active) {
e.currentTarget.style.color = 'var(--activity-item-text-hover)';
}
}}
onMouseLeave={(e) => {
if (!active) {
e.currentTarget.style.color = 'var(--activity-item-text-default)';
}
}}
>
<Icon size={24} strokeWidth={1.5} />
</div>
);
Expand Down
68 changes: 59 additions & 9 deletions src/components/layout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,25 @@ 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;
editorContent: ReactNode;
}

export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
const { isExplorerCollapsed, toggleExplorerCollapsed } = useAppStore();

return (
<div className="h-screen w-screen flex flex-col bg-[#1e1f1c] text-[#cfcfc2] overflow-hidden">
<div
className="h-screen w-screen flex flex-col overflow-hidden"
style={{
backgroundColor: 'var(--bg-primary)',
color: 'var(--text-primary)'
}}
>

<TitleBar />

Expand All @@ -21,17 +31,57 @@ export function MainLayout({ sidebarContent, editorContent }: MainLayoutProps) {
<div className="flex-1 flex min-w-0 h-full">
<Group orientation="horizontal">
{/* Sidebar Panel */}
<Panel id="sidebar" defaultSize={20} minSize={10}>
<div className="flex flex-col bg-[#1e1f1c] h-full w-full">
{sidebarContent}
</div>
</Panel>
{!isExplorerCollapsed && (
<>
<Panel id="sidebar" defaultSize={20} minSize={10} collapsible={true} collapsedSize={0}>
<div
className="flex flex-col h-full w-full"
style={{ backgroundColor: 'var(--bg-primary)' }}
>
{sidebarContent}
</div>
</Panel>

<Separator id="resize-handle" className="w-[4px] bg-[#171717] hover:bg-[#f92672] transition-colors cursor-col-resize z-50 active:bg-[#f92672] flex-shrink-0" />
<Separator
id="resize-handle"
className="w-[4px] transition-colors cursor-col-resize z-50 flex-shrink-0"
style={{
backgroundColor: 'var(--border-primary)',
}}
/>
</>
)}

{/* Collapsed Sidebar - VS Code Style */}
{isExplorerCollapsed && (
<div
className="w-[35px] flex-shrink-0 flex flex-col items-center py-3 gap-2 transition-colors"
style={{
backgroundColor: 'var(--bg-primary)',
borderRight: '1px solid var(--border-secondary)'
}}
>
<button
onClick={() => toggleExplorerCollapsed()}
className="p-2 rounded transition-colors group"
style={{
color: 'var(--text-primary)',
}}
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'var(--bg-tertiary)'}
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
title="Explorer"
>
<ChevronRight size={18} />
</button>
</div>
)}

{/* Editor Panel */}
<Panel id="editor" defaultSize={80} minSize={30}>
<div className="flex flex-col bg-[#272822] h-full w-full">
<Panel id="editor" defaultSize={isExplorerCollapsed ? 95 : 80} minSize={30}>
<div
className="flex flex-col h-full w-full"
style={{ backgroundColor: 'var(--bg-secondary)' }}
>
{editorContent}
</div>
</Panel>
Expand Down
15 changes: 13 additions & 2 deletions src/components/layout/TitleBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
export function TitleBar() {
return (
<div className="h-[35px] bg-[#1e1f1c] flex items-center justify-center border-b border-[#171717] select-none drag-region">
<span className="text-[13px] font-medium text-[#cfcfc2] opacity-80">Cinder Notes</span>
<div
className="h-[35px] flex items-center justify-center border-b select-none drag-region"
style={{
backgroundColor: 'var(--bg-primary)',
borderColor: 'var(--border-primary)'
}}
>
<span
className="text-[13px] font-medium opacity-80"
style={{ color: 'var(--text-primary)' }}
>
Cinder Notes
</span>
</div>
);
}
Loading