Skip to content
This repository was archived by the owner on Feb 25, 2026. It is now read-only.

Commit dc2d405

Browse files
author
8to16
committed
theme
1 parent 65dc765 commit dc2d405

4 files changed

Lines changed: 133 additions & 112 deletions

File tree

src/globalstyles/colors.css

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
/* this is global so no need to import it */
22
/* TODO: better theming system */
33

4-
:root {
4+
html {
5+
color-scheme: light;
6+
57
/* omniblocks colours */
68
--accent-1: #59c0c0;
79
--accent-2: #49b0b0;
@@ -16,7 +18,9 @@
1618
}
1719

1820
/* turn the light stuff into dark */
19-
:global(.ob-dark-theme) {
21+
html.ob-dark-theme {
22+
color-scheme: dark;
23+
2024
--page-background: #33333f;
2125
--page-foreground: white;
2226
--black-transparent: #ffffff33;

src/lib/Layout.jsx

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@ const AppShell = styled.div`
1212
flex-direction: column;
1313
height: 100vh;
1414
width: 100vw;
15-
background-color: var(--page-background, #1e1e1e);
16-
color: var(--page-foreground, #cccccc);
15+
background-color: var(--page-background);
16+
color: var(--page-foreground);
1717
overflow: hidden;
1818
label: AppShell;
1919
`;
2020

2121
const ActivityBar = styled.nav`
2222
width: 48px;
23-
background-color: var(--activity-bar-bg, #333);
24-
border-right: 1px solid var(--border-color, #252525);
23+
/* Slightly darker or same as background depending on theme */
24+
background-color: var(--page-background);
25+
border-right: 1px solid var(--black-transparent);
2526
display: flex;
2627
flex-direction: column;
2728
align-items: center;
@@ -32,8 +33,9 @@ const ActivityBar = styled.nav`
3233

3334
const TabList = styled(Tabs.List)`
3435
display: flex;
35-
background: var(--tab-bar-bg, #252526);
36-
border-bottom: 1px solid rgba(0,0,0,0.3);
36+
/* Uses the transparent black to slightly darken the tab row */
37+
background: var(--black-transparent);
38+
border-bottom: 1px solid var(--black-transparent);
3739
height: 35px;
3840
label: TabList;
3941
`;
@@ -43,24 +45,31 @@ const TabTrigger = styled(Tabs.Trigger)`
4345
font-size: 11px;
4446
border: none;
4547
background: transparent;
46-
color: #888;
48+
color: var(--page-foreground);
49+
opacity: 0.6;
4750
cursor: pointer;
4851
display: flex;
4952
align-items: center;
50-
transition: background 0.2s;
53+
transition: all 0.2s;
54+
5155
&[data-state='active'] {
52-
color: #fff;
53-
background: var(--editor-bg, #1e1e1e);
54-
border-bottom: 1px solid var(--accent-1, #007acc);
56+
opacity: 1;
57+
background: var(--page-background);
58+
border-bottom: 2px solid var(--accent-1);
59+
}
60+
61+
&:hover {
62+
background: var(--white-transparent);
63+
opacity: 1;
5564
}
56-
&:hover { background: rgba(255,255,255,0.05); }
5765
label: TabTrigger;
5866
`;
5967

6068
const StatusBar = styled.footer`
6169
height: 22px;
62-
background-color: var(--status-bar-bg, #007acc);
63-
color: white;
70+
/* Use accent color for the classic IDE status bar look */
71+
background-color: var(--accent-1);
72+
color: white;
6473
display: flex;
6574
align-items: center;
6675
justify-content: space-between;
@@ -70,10 +79,22 @@ const StatusBar = styled.footer`
7079
`;
7180

7281
const Resizer = styled(Separator)`
73-
background-color: #000;
74-
&[aria-orientation="horizontal"] { cursor: col-resize; }
75-
&[aria-orientation="vertical"] { cursor: row-resize; }
76-
&:hover { background-color: var(--accent-1, #007acc); }
82+
background-color: var(--black-transparent);
83+
transition: background-color 0.2s;
84+
85+
&[aria-orientation="horizontal"] {
86+
width: 2px;
87+
cursor: col-resize;
88+
}
89+
&[aria-orientation="vertical"] {
90+
height: 2px;
91+
cursor: row-resize;
92+
}
93+
94+
&[data-resize-handle-active],
95+
&:hover {
96+
background-color: var(--accent-1);
97+
}
7798
`;
7899

79100
// --- Slot Helpers ---
@@ -89,13 +110,25 @@ const TabbedSlot = ({ panels, activeId, onToggle, onSelect }) => {
89110
<div style={{ flex: 1 }} />
90111
<button
91112
onClick={() => onToggle(activeId)}
92-
style={{ background: 'none', border: 'none', color: '#888', cursor: 'pointer', padding: '0 10px', fontSize: '14px' }}
113+
style={{
114+
background: 'none',
115+
border: 'none',
116+
color: 'var(--page-foreground)',
117+
opacity: 0.5,
118+
cursor: 'pointer',
119+
padding: '0 10px',
120+
fontSize: '14px'
121+
}}
93122
>
94123
×
95124
</button>
96125
</TabList>
97126
{panels.map(p => (
98-
<Tabs.Content key={p.id} value={p.id} style={{ flex: 1, overflow: 'auto', background: 'var(--editor-bg, #1e1e1e)' }}>
127+
<Tabs.Content
128+
key={p.id}
129+
value={p.id}
130+
style={{ flex: 1, overflow: 'auto', background: 'var(--page-background)' }}
131+
>
99132
{p.component}
100133
</Tabs.Content>
101134
))}
@@ -115,7 +148,6 @@ export const OmniLayout = () => {
115148
activeSelection
116149
} = useOmniLayout();
117150

118-
// Sort panels into UI buckets
119151
const sidebarPanels = panels.filter(p => p.position === 'left');
120152
const activeSidebar = sidebarPanels.find(p => isOpen(p.id));
121153

@@ -126,17 +158,18 @@ export const OmniLayout = () => {
126158
<AppShell>
127159
<div style={{ display: 'flex', flex: 1, overflow: 'hidden' }}>
128160

129-
{/* 1. Activity Bar (Icons for Sidebars) */}
161+
{/* 1. Activity Bar */}
130162
<ActivityBar>
131163
{sidebarPanels.map(p => (
132164
<div
133165
key={p.id}
134166
onClick={() => togglePanel(p.id)}
135167
style={{
136168
cursor: 'pointer',
169+
color: isOpen(p.id) ? 'var(--accent-1)' : 'var(--page-foreground)',
137170
opacity: isOpen(p.id) ? 1 : 0.4,
138171
fontSize: 20,
139-
transition: 'opacity 0.2s'
172+
transition: 'all 0.2s'
140173
}}
141174
title={p.title}
142175
>
@@ -151,8 +184,19 @@ export const OmniLayout = () => {
151184
{/* Sidebar Slot */}
152185
{activeSidebar && (
153186
<>
154-
<Panel collapsible defaultSize={20} minSize={10} style={{ display: 'flex', flexDirection: 'column', background: '#252526' }}>
155-
<div style={{ height: '35px', padding: '0 12px', display: 'flex', alignItems: 'center', fontSize: 11, fontWeight: 700, borderBottom: '1px solid rgba(0,0,0,0.2)' }}>
187+
<Panel collapsible defaultSize={20} minSize={10} style={{ display: 'flex', flexDirection: 'column', background: 'var(--black-transparent)' }}>
188+
<div style={{
189+
height: '35px',
190+
padding: '0 12px',
191+
display: 'flex',
192+
alignItems: 'center',
193+
fontSize: 11,
194+
fontWeight: 700,
195+
letterSpacing: '0.5px',
196+
borderBottom: '1px solid var(--black-transparent)',
197+
color: 'var(--page-foreground)',
198+
opacity: 0.8
199+
}}>
156200
{activeSidebar.title.toUpperCase()}
157201
</div>
158202
<div style={{ flex: 1, overflow: 'auto' }}>{activeSidebar.component}</div>
@@ -194,7 +238,7 @@ export const OmniLayout = () => {
194238
</Group>
195239
</div>
196240

197-
{/* 3. Hackable Status Bar */}
241+
{/* 3. Status Bar */}
198242
<StatusBar>
199243
<div style={{ display: 'flex', gap: '15px' }}>
200244
{statusItems.filter(i => i.alignment === 'left').map(item => (

src/lib/Monaco.jsx

Lines changed: 56 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,51 @@
22
import React, { useRef, useEffect, useState } from 'react';
33
import Editor, { loader } from '@monaco-editor/react';
44

5-
// --- Lazy Worker Configuration ---
6-
const configureMonacoEnvironment = () => {
7-
if (typeof self === 'undefined' || self.MonacoEnvironment) return;
8-
9-
self.MonacoEnvironment = {
10-
async getWorker(_, label) {
11-
let WorkerModule;
12-
switch (label) {
13-
case 'json':
14-
WorkerModule = await import('monaco-editor/esm/vs/language/json/json.worker?worker');
15-
break;
16-
case 'css':
17-
case 'scss':
18-
case 'less':
19-
WorkerModule = await import('monaco-editor/esm/vs/language/css/css.worker?worker');
20-
break;
21-
case 'html':
22-
case 'handlebars':
23-
case 'razor':
24-
WorkerModule = await import('monaco-editor/esm/vs/language/html/html.worker?worker');
25-
break;
26-
case 'typescript':
27-
case 'javascript':
28-
WorkerModule = await import('monaco-editor/esm/vs/language/typescript/ts.worker?worker');
29-
break;
30-
default:
31-
WorkerModule = await import('monaco-editor/esm/vs/editor/editor.worker?worker');
32-
}
33-
return new WorkerModule.default();
34-
},
35-
};
36-
};
37-
38-
const MonacoEditor = ({
39-
language = 'javascript',
40-
value = '',
41-
onChange,
42-
theme = 'omni-dark'
43-
}) => {
44-
const editorRef = useRef(null);
5+
const MonacoEditor = ({ language = 'javascript', value = '', onChange }) => {
6+
const monacoRef = useRef(null);
457
const [isReady, setIsReady] = useState(false);
468

9+
// Helper to get current theme name based on HTML class
10+
const getThemeName = () =>
11+
document.documentElement.classList.contains('ob-dark-theme') ? 'omni-dark' : 'omni-light';
12+
4713
useEffect(() => {
4814
let isMounted = true;
4915

5016
const initMonaco = async () => {
51-
// 1. Setup workers
52-
configureMonacoEnvironment();
53-
54-
// 2. Actually download the library
5517
const monaco = await import('monaco-editor');
56-
57-
// 3. Configure the loader with the downloaded instance
5818
loader.config({ monaco });
59-
60-
// 4. Wait for the loader to initialize fully
61-
await loader.init();
19+
const instance = await loader.init();
6220

6321
if (isMounted) {
22+
const style = getComputedStyle(document.documentElement);
23+
const accent = style.getPropertyValue('--accent-1').trim() || '#59c0c0';
24+
25+
// 1. Define Dark Theme
26+
instance.editor.defineTheme('omni-dark', {
27+
base: 'vs-dark',
28+
inherit: true,
29+
rules: [],
30+
colors: {
31+
'editor.background': '#33333f', // Hardcoded fallbacks prevent empty flashes
32+
'editorCursor.foreground': accent,
33+
'editor.selectionBackground': `${accent}33`,
34+
},
35+
});
36+
37+
// 2. Define Light Theme
38+
instance.editor.defineTheme('omni-light', {
39+
base: 'vs',
40+
inherit: true,
41+
rules: [],
42+
colors: {
43+
'editor.background': '#e8e8e8',
44+
'editorCursor.foreground': accent,
45+
'editor.selectionBackground': `${accent}33`,
46+
},
47+
});
48+
49+
monacoRef.current = instance;
6450
setIsReady(true);
6551
}
6652
};
@@ -69,54 +55,40 @@ const MonacoEditor = ({
6955
return () => { isMounted = false; };
7056
}, []);
7157

72-
const handleEditorWillMount = (monaco) => {
73-
monaco.editor.defineTheme('omni-dark', {
74-
base: 'vs-dark',
75-
inherit: true,
76-
rules: [],
77-
colors: {
78-
'editor.background': '#33333f', // OmniBlocks background
79-
'editorCursor.foreground': '#59c0c0',
80-
'editor.lineHighlightBackground': '#3e3e4a',
81-
'editor.selectionBackground': '#59c0c033',
82-
},
58+
// 3. Observer: Only calls setTheme (Much lighter than defineTheme)
59+
useEffect(() => {
60+
if (!isReady || !monacoRef.current) return;
61+
62+
const observer = new MutationObserver(() => {
63+
monacoRef.current.editor.setTheme(getThemeName());
64+
});
65+
66+
observer.observe(document.documentElement, {
67+
attributes: true,
68+
attributeFilter: ['class'],
8369
});
84-
};
85-
86-
const handleEditorDidMount = (editor) => {
87-
editorRef.current = editor;
88-
};
89-
90-
// We return the "Loading..." state manually until the JS is downloaded and initialized
91-
if (!isReady) {
92-
return (
93-
<div style={{
94-
height: '100%',
95-
width: '100%',
96-
background: '#33333f',
97-
}}>
98-
</div>
99-
);
100-
}
70+
71+
// Set initial theme
72+
monacoRef.current.editor.setTheme(getThemeName());
73+
74+
return () => observer.disconnect();
75+
}, [isReady]);
76+
77+
if (!isReady) return <div style={{ height: '100%', background: 'var(--page-background)' }} />;
10178

10279
return (
103-
<div style={{ height: '100%', width: '100%', background: '#33333f' }}>
80+
<div style={{ height: '100%', width: '100%' }}>
10481
<Editor
10582
height="100%"
10683
language={language}
10784
value={value}
108-
theme={theme}
85+
theme={getThemeName()}
10986
onChange={onChange}
110-
onMount={handleEditorDidMount}
111-
beforeMount={handleEditorWillMount}
11287
options={{
11388
automaticLayout: true,
11489
fontSize: 13,
115-
fontFamily: "var(--font-mono, 'Fira Code', monospace)",
11690
minimap: { enabled: false },
11791
scrollBeyondLastLine: false,
118-
fixedOverflowWidgets: true,
119-
padding: { top: 8 }
12092
}}
12193
/>
12294
</div>

src/main.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { StrictMode } from 'react';
22
import { createRoot } from 'react-dom/client';
33
import 'modern-normalize';
44
import './index.css';
5+
import './globalstyles/colors.css';
56
import { LayoutProvider } from './hooks/useOmniLayout';
67
import { OmniLayout } from './lib/Layout';
78
import { CorePlugin } from './plugins/corePlugin';

0 commit comments

Comments
 (0)